@gradial/aci 0.1.20-preview.3 → 0.1.21

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 (227) hide show
  1. package/README.md +48 -108
  2. package/bin/{aci → aci-darwin-arm64} +0 -0
  3. package/bin/aci.js +99 -6
  4. package/dist/assets/index.d.ts +3 -3
  5. package/dist/assets/index.js +3 -3
  6. package/dist/astro/index.d.ts +12 -3
  7. package/dist/astro/index.js +20 -5
  8. package/dist/content/assets.d.ts +17 -0
  9. package/dist/content/assets.js +65 -0
  10. package/dist/content/index.d.ts +1 -0
  11. package/dist/content/index.js +1 -0
  12. package/dist/define-component.d.ts +1 -2
  13. package/dist/define-component.js +73 -5
  14. package/dist/dev/content-watch.d.ts +37 -0
  15. package/dist/dev/content-watch.js +154 -0
  16. package/dist/dev/index.d.ts +24 -43
  17. package/dist/dev/index.js +4 -169
  18. package/dist/index.d.ts +14 -6
  19. package/dist/index.js +8 -9
  20. package/dist/next/asset-route.js +2 -2
  21. package/dist/next/config.d.ts +2 -2
  22. package/dist/next/config.js +5 -5
  23. package/dist/next/content-watch.js +6 -1
  24. package/dist/next/index.d.ts +2 -2
  25. package/dist/next/index.js +2 -2
  26. package/dist/next/middleware.d.ts +1 -0
  27. package/dist/next/middleware.js +49 -8
  28. package/dist/next/page.d.ts +1 -1
  29. package/dist/next/page.js +14 -12
  30. package/dist/next/render.d.ts +3 -3
  31. package/dist/next/render.js +11 -9
  32. package/dist/next/server.d.ts +12 -12
  33. package/dist/next/server.js +1 -1
  34. package/dist/preview/core.d.ts +5 -0
  35. package/dist/preview/core.js +1 -1
  36. package/dist/react/Media.d.ts +24 -0
  37. package/dist/react/Media.js +30 -0
  38. package/dist/react/Picture.d.ts +12 -0
  39. package/dist/react/Picture.js +11 -0
  40. package/dist/react/VideoPlayer.d.ts +13 -0
  41. package/dist/react/{GradialVideoPlayer.js → VideoPlayer.js} +6 -5
  42. package/dist/react/index.d.ts +333 -3
  43. package/dist/react/index.js +89 -3
  44. package/dist/registry.d.ts +2 -2
  45. package/dist/registry.js +3 -3
  46. package/dist/types/block-ref.d.ts +26 -0
  47. package/dist/types/block-ref.js +28 -0
  48. package/dist/types/component.d.ts +36 -32
  49. package/dist/types/config.d.ts +1 -1
  50. package/dist/types/image.d.ts +33 -20
  51. package/dist/types/image.js +42 -50
  52. package/dist/types/index.d.ts +1 -0
  53. package/dist/types/index.js +1 -0
  54. package/dist/types/link.d.ts +38 -0
  55. package/dist/types/link.js +58 -0
  56. package/dist/types/media.d.ts +16 -35
  57. package/dist/types/media.js +15 -84
  58. package/dist/types/renderer.d.ts +1 -1
  59. package/dist/types/rich-text.d.ts +40 -0
  60. package/dist/types/rich-text.js +39 -0
  61. package/dist/types/video.d.ts +7 -13
  62. package/dist/types/video.js +3 -3
  63. package/package.json +29 -76
  64. package/src/cli/compile-registry.mjs +120 -63
  65. package/src/cli/validate-content.mjs +38 -75
  66. package/src/types/block-ref.ts +74 -0
  67. package/src/types/image.ts +79 -60
  68. package/templates/astro/template/.aci.yaml +28 -0
  69. package/templates/astro/template/.storybook/main.ts +79 -0
  70. package/templates/astro/template/.storybook/manager.ts +6 -0
  71. package/templates/astro/template/.storybook/preview.ts +33 -0
  72. package/templates/astro/template/astro.config.mjs +37 -0
  73. package/templates/astro/template/package.json.tmpl +41 -0
  74. package/templates/astro/template/src/cms/contracts/layouts/index.ts +18 -0
  75. package/templates/astro/template/src/cms/registry.ts +28 -0
  76. package/templates/astro/template/src/components/chrome/Footer.astro +107 -0
  77. package/templates/astro/template/src/components/chrome/Header.astro +94 -0
  78. package/templates/astro/template/src/components/elements/AtomicBlock.astro +15 -0
  79. package/templates/astro/template/src/components/elements/AtomicBlocks.astro +16 -0
  80. package/templates/astro/template/src/components/elements/Button.astro +51 -0
  81. package/templates/astro/template/src/components/elements/ButtonBlock.astro +25 -0
  82. package/templates/astro/template/src/components/elements/Container.astro +11 -0
  83. package/templates/astro/template/src/components/elements/Icon.astro +31 -0
  84. package/templates/astro/template/src/components/elements/Logo.astro +29 -0
  85. package/templates/astro/template/src/components/elements/RemoteImage.astro +41 -0
  86. package/templates/astro/template/src/components/sections/ContainerSection.astro +32 -0
  87. package/templates/astro/template/src/components/sections/FeatureCard.astro +23 -0
  88. package/templates/astro/template/src/components/sections/FeatureGrid.astro +35 -0
  89. package/templates/astro/template/src/components/sections/HomeHero.astro +51 -0
  90. package/templates/astro/template/src/components/sections/StatsBar.astro +33 -0
  91. package/templates/astro/template/src/design-system/styles.css +399 -0
  92. package/templates/astro/template/src/design-system/tokens/colors.css +60 -0
  93. package/templates/astro/template/src/design-system/tokens/components.css +69 -0
  94. package/templates/astro/template/src/design-system/tokens/index.css +6 -0
  95. package/templates/astro/template/src/design-system/tokens/radii.css +5 -0
  96. package/templates/astro/template/src/design-system/tokens/shadows.css +5 -0
  97. package/templates/astro/template/src/design-system/tokens/spacing.css +13 -0
  98. package/templates/astro/template/src/design-system/tokens/typography.css +24 -0
  99. package/templates/astro/template/src/env.d.ts +1 -0
  100. package/templates/astro/template/src/fixtures/atomicBlocks.ts +33 -0
  101. package/templates/astro/template/src/fixtures/composition.ts +31 -0
  102. package/templates/astro/template/src/fixtures/index.ts +17 -0
  103. package/templates/astro/template/src/fixtures/sections.ts +39 -0
  104. package/templates/astro/template/src/layouts/SiteLayout.astro +30 -0
  105. package/templates/astro/template/src/pages/[...slug].astro +61 -0
  106. package/templates/astro/template/src/render/RenderPage.astro +66 -0
  107. package/templates/astro/template/src/stories/CompositionStoryFrame.astro +15 -0
  108. package/templates/astro/template/src/stories/HomeHero.stories.ts +24 -0
  109. package/templates/astro/template/src/stories/SectionStoryFrame.astro +16 -0
  110. package/templates/astro/template/src/stories/StoryDocFrame.astro +31 -0
  111. package/templates/astro/template/tsconfig.json +11 -0
  112. package/templates/common/.agents/AGENTS.md +37 -0
  113. package/templates/common/.agents/skills/aci/SKILL.md +162 -0
  114. package/templates/common/.agents/skills/authoring/SKILL.md +590 -0
  115. package/templates/common/.agents/skills/authoring/references/block-registry.md +151 -0
  116. package/templates/common/.agents/skills/authoring/references/contracts.md +153 -0
  117. package/templates/common/.agents/skills/authoring/references/design-system.md +171 -0
  118. package/templates/common/.agents/skills/authoring/references/image-assets.md +73 -0
  119. package/templates/common/.agents/skills/authoring/references/repo-structure.md +157 -0
  120. package/templates/common/.agents/skills/migration/SKILL.md +160 -0
  121. package/templates/common/.agents/skills/migration/references/analyzing-source.md +215 -0
  122. package/templates/common/.agents/skills/migration/references/component-migration.md +200 -0
  123. package/templates/common/.agents/skills/migration/references/selector-map.md +31 -0
  124. package/templates/common/.content/.gradial-dam/blobs/sha256/7f/bf/7fbfc7fe230ff12688c496f660119e41d9725c4504d82e310c15665c73c09292 +0 -0
  125. package/templates/common/.content/.gradial-dam/blobs/sha256/a0/f5/a0f506689de9b15a7055f70103a3f02cd3ba105771ae2de6754df2ede1210d3a +0 -0
  126. package/templates/common/.content/.gradial-dam/blobs/sha256/dd/b7/ddb7e9642be08317bcd4b2bd26b58ba8d0d34dd7239e03e684a4f3634fa3845b +0 -0
  127. package/templates/common/.content/.gradial-dam/blobs/sha256/fb/32/fb3260e8286ea8231ea1c77b9c0be92d6edd9026565731eb14cfdcfd6b1b75b3 +0 -0
  128. package/templates/common/.content/config/site.json +192 -0
  129. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/asset.json +9 -0
  130. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/editorial.json +14 -0
  131. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/governance.json +23 -0
  132. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/versions/v0001.json +37 -0
  133. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/asset.json +9 -0
  134. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/editorial.json +14 -0
  135. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/governance.json +23 -0
  136. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/versions/v0001.json +37 -0
  137. package/templates/common/.content/fragments/navbar/_index.json +25 -0
  138. package/templates/common/.content/fragments/site-footer/_index.json +62 -0
  139. package/templates/common/.content/pages/about/_index.json +51 -0
  140. package/templates/common/.content/pages/home/_index.json +112 -0
  141. package/templates/common/.content/schemas/site.schema.json +123 -0
  142. package/templates/common/README.md.tmpl +45 -0
  143. package/templates/common/contracts/components/button.contract.ts +19 -0
  144. package/templates/common/contracts/components/container.contract.ts +19 -0
  145. package/templates/common/contracts/components/featureCard.contract.ts +15 -0
  146. package/templates/common/contracts/components/featureGrid.contract.ts +16 -0
  147. package/templates/common/contracts/components/homeHero.contract.ts +36 -0
  148. package/templates/common/contracts/components/index.ts +21 -0
  149. package/templates/common/contracts/components/siteFooter.contract.ts +45 -0
  150. package/templates/common/contracts/components/siteNavigation.contract.ts +30 -0
  151. package/templates/common/contracts/components/statsBar.contract.ts +19 -0
  152. package/templates/common/design-system/styles.css +346 -0
  153. package/templates/common/design-system/tokens/colors.css +110 -0
  154. package/templates/common/design-system/tokens/components.css +86 -0
  155. package/templates/common/design-system/tokens/index.css +6 -0
  156. package/templates/common/design-system/tokens/radii.css +5 -0
  157. package/templates/common/design-system/tokens/shadows.css +9 -0
  158. package/templates/common/design-system/tokens/spacing.css +26 -0
  159. package/templates/common/design-system/tokens/typography.css +32 -0
  160. package/templates/common/eslint-rules/no-raw-tailwind-values.js +127 -0
  161. package/templates/common/public/assets/Dwire-model.png +0 -0
  162. package/templates/common/public/assets/bare-metal-logo.png +0 -0
  163. package/templates/common/public/assets/meridian-logo.svg +8 -0
  164. package/templates/common/public/assets/seattle.avif +0 -0
  165. package/templates/nextjs/template/.aci.yaml +26 -0
  166. package/templates/nextjs/template/.storybook/main.ts +13 -0
  167. package/templates/nextjs/template/.storybook/preview.ts +34 -0
  168. package/templates/nextjs/template/eslint.config.mjs +36 -0
  169. package/templates/nextjs/template/next-env.d.ts +6 -0
  170. package/templates/nextjs/template/next.config.ts +8 -0
  171. package/templates/nextjs/template/package.json.tmpl +46 -0
  172. package/templates/nextjs/template/postcss.config.mjs +7 -0
  173. package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +8 -0
  174. package/templates/nextjs/template/src/app/gradial/assets/[releaseId]/[...path]/route.ts +31 -0
  175. package/templates/nextjs/template/src/app/layout.tsx +29 -0
  176. package/templates/nextjs/template/src/cms/contracts/components/button.contract.ts +19 -0
  177. package/templates/nextjs/template/src/cms/contracts/components/container.contract.ts +20 -0
  178. package/templates/nextjs/template/src/cms/contracts/components/homeHero.contract.ts +36 -0
  179. package/templates/nextjs/template/src/cms/contracts/components/index.ts +15 -0
  180. package/templates/nextjs/template/src/cms/contracts/components/siteFooter.contract.ts +45 -0
  181. package/templates/nextjs/template/src/cms/contracts/components/siteNavigation.contract.ts +30 -0
  182. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +16 -0
  183. package/templates/nextjs/template/src/cms/registry.ts +28 -0
  184. package/templates/nextjs/template/src/components/chrome/Footer.tsx +86 -0
  185. package/templates/nextjs/template/src/components/chrome/Header.tsx +74 -0
  186. package/templates/nextjs/template/src/components/elements/AtomicBlock.tsx +13 -0
  187. package/templates/nextjs/template/src/components/elements/Button.tsx +40 -0
  188. package/templates/nextjs/template/src/components/elements/ButtonBlock.tsx +18 -0
  189. package/templates/nextjs/template/src/components/elements/Container.tsx +14 -0
  190. package/templates/nextjs/template/src/components/elements/Icon.tsx +29 -0
  191. package/templates/nextjs/template/src/components/elements/Logo.tsx +38 -0
  192. package/templates/nextjs/template/src/components/sections/ContainerSection.tsx +28 -0
  193. package/templates/nextjs/template/src/components/sections/FeatureCard.tsx +25 -0
  194. package/templates/nextjs/template/src/components/sections/FeatureGrid.tsx +36 -0
  195. package/templates/nextjs/template/src/components/sections/HomeHero.tsx +62 -0
  196. package/templates/nextjs/template/src/components/sections/StatsBar.tsx +30 -0
  197. package/templates/nextjs/template/src/middleware.ts +4 -0
  198. package/templates/nextjs/template/src/stories/Button.stories.tsx +38 -0
  199. package/templates/nextjs/template/src/stories/Header.stories.tsx +30 -0
  200. package/templates/nextjs/template/src/stories/HomeHero.stories.tsx +33 -0
  201. package/templates/nextjs/template/tsconfig.json +23 -0
  202. package/templates/nextjs/template/vercel.json +6 -0
  203. package/dist/content/contract.d.ts +0 -83
  204. package/dist/content/contract.js +0 -104
  205. package/dist/content/tailwind-validator.d.ts +0 -6
  206. package/dist/content/tailwind-validator.js +0 -31
  207. package/dist/content/validation.d.ts +0 -108
  208. package/dist/content/validation.js +0 -183
  209. package/dist/react/GradialMedia.d.ts +0 -24
  210. package/dist/react/GradialMedia.js +0 -31
  211. package/dist/react/GradialPicture.d.ts +0 -14
  212. package/dist/react/GradialPicture.js +0 -30
  213. package/dist/react/GradialVideoPlayer.d.ts +0 -13
  214. package/dist/sveltekit/index.d.ts +0 -25
  215. package/dist/sveltekit/index.js +0 -66
  216. package/dist/sveltekit/preview.d.ts +0 -5
  217. package/dist/sveltekit/preview.js +0 -33
  218. package/src/types/component.ts +0 -49
  219. package/src/types/config.ts +0 -37
  220. package/src/types/data.ts +0 -47
  221. package/src/types/index.ts +0 -10
  222. package/src/types/layout.ts +0 -29
  223. package/src/types/media.ts +0 -125
  224. package/src/types/page.ts +0 -47
  225. package/src/types/render-mode.ts +0 -10
  226. package/src/types/renderer.ts +0 -83
  227. package/src/types/video.ts +0 -66
@@ -1,3 +1,333 @@
1
- export { GradialPicture } from './GradialPicture.js';
2
- export { GradialVideoPlayer } from './GradialVideoPlayer.js';
3
- export { GradialMedia } from './GradialMedia.js';
1
+ import { type ImgHTMLAttributes, type ReactElement, type ReactNode } from 'react';
2
+ import { type Image as ImageData } from '../types/image.js';
3
+ import { type Link as LinkData } from '../types/link.js';
4
+ import type { Heading as HeadingData, RichTextValue } from '../types/rich-text.js';
5
+ import type { BlockRef } from '../types/block-ref.js';
6
+ export { Picture, type PictureProps } from './Picture.js';
7
+ export { Media, type MediaProps } from './Media.js';
8
+ export { VideoPlayer, type VideoPlayerProps } from './VideoPlayer.js';
9
+ export type RenderChildren<T extends readonly BlockRef[]> = (blocks: T) => Promise<ReactElement[]>;
10
+ export interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'alt'> {
11
+ image?: ImageData;
12
+ value?: ImageData;
13
+ }
14
+ export declare function Image({ image, value, ...attrs }: ImageProps): import("react").DetailedReactHTMLElement<import("../types/image.js").ImageAttrs, HTMLElement> | import("react").DetailedReactHTMLElement<{
15
+ prefix?: string | undefined | undefined;
16
+ id?: string | undefined | undefined;
17
+ width?: number | string | undefined | undefined;
18
+ height?: number | string | undefined | undefined;
19
+ srcSet?: string | undefined | undefined;
20
+ sizes?: string | undefined | undefined;
21
+ loading?: "eager" | "lazy" | undefined | undefined;
22
+ decoding?: "async" | "auto" | "sync" | undefined | undefined;
23
+ title?: string | undefined | undefined;
24
+ rel?: string | undefined | undefined;
25
+ content?: string | undefined | undefined;
26
+ dir?: string | undefined | undefined;
27
+ children?: ReactNode;
28
+ className?: string | undefined | undefined;
29
+ crossOrigin?: "" | "anonymous" | "use-credentials" | undefined;
30
+ fetchPriority?: "high" | "low" | "auto" | undefined | undefined;
31
+ referrerPolicy?: import("react").HTMLAttributeReferrerPolicy | undefined;
32
+ useMap?: string | undefined | undefined;
33
+ defaultChecked?: boolean | undefined | undefined;
34
+ defaultValue?: string | number | readonly string[] | undefined;
35
+ suppressContentEditableWarning?: boolean | undefined | undefined;
36
+ suppressHydrationWarning?: boolean | undefined | undefined;
37
+ accessKey?: string | undefined | undefined;
38
+ autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | (string & {}) | undefined;
39
+ autoFocus?: boolean | undefined | undefined;
40
+ contentEditable?: "inherit" | (boolean | "true" | "false") | "plaintext-only" | undefined;
41
+ contextMenu?: string | undefined | undefined;
42
+ draggable?: (boolean | "true" | "false") | undefined;
43
+ enterKeyHint?: "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | undefined | undefined;
44
+ hidden?: boolean | undefined | undefined;
45
+ lang?: string | undefined | undefined;
46
+ nonce?: string | undefined | undefined;
47
+ slot?: string | undefined | undefined;
48
+ spellCheck?: (boolean | "true" | "false") | undefined;
49
+ style?: import("react").CSSProperties | undefined;
50
+ tabIndex?: number | undefined | undefined;
51
+ translate?: "yes" | "no" | undefined | undefined;
52
+ radioGroup?: string | undefined | undefined;
53
+ role?: import("react").AriaRole | undefined;
54
+ about?: string | undefined | undefined;
55
+ datatype?: string | undefined | undefined;
56
+ inlist?: any;
57
+ property?: string | undefined | undefined;
58
+ resource?: string | undefined | undefined;
59
+ rev?: string | undefined | undefined;
60
+ typeof?: string | undefined | undefined;
61
+ vocab?: string | undefined | undefined;
62
+ autoCorrect?: string | undefined | undefined;
63
+ autoSave?: string | undefined | undefined;
64
+ color?: string | undefined | undefined;
65
+ itemProp?: string | undefined | undefined;
66
+ itemScope?: boolean | undefined | undefined;
67
+ itemType?: string | undefined | undefined;
68
+ itemID?: string | undefined | undefined;
69
+ itemRef?: string | undefined | undefined;
70
+ results?: number | undefined | undefined;
71
+ security?: string | undefined | undefined;
72
+ unselectable?: "on" | "off" | undefined | undefined;
73
+ popover?: "" | "auto" | "manual" | "hint" | undefined | undefined;
74
+ popoverTargetAction?: "toggle" | "show" | "hide" | undefined | undefined;
75
+ popoverTarget?: string | undefined | undefined;
76
+ inert?: boolean | undefined | undefined;
77
+ inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined | undefined;
78
+ is?: string | undefined | undefined;
79
+ exportparts?: string | undefined | undefined;
80
+ part?: string | undefined | undefined;
81
+ tw?: string | undefined;
82
+ "aria-activedescendant"?: string | undefined | undefined;
83
+ "aria-atomic"?: (boolean | "true" | "false") | undefined;
84
+ "aria-autocomplete"?: "none" | "inline" | "list" | "both" | undefined | undefined;
85
+ "aria-braillelabel"?: string | undefined | undefined;
86
+ "aria-brailleroledescription"?: string | undefined | undefined;
87
+ "aria-busy"?: (boolean | "true" | "false") | undefined;
88
+ "aria-checked"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
89
+ "aria-colcount"?: number | undefined | undefined;
90
+ "aria-colindex"?: number | undefined | undefined;
91
+ "aria-colindextext"?: string | undefined | undefined;
92
+ "aria-colspan"?: number | undefined | undefined;
93
+ "aria-controls"?: string | undefined | undefined;
94
+ "aria-current"?: boolean | "false" | "true" | "page" | "step" | "location" | "date" | "time" | undefined | undefined;
95
+ "aria-describedby"?: string | undefined | undefined;
96
+ "aria-description"?: string | undefined | undefined;
97
+ "aria-details"?: string | undefined | undefined;
98
+ "aria-disabled"?: (boolean | "true" | "false") | undefined;
99
+ "aria-dropeffect"?: "none" | "copy" | "execute" | "link" | "move" | "popup" | undefined | undefined;
100
+ "aria-errormessage"?: string | undefined | undefined;
101
+ "aria-expanded"?: (boolean | "true" | "false") | undefined;
102
+ "aria-flowto"?: string | undefined | undefined;
103
+ "aria-grabbed"?: (boolean | "true" | "false") | undefined;
104
+ "aria-haspopup"?: boolean | "false" | "true" | "menu" | "listbox" | "tree" | "grid" | "dialog" | undefined | undefined;
105
+ "aria-hidden"?: (boolean | "true" | "false") | undefined;
106
+ "aria-invalid"?: boolean | "false" | "true" | "grammar" | "spelling" | undefined | undefined;
107
+ "aria-keyshortcuts"?: string | undefined | undefined;
108
+ "aria-label"?: string | undefined | undefined;
109
+ "aria-labelledby"?: string | undefined | undefined;
110
+ "aria-level"?: number | undefined | undefined;
111
+ "aria-live"?: "off" | "assertive" | "polite" | undefined | undefined;
112
+ "aria-modal"?: (boolean | "true" | "false") | undefined;
113
+ "aria-multiline"?: (boolean | "true" | "false") | undefined;
114
+ "aria-multiselectable"?: (boolean | "true" | "false") | undefined;
115
+ "aria-orientation"?: "horizontal" | "vertical" | undefined | undefined;
116
+ "aria-owns"?: string | undefined | undefined;
117
+ "aria-placeholder"?: string | undefined | undefined;
118
+ "aria-posinset"?: number | undefined | undefined;
119
+ "aria-pressed"?: boolean | "false" | "mixed" | "true" | undefined | undefined;
120
+ "aria-readonly"?: (boolean | "true" | "false") | undefined;
121
+ "aria-relevant"?: "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined | undefined;
122
+ "aria-required"?: (boolean | "true" | "false") | undefined;
123
+ "aria-roledescription"?: string | undefined | undefined;
124
+ "aria-rowcount"?: number | undefined | undefined;
125
+ "aria-rowindex"?: number | undefined | undefined;
126
+ "aria-rowindextext"?: string | undefined | undefined;
127
+ "aria-rowspan"?: number | undefined | undefined;
128
+ "aria-selected"?: (boolean | "true" | "false") | undefined;
129
+ "aria-setsize"?: number | undefined | undefined;
130
+ "aria-sort"?: "none" | "ascending" | "descending" | "other" | undefined | undefined;
131
+ "aria-valuemax"?: number | undefined | undefined;
132
+ "aria-valuemin"?: number | undefined | undefined;
133
+ "aria-valuenow"?: number | undefined | undefined;
134
+ "aria-valuetext"?: string | undefined | undefined;
135
+ dangerouslySetInnerHTML?: {
136
+ __html: string | TrustedHTML;
137
+ } | undefined | undefined;
138
+ onCopy?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
139
+ onCopyCapture?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
140
+ onCut?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
141
+ onCutCapture?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
142
+ onPaste?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
143
+ onPasteCapture?: import("react").ClipboardEventHandler<HTMLImageElement> | undefined;
144
+ onCompositionEnd?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
145
+ onCompositionEndCapture?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
146
+ onCompositionStart?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
147
+ onCompositionStartCapture?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
148
+ onCompositionUpdate?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
149
+ onCompositionUpdateCapture?: import("react").CompositionEventHandler<HTMLImageElement> | undefined;
150
+ onFocus?: import("react").FocusEventHandler<HTMLImageElement> | undefined;
151
+ onFocusCapture?: import("react").FocusEventHandler<HTMLImageElement> | undefined;
152
+ onBlur?: import("react").FocusEventHandler<HTMLImageElement> | undefined;
153
+ onBlurCapture?: import("react").FocusEventHandler<HTMLImageElement> | undefined;
154
+ onChange?: import("react").ChangeEventHandler<HTMLImageElement, Element> | undefined;
155
+ onChangeCapture?: import("react").ChangeEventHandler<HTMLImageElement, Element> | undefined;
156
+ onBeforeInput?: import("react").InputEventHandler<HTMLImageElement> | undefined;
157
+ onBeforeInputCapture?: import("react").InputEventHandler<HTMLImageElement> | undefined;
158
+ onInput?: import("react").InputEventHandler<HTMLImageElement> | undefined;
159
+ onInputCapture?: import("react").InputEventHandler<HTMLImageElement> | undefined;
160
+ onReset?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
161
+ onResetCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
162
+ onSubmit?: import("react").SubmitEventHandler<HTMLImageElement> | undefined;
163
+ onSubmitCapture?: import("react").SubmitEventHandler<HTMLImageElement> | undefined;
164
+ onInvalid?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
165
+ onInvalidCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
166
+ onLoad?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
167
+ onLoadCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
168
+ onError?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
169
+ onErrorCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
170
+ onKeyDown?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
171
+ onKeyDownCapture?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
172
+ onKeyPress?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
173
+ onKeyPressCapture?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
174
+ onKeyUp?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
175
+ onKeyUpCapture?: import("react").KeyboardEventHandler<HTMLImageElement> | undefined;
176
+ onAbort?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
177
+ onAbortCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
178
+ onCanPlay?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
179
+ onCanPlayCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
180
+ onCanPlayThrough?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
181
+ onCanPlayThroughCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
182
+ onDurationChange?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
183
+ onDurationChangeCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
184
+ onEmptied?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
185
+ onEmptiedCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
186
+ onEncrypted?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
187
+ onEncryptedCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
188
+ onEnded?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
189
+ onEndedCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
190
+ onLoadedData?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
191
+ onLoadedDataCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
192
+ onLoadedMetadata?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
193
+ onLoadedMetadataCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
194
+ onLoadStart?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
195
+ onLoadStartCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
196
+ onPause?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
197
+ onPauseCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
198
+ onPlay?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
199
+ onPlayCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
200
+ onPlaying?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
201
+ onPlayingCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
202
+ onProgress?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
203
+ onProgressCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
204
+ onRateChange?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
205
+ onRateChangeCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
206
+ onSeeked?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
207
+ onSeekedCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
208
+ onSeeking?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
209
+ onSeekingCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
210
+ onStalled?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
211
+ onStalledCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
212
+ onSuspend?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
213
+ onSuspendCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
214
+ onTimeUpdate?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
215
+ onTimeUpdateCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
216
+ onVolumeChange?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
217
+ onVolumeChangeCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
218
+ onWaiting?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
219
+ onWaitingCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
220
+ onAuxClick?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
221
+ onAuxClickCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
222
+ onClick?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
223
+ onClickCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
224
+ onContextMenu?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
225
+ onContextMenuCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
226
+ onDoubleClick?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
227
+ onDoubleClickCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
228
+ onDrag?: import("react").DragEventHandler<HTMLImageElement> | undefined;
229
+ onDragCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
230
+ onDragEnd?: import("react").DragEventHandler<HTMLImageElement> | undefined;
231
+ onDragEndCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
232
+ onDragEnter?: import("react").DragEventHandler<HTMLImageElement> | undefined;
233
+ onDragEnterCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
234
+ onDragExit?: import("react").DragEventHandler<HTMLImageElement> | undefined;
235
+ onDragExitCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
236
+ onDragLeave?: import("react").DragEventHandler<HTMLImageElement> | undefined;
237
+ onDragLeaveCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
238
+ onDragOver?: import("react").DragEventHandler<HTMLImageElement> | undefined;
239
+ onDragOverCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
240
+ onDragStart?: import("react").DragEventHandler<HTMLImageElement> | undefined;
241
+ onDragStartCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
242
+ onDrop?: import("react").DragEventHandler<HTMLImageElement> | undefined;
243
+ onDropCapture?: import("react").DragEventHandler<HTMLImageElement> | undefined;
244
+ onMouseDown?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
245
+ onMouseDownCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
246
+ onMouseEnter?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
247
+ onMouseLeave?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
248
+ onMouseMove?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
249
+ onMouseMoveCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
250
+ onMouseOut?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
251
+ onMouseOutCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
252
+ onMouseOver?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
253
+ onMouseOverCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
254
+ onMouseUp?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
255
+ onMouseUpCapture?: import("react").MouseEventHandler<HTMLImageElement> | undefined;
256
+ onSelect?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
257
+ onSelectCapture?: import("react").ReactEventHandler<HTMLImageElement> | undefined;
258
+ onTouchCancel?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
259
+ onTouchCancelCapture?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
260
+ onTouchEnd?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
261
+ onTouchEndCapture?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
262
+ onTouchMove?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
263
+ onTouchMoveCapture?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
264
+ onTouchStart?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
265
+ onTouchStartCapture?: import("react").TouchEventHandler<HTMLImageElement> | undefined;
266
+ onPointerDown?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
267
+ onPointerDownCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
268
+ onPointerMove?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
269
+ onPointerMoveCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
270
+ onPointerUp?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
271
+ onPointerUpCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
272
+ onPointerCancel?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
273
+ onPointerCancelCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
274
+ onPointerEnter?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
275
+ onPointerLeave?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
276
+ onPointerOver?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
277
+ onPointerOverCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
278
+ onPointerOut?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
279
+ onPointerOutCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
280
+ onGotPointerCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
281
+ onGotPointerCaptureCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
282
+ onLostPointerCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
283
+ onLostPointerCaptureCapture?: import("react").PointerEventHandler<HTMLImageElement> | undefined;
284
+ onScroll?: import("react").UIEventHandler<HTMLImageElement> | undefined;
285
+ onScrollCapture?: import("react").UIEventHandler<HTMLImageElement> | undefined;
286
+ onScrollEnd?: import("react").UIEventHandler<HTMLImageElement> | undefined;
287
+ onScrollEndCapture?: import("react").UIEventHandler<HTMLImageElement> | undefined;
288
+ onWheel?: import("react").WheelEventHandler<HTMLImageElement> | undefined;
289
+ onWheelCapture?: import("react").WheelEventHandler<HTMLImageElement> | undefined;
290
+ onAnimationStart?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
291
+ onAnimationStartCapture?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
292
+ onAnimationEnd?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
293
+ onAnimationEndCapture?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
294
+ onAnimationIteration?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
295
+ onAnimationIterationCapture?: import("react").AnimationEventHandler<HTMLImageElement> | undefined;
296
+ onToggle?: import("react").ToggleEventHandler<HTMLImageElement> | undefined;
297
+ onBeforeToggle?: import("react").ToggleEventHandler<HTMLImageElement> | undefined;
298
+ onTransitionCancel?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
299
+ onTransitionCancelCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
300
+ onTransitionEnd?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
301
+ onTransitionEndCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
302
+ onTransitionRun?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
303
+ onTransitionRunCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
304
+ onTransitionStart?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
305
+ onTransitionStartCapture?: import("react").TransitionEventHandler<HTMLImageElement> | undefined;
306
+ src: string;
307
+ alt: string;
308
+ }, HTMLElement>;
309
+ export interface LinkProps {
310
+ link: LinkData;
311
+ resolveLink?: (link: LinkData) => string | Promise<string>;
312
+ children?: ReactNode;
313
+ }
314
+ export declare function Link({ link, resolveLink, children }: LinkProps): import("react").DetailedReactHTMLElement<{
315
+ href: string | Promise<string>;
316
+ target: import("../types/link.js").LinkTarget | undefined;
317
+ rel: string | undefined;
318
+ title: string | undefined;
319
+ }, HTMLElement>;
320
+ export interface HeadingProps {
321
+ heading?: HeadingData;
322
+ value?: HeadingData;
323
+ }
324
+ export declare function Heading({ heading, value }: HeadingProps): import("react").DetailedReactHTMLElement<import("react").HTMLAttributes<HTMLElement>, HTMLElement> | null;
325
+ export declare function headingPlainText(value: HeadingData): string;
326
+ export interface RichTextProps {
327
+ value: RichTextValue | string;
328
+ }
329
+ export declare function RichText({ value }: RichTextProps): import("react").DetailedReactHTMLElement<{
330
+ dangerouslySetInnerHTML: {
331
+ __html: string;
332
+ };
333
+ }, HTMLElement>;
@@ -1,3 +1,89 @@
1
- export { GradialPicture } from './GradialPicture.js';
2
- export { GradialVideoPlayer } from './GradialVideoPlayer.js';
3
- export { GradialMedia } from './GradialMedia.js';
1
+ import { createElement, Fragment, } from 'react';
2
+ import sanitizeHtml from 'sanitize-html';
3
+ import MarkdownIt from 'markdown-it';
4
+ import { imageAttrs } from '../types/image.js';
5
+ import { resolveHref, normalizeLinkRel, assertSafeHref } from '../types/link.js';
6
+ export { Picture } from './Picture.js';
7
+ export { Media } from './Media.js';
8
+ export { VideoPlayer } from './VideoPlayer.js';
9
+ export function Image({ image, value, ...attrs }) {
10
+ const resolved = image ?? value ?? {
11
+ $type: 'gradial.image',
12
+ assetId: '',
13
+ versionId: '',
14
+ alt: '',
15
+ sources: [],
16
+ };
17
+ if (!resolved.sources.length) {
18
+ return createElement('img', {
19
+ src: '',
20
+ alt: resolved.alt,
21
+ ...attrs,
22
+ });
23
+ }
24
+ return createElement('img', imageAttrs(resolved, attrs));
25
+ }
26
+ export function Link({ link, resolveLink, children }) {
27
+ const href = resolveHref(link, resolveLink);
28
+ if (typeof href === 'string') {
29
+ assertSafeHref(href);
30
+ }
31
+ return createElement('a', {
32
+ href,
33
+ target: link.target,
34
+ rel: normalizeLinkRel(link),
35
+ title: link.title,
36
+ }, children);
37
+ }
38
+ export function Heading({ heading, value }) {
39
+ const resolved = heading ?? value;
40
+ if (!resolved) {
41
+ return null;
42
+ }
43
+ return createElement(`h${resolved.level}`, null, renderInlineContent(resolved.content));
44
+ }
45
+ export function headingPlainText(value) {
46
+ return inlinePlainText(value.content);
47
+ }
48
+ const markdown = new MarkdownIt({ html: false, linkify: true, typographer: true });
49
+ export function RichText({ value }) {
50
+ const richText = typeof value === 'string' ? { format: 'markdown', markdown: value } : value;
51
+ const rendered = richText.format === 'markdown'
52
+ ? markdown.render(richText.markdown)
53
+ : richText.html;
54
+ const clean = sanitizeHtml(rendered, {
55
+ allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img']),
56
+ allowedAttributes: {
57
+ ...sanitizeHtml.defaults.allowedAttributes,
58
+ a: ['href', 'name', 'target', 'rel'],
59
+ img: ['src', 'alt', 'width', 'height', 'loading'],
60
+ },
61
+ transformTags: {
62
+ a: sanitizeHtml.simpleTransform('a', { rel: 'noopener noreferrer' }, true),
63
+ },
64
+ });
65
+ return createElement('div', { dangerouslySetInnerHTML: { __html: clean } });
66
+ }
67
+ function renderInlineContent(content) {
68
+ return content.map((node, index) => {
69
+ const children = 'content' in node ? renderInlineContent(node.content) : node.text;
70
+ switch (node.type) {
71
+ case 'strong':
72
+ return createElement('strong', { key: index }, children);
73
+ case 'em':
74
+ return createElement('em', { key: index }, children);
75
+ case 'link':
76
+ return createElement('a', { key: index, href: node.href }, children);
77
+ case 'span':
78
+ return createElement('span', { key: index, 'data-aci-variant': node.variant }, children);
79
+ case 'text':
80
+ default:
81
+ return createElement(Fragment, { key: index }, children);
82
+ }
83
+ });
84
+ }
85
+ function inlinePlainText(content) {
86
+ return content
87
+ .map((node) => node.type === 'text' ? node.text : inlinePlainText(node.content))
88
+ .join('');
89
+ }
@@ -1,7 +1,7 @@
1
1
  import type { ComponentContract, InferComponentProps } from './types/component.js';
2
2
  export type AnyComponent = (abstract new (...args: any[]) => any) | ((props: any) => any) | Record<string, any>;
3
3
  export interface RegistryEntry {
4
- name: string;
4
+ id: string;
5
5
  component: AnyComponent;
6
6
  contract: ComponentContract;
7
7
  }
@@ -11,5 +11,5 @@ type ValidatedEntries<T extends readonly (readonly [ComponentContract, AnyCompon
11
11
  [K in keyof T]: ValidatedEntry<T[K]>;
12
12
  };
13
13
  export declare function createRegistry<const T extends readonly (readonly [ComponentContract, AnyComponent])[]>(entries: ValidatedEntries<T> & T): Registry;
14
- export declare function registryLookup(registry: Registry, name: string): AnyComponent | undefined;
14
+ export declare function registryLookup(registry: Registry, id: string): AnyComponent | undefined;
15
15
  export {};
package/dist/registry.js CHANGED
@@ -1,10 +1,10 @@
1
1
  export function createRegistry(entries) {
2
2
  return entries.map(([contract, component]) => ({
3
- name: contract.name,
3
+ id: contract.id,
4
4
  component,
5
5
  contract,
6
6
  }));
7
7
  }
8
- export function registryLookup(registry, name) {
9
- return registry.find((r) => r.name === name)?.component;
8
+ export function registryLookup(registry, id) {
9
+ return registry.find((r) => r.id === id)?.component;
10
10
  }
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ import type { ComponentContract } from './component.js';
3
+ export interface BlockRefMeta {
4
+ allowed: readonly string[];
5
+ multiple: boolean;
6
+ }
7
+ declare const blockRefBase: z.ZodObject<{
8
+ id: z.ZodString;
9
+ component: z.ZodString;
10
+ props: z.ZodRecord<z.ZodString, z.ZodUnknown>;
11
+ }, z.core.$strip>;
12
+ type InferContractProps<T> = T extends ComponentContract<string, infer Schema> ? Schema extends z.ZodType<infer P> ? P : Record<string, unknown> : Record<string, unknown>;
13
+ type InferContractId<T> = T extends ComponentContract<infer Id, unknown> ? Id : never;
14
+ export type BlockRefEntry<T extends ComponentContract> = {
15
+ id: string;
16
+ component: InferContractId<T>;
17
+ props: InferContractProps<T>;
18
+ };
19
+ export type BlockRefUnion<T extends readonly ComponentContract[]> = {
20
+ [K in keyof T]: BlockRefEntry<T[K]>;
21
+ }[number];
22
+ export declare function blockRefArray<const T extends readonly ComponentContract[]>(contracts: T): z.ZodArray<z.ZodType<BlockRefUnion<T>>>;
23
+ export declare function blockRef<const T extends readonly ComponentContract[]>(contracts: T): z.ZodType<BlockRefUnion<T>>;
24
+ export declare function getBlockRefMeta(schema: unknown): BlockRefMeta | null;
25
+ export type BlockRef = z.infer<typeof blockRefBase>;
26
+ export {};
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod';
2
+ const BLOCK_REF_KEY = '_gradialBlockRef';
3
+ const blockRefBase = z.object({
4
+ id: z.string().min(1),
5
+ component: z.string().min(1),
6
+ props: z.record(z.string(), z.unknown()),
7
+ });
8
+ function attachMeta(schema, allowed, multiple) {
9
+ Object.defineProperty(schema, BLOCK_REF_KEY, {
10
+ value: { allowed, multiple },
11
+ enumerable: false,
12
+ writable: false,
13
+ configurable: false,
14
+ });
15
+ return schema;
16
+ }
17
+ export function blockRefArray(contracts) {
18
+ return attachMeta(z.array(blockRefBase), contracts.map((c) => c.id), true);
19
+ }
20
+ export function blockRef(contracts) {
21
+ return attachMeta(blockRefBase, contracts.map((c) => c.id), false);
22
+ }
23
+ export function getBlockRefMeta(schema) {
24
+ if (schema && typeof schema === 'object' && BLOCK_REF_KEY in schema) {
25
+ return schema[BLOCK_REF_KEY];
26
+ }
27
+ return null;
28
+ }
@@ -1,39 +1,43 @@
1
- import type { IslandMode, VaryDimension } from './render-mode.js';
2
1
  import type { ImageSlotContract } from './image.js';
2
+ import type { BlockRefMeta } from './block-ref.js';
3
3
  import type { z } from 'zod';
4
- /**
5
- * A CMS-registered component — sync or async (server components).
6
- * Accepts content props derived from the Zod schema.
7
- */
8
- type CmsComponentFn<TProps = any> = ((props: TProps) => import('react').ReactElement | null) | ((props: TProps) => Promise<import('react').ReactElement | null>);
9
- /**
10
- * Infers the props type from a schema.
11
- * If TSchema is a Zod type, returns z.infer<TSchema>.
12
- * Otherwise returns Record<string, unknown>.
13
- */
14
4
  type InferContentProps<TSchema> = TSchema extends z.ZodType<infer T> ? T : Record<string, unknown>;
15
- export interface ComponentDefinition<TSchema = unknown> {
16
- name: string;
17
- /**
18
- * The React component that renders this CMS block.
19
- * Accepts at least the schema-derived props, but may accept additional
20
- * composition params (className, etc.) passed by parent sections.
21
- */
22
- component?: CmsComponentFn<any>;
23
- schema: TSchema;
24
- defaultIslandMode?: IslandMode;
25
- varyDimensions?: VaryDimension[];
26
- vary?: VaryDimension[];
5
+ export interface ComponentContractValidator<TProps = Record<string, unknown>> {
6
+ (context: ComponentValidationContext<TProps>): void | Promise<void>;
7
+ }
8
+ export interface ComponentValidationContext<TProps = Record<string, unknown>> {
9
+ component: string;
10
+ props: TProps;
11
+ blockId?: string;
12
+ path: readonly string[];
13
+ report(issue: ComponentValidationIssue): void;
14
+ }
15
+ export interface ComponentValidationIssue {
16
+ path?: readonly string[];
17
+ code?: string;
18
+ message: string;
19
+ severity?: 'error' | 'warning';
20
+ }
21
+ export interface ComponentDefinition<TId extends string = string, TSchema = unknown> {
22
+ id: TId;
23
+ displayName?: string;
24
+ props: TSchema;
27
25
  imageSlots?: Record<string, ImageSlotContract>;
26
+ validate?: readonly ComponentContractValidator<InferContentProps<TSchema>>[];
28
27
  }
29
- export interface ComponentContract<TSchema = unknown> {
30
- name: string;
31
- component?: CmsComponentFn<any>;
32
- schema: TSchema;
33
- defaultIslandMode?: IslandMode;
34
- varyDimensions?: VaryDimension[];
35
- vary?: VaryDimension[];
28
+ export interface ComponentContract<TId extends string = string, TSchema = unknown> {
29
+ readonly id: TId;
30
+ readonly displayName?: string;
31
+ props: TSchema;
32
+ blockSlots?: Record<string, BlockRefMeta>;
36
33
  imageSlots?: Record<string, ImageSlotContract>;
34
+ validate: readonly ComponentContractValidator<InferContentProps<TSchema>>[];
37
35
  }
38
- export type InferComponentProps<TContract> = TContract extends ComponentContract<infer TSchema> ? InferContentProps<TSchema> : Record<string, unknown>;
39
- export type { CmsComponentFn, InferContentProps };
36
+ export type InferComponentProps<TContract> = TContract extends ComponentContract<string, infer TSchema> ? InferContentProps<TSchema> : Record<string, unknown>;
37
+ export type ComponentContractID<TContract> = TContract extends ComponentContract<infer TId, unknown> ? TId : never;
38
+ export type ComponentRegistry<TContracts extends Record<string, ComponentContract>> = {
39
+ readonly [K in keyof TContracts]: TContracts[K] & {
40
+ readonly id: K & string;
41
+ };
42
+ };
43
+ export type { InferContentProps };
@@ -1,5 +1,5 @@
1
1
  import type { RenderCapabilities } from './renderer.js';
2
- export interface BareMetalConfig {
2
+ export interface Config {
3
3
  version: '1';
4
4
  siteId: string;
5
5
  framework: 'astro' | 'next' | 'sveltekit' | 'custom';