@opensite/ui 3.5.6 → 3.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/registry.cjs CHANGED
@@ -112060,7 +112060,97 @@ var BLOCK_REGISTRY = {
112060
112060
  category: "hero",
112061
112061
  component: HeroMentalHealthTeam,
112062
112062
  props: "HeroMentalHealthTeamProps",
112063
- exampleUsage: `<HeroMentalHealthTeam />`.trim()
112063
+ exampleUsage: `
112064
+ <HeroMentalHealthTeam
112065
+ heading="Compassionate care for your mental wellbeing"
112066
+ description="Our team of experienced mental health professionals is dedicated to providing compassionate care and support to individuals in need."
112067
+ smallImages={[
112068
+ { src: "/images/team-1.jpg", alt: "Dr. Smith" },
112069
+ { src: "/images/team-2.jpg", alt: "Dr. Johnson" },
112070
+ ]}
112071
+ testimonial={{
112072
+ quote:
112073
+ "The support I received changed my life. I'm so grateful for the compassionate care.",
112074
+ author: "Sarah M.",
112075
+ role: "Client",
112076
+ avatarSrc: "/images/avatar.jpg",
112077
+ }}
112078
+ featureImage={{ src: "/images/feature.jpg", alt: "Mental health support" }}
112079
+ actions={[
112080
+ { label: "Get Started", href: "#", variant: "default" },
112081
+ { label: "Talk to Sales", href: "#", variant: "outline" },
112082
+ ]}
112083
+ background="gray"
112084
+ />
112085
+ `.trim(),
112086
+ importantUsageNotes: "Only use if you have a valid testimonial - DO NOT MAKE UP A TESTIMONIAL/REVIEW. Supply exactly 2 images to the 'smallImages' prop and ensure you supply a 'featureImage' prop object. Do not exceed 40 characters for the 'heading' prop. Do not exceed 130 characters for the 'description' prop. If you supply multiple 'actions', ensure to use a variant of 'default' for the first action, and 'outline' for the second action to ensure proper visual distinction between the two CTAs. Follow the example props closely for this block.",
112087
+ usageRequirements: {
112088
+ requiredProps: ["heading", "smallImages", "featureImage", "testimonial"],
112089
+ propConstraints: {
112090
+ heading: { required: true, maxLength: 40 },
112091
+ description: { maxLength: 130 },
112092
+ smallImages: { required: true, count: 2, minItems: 2, maxItems: 2 },
112093
+ featureImage: { required: true },
112094
+ testimonial: {
112095
+ required: true,
112096
+ note: "Must be a real, sourced testimonial. Do not fabricate."
112097
+ },
112098
+ actions: {
112099
+ maxItems: 2,
112100
+ pinnedValues: {
112101
+ "0.variant": "default",
112102
+ "1.variant": "outline"
112103
+ }
112104
+ }
112105
+ },
112106
+ mediaSlots: {
112107
+ featureImage: {
112108
+ path: "featureImage",
112109
+ roles: ["feature", "hero"],
112110
+ disallowedRoles: ["logo", "favicon"],
112111
+ minPixelClass: "large",
112112
+ required: true,
112113
+ note: "Large feature image. Must not be a logo or favicon."
112114
+ },
112115
+ "smallImages[]": {
112116
+ path: "smallImages[]",
112117
+ roles: ["thumbnail", "profile", "feature"],
112118
+ disallowedRoles: ["logo", "favicon"],
112119
+ minPixelClass: "small",
112120
+ required: true,
112121
+ note: "Two team / supporting images. Must not be logos."
112122
+ },
112123
+ "testimonial.avatarSrc": {
112124
+ path: "testimonial.avatarSrc",
112125
+ roles: ["profile", "avatar"],
112126
+ disallowedRoles: ["logo", "favicon"],
112127
+ minPixelClass: "small",
112128
+ preferredAspect: "1:1",
112129
+ note: "Headshot/avatar for the testimonial author."
112130
+ }
112131
+ },
112132
+ requiresSiteCapabilities: ["reviews_or_testimonials", "media_library"]
112133
+ },
112134
+ defaultProps: {
112135
+ heading: "Compassionate care for your mental wellbeing",
112136
+ description: "Our team of experienced mental health professionals is dedicated to providing compassionate care and support to individuals in need.",
112137
+ smallImages: [
112138
+ { src: "/images/team-1.jpg", alt: "Dr. Smith" },
112139
+ { src: "/images/team-2.jpg", alt: "Dr. Johnson" }
112140
+ ],
112141
+ testimonial: {
112142
+ quote: "The support I received changed my life. I'm so grateful for the compassionate care.",
112143
+ author: "Sarah M.",
112144
+ role: "Client",
112145
+ avatarSrc: "/images/avatar.jpg"
112146
+ },
112147
+ featureImage: { src: "/images/feature.jpg", alt: "Mental health support" },
112148
+ actions: [
112149
+ { label: "Get Started", href: "#", variant: "default" },
112150
+ { label: "Talk to Sales", href: "#", variant: "outline" }
112151
+ ],
112152
+ background: "gray"
112153
+ }
112064
112154
  },
112065
112155
  "hero-mentorship-video-split": {
112066
112156
  id: "hero-mentorship-video-split",
@@ -120360,9 +120450,11 @@ function normalizeBlock(block, source) {
120360
120450
  },
120361
120451
  examples: {
120362
120452
  exampleUsage: block.exampleUsage || null,
120363
- defaultData: null
120453
+ defaultData: block.defaultProps ? JSON.parse(JSON.stringify(block.defaultProps)) : null
120364
120454
  },
120365
- source: source ?? null
120455
+ source: source ?? null,
120456
+ importantUsageNotes: block.importantUsageNotes ?? null,
120457
+ usageRequirements: block.usageRequirements ? JSON.parse(JSON.stringify(block.usageRequirements)) : null
120366
120458
  };
120367
120459
  }
120368
120460
  function createBuilderContractBundle({
@@ -1,68 +1,124 @@
1
1
  /**
2
- * Semantic Block Registry
2
+ * Block Registry Types
3
3
  *
4
- * This registry maps semantic concepts to available UI blocks for AI-driven
5
- * site generation. Each block entry contains:
6
- * - id: Unique identifier for the block
7
- * - name: Human-readable name
8
- * - description: What the block does and when to use it
9
- * - semanticTags: Array of semantic concepts this block represents
10
- * - category: Block category (about, features, cta, testimonials, etc.)
11
- * - component: Reference to the actual component
12
- * - props: TypeScript type for the component's props
13
- * - exampleUsage: Code example showing how to use the block
14
- */
15
- interface BlockRegistryEntry$1<T = any> {
16
- id: string;
17
- name: string;
18
- description: string;
19
- semanticTags: string[];
20
- category: BlockCategory$1;
21
- component: React.ComponentType<T>;
22
- props: string;
23
- exampleUsage: string;
24
- }
25
- type BlockCategory$1 = "about" | "features" | "cta" | "testimonials" | "services" | "hero" | "footer" | "header" | "pricing" | "team" | "stats" | "faq" | "contact" | "carousel" | "gallery" | "timeline" | "process" | "benefits" | "comparison" | "background-pattern-hero" | "blog" | "article" | "case-studies-list" | "case-study-detail" | "navbar" | "logos" | "project-list" | "project-detail" | "list" | "offer-modal" | "banner" | "industries" | "resource-detail" | "service-detail" | "services-list" | "resource-list" | "link-page";
26
- /**
27
- * Block Registry - Central registry of all available UI blocks
28
- */
29
- declare const BLOCK_REGISTRY: Record<string, BlockRegistryEntry$1>;
30
- /**
31
- * Get blocks by semantic tag
4
+ * Shared type definitions for the block registry system.
32
5
  */
33
- declare function getBlocksBySemanticTag(tag: string): BlockRegistryEntry$1[];
6
+ type BlockCategory = "about" | "features" | "cta" | "testimonials" | "services" | "hero" | "footer" | "header" | "pricing" | "team" | "stats" | "faq" | "contact" | "carousel" | "gallery" | "timeline" | "process" | "benefits" | "comparison" | "background-pattern-hero" | "blog" | "article" | "case-studies-list" | "case-study-detail" | "navbar" | "logos" | "project-list" | "project-detail" | "list" | "offer-modal" | "banner" | "industries" | "resource-detail" | "service-detail" | "services-list" | "resource-list" | "link-page";
34
7
  /**
35
- * Get blocks by category
8
+ * Semantic role hints for a media slot. Consumers (semantic site builders,
9
+ * media classifiers) use these to scope which assets are eligible for a slot.
10
+ *
11
+ * - `logo`: brand logos / wordmarks (small, transparent backgrounds).
12
+ * - `favicon`: tiny brand icon.
13
+ * - `hero`: large hero/banner imagery.
14
+ * - `feature`: large feature/marketing imagery (non-logo).
15
+ * - `thumbnail`: small supporting imagery (e.g. card images, team thumbs).
16
+ * - `profile`: portrait/headshot of a person.
17
+ * - `avatar`: small profile / testimonial avatar.
18
+ * - `gallery`: imagery suited for galleries / grids.
19
+ * - `background`: large background imagery, often photographic.
20
+ * - `screenshot`: product screenshots / UI captures.
21
+ * - `illustration`: vector / illustrative art.
22
+ * - `video-thumbnail`: poster image for a video slot.
36
23
  */
37
- declare function getBlocksByCategory(category: BlockCategory$1): BlockRegistryEntry$1[];
24
+ type MediaRole = "logo" | "favicon" | "hero" | "feature" | "thumbnail" | "profile" | "avatar" | "gallery" | "background" | "screenshot" | "illustration" | "video-thumbnail";
25
+ /** Minimum pixel class expected for a media asset. */
26
+ type MediaPixelClass = "tiny" | "small" | "medium" | "large" | "xlarge";
38
27
  /**
39
- * Get block by ID
28
+ * Structured description of a single media slot inside a block's prop tree.
29
+ * The `path` is dot/bracket notation, e.g. `featureImage`, `smallImages[]`,
30
+ * `testimonial.avatarSrc`.
40
31
  */
41
- declare function getBlockById(id: string): BlockRegistryEntry$1 | undefined;
32
+ interface BlockMediaSlot {
33
+ path: string;
34
+ /** Allowed/expected semantic roles for this slot, in priority order. */
35
+ roles: MediaRole[];
36
+ /** Roles that must NOT be assigned to this slot. */
37
+ disallowedRoles?: MediaRole[];
38
+ /** Minimum acceptable pixel class for this slot. */
39
+ minPixelClass?: MediaPixelClass;
40
+ /** Preferred aspect ratio, e.g. "16:9", "1:1", "4:5". */
41
+ preferredAspect?: string;
42
+ /** Whether the block visually requires this slot to render correctly. */
43
+ required?: boolean;
44
+ /** Short note explaining the slot's intent (consumed by AI prompts). */
45
+ note?: string;
46
+ }
42
47
  /**
43
- * Get all available blocks
48
+ * Per-prop content constraints. Additive – consumers should treat missing
49
+ * fields as "no constraint declared" rather than rejecting payloads.
44
50
  */
45
- declare function getAllBlocks(): BlockRegistryEntry$1[];
51
+ interface BlockPropConstraint {
52
+ /** Whether the block requires this prop to render correctly. */
53
+ required?: boolean;
54
+ /** Maximum string length for text-shaped props. */
55
+ maxLength?: number;
56
+ /** Exact item count for array props (shorthand for minItems = maxItems). */
57
+ count?: number;
58
+ /** Minimum array length. */
59
+ minItems?: number;
60
+ /** Maximum array length. */
61
+ maxItems?: number;
62
+ /**
63
+ * Pinned values, by index for array props or as a single value for scalars.
64
+ * Used for the `actions[0].variant = "default"` / `actions[1].variant = "outline"` pattern.
65
+ */
66
+ pinnedValues?: Record<string, string | number | boolean>;
67
+ /** Free-form note about this prop (for AI prompts). */
68
+ note?: string;
69
+ }
46
70
  /**
47
- * Get all categories
71
+ * Capabilities the host site / data source must satisfy for the block to be
72
+ * suitable. Consumers (e.g. Octane) gate block selection on these BEFORE the
73
+ * block is offered to the model, so it cannot fabricate the missing input.
48
74
  */
49
- declare function getAllCategories(): BlockCategory$1[];
75
+ type SiteCapability = "reviews_or_testimonials" | "pricing_data" | "team_members" | "blog_posts" | "case_studies" | "metrics_or_stats" | "product_catalog" | "media_library" | "contact_info";
50
76
  /**
51
- * Search blocks by query (searches name, description, and semantic tags)
77
+ * Structured usage requirements for a block. This is the executable
78
+ * complement to `importantUsageNotes` (which remains for human-readable
79
+ * prompt context). When present, downstream consumers SHOULD enforce these
80
+ * at selection time and during post-generation validation.
52
81
  */
53
- declare function searchBlocks(query: string): BlockRegistryEntry$1[];
54
-
82
+ interface BlockUsageRequirements {
83
+ /** Names of props that are required for the block to render correctly. */
84
+ requiredProps?: string[];
85
+ /** Per-prop content/cardinality constraints, keyed by prop name/path. */
86
+ propConstraints?: Record<string, BlockPropConstraint>;
87
+ /** Media slot metadata, keyed by slot path. */
88
+ mediaSlots?: Record<string, BlockMediaSlot>;
89
+ /** Site capabilities required to safely select this block. */
90
+ requiresSiteCapabilities?: SiteCapability[];
91
+ /**
92
+ * Free-form structured rules that don't fit other fields. Consumers should
93
+ * treat unknown keys as advisory.
94
+ */
95
+ notes?: string[];
96
+ }
55
97
  /**
56
- * Block Registry Types
57
- *
58
- * Shared type definitions for the block registry system.
98
+ * Shared metadata fields that describe a block's contract. Used both by
99
+ * {@link BlockMetadata} (no component) and {@link BlockRegistryEntry}
100
+ * (with component).
59
101
  */
60
- type BlockCategory = "about" | "features" | "cta" | "testimonials" | "services" | "hero" | "footer" | "header" | "pricing" | "team" | "stats" | "faq" | "contact" | "carousel" | "gallery" | "timeline" | "process" | "benefits" | "comparison" | "background-pattern-hero" | "blog" | "article" | "case-studies-list" | "case-study-detail" | "navbar" | "logos" | "project-list" | "project-detail" | "list" | "offer-modal" | "banner" | "industries" | "resource-detail" | "service-detail" | "services-list" | "resource-list" | "link-page";
102
+ interface BlockContractFields {
103
+ /**
104
+ * Human-readable usage guidance for AI prompts. This remains advisory.
105
+ * For executable rules use {@link BlockContractFields.usageRequirements}.
106
+ */
107
+ importantUsageNotes?: string;
108
+ /** Structured, machine-readable usage requirements. */
109
+ usageRequirements?: BlockUsageRequirements;
110
+ /**
111
+ * Canonical default / example payload for the block, matching the prop
112
+ * shape. Optional. When supplied, consumers should prefer this over
113
+ * parsing `exampleUsage` JSX.
114
+ */
115
+ defaultProps?: Record<string, unknown>;
116
+ }
61
117
  /**
62
118
  * Metadata-only block registry entry (no component import)
63
119
  * Used for AI-driven component discovery without bundling all components
64
120
  */
65
- interface BlockMetadata {
121
+ interface BlockMetadata extends BlockContractFields {
66
122
  id: string;
67
123
  name: string;
68
124
  description: string;
@@ -81,7 +137,7 @@ interface BlockMetadata {
81
137
  * Full block registry entry with component reference
82
138
  * @deprecated Use BlockMetadata for new code - this type causes all components to be bundled
83
139
  */
84
- interface BlockRegistryEntry<T = any> {
140
+ interface BlockRegistryEntry<T = any> extends BlockContractFields {
85
141
  id: string;
86
142
  name: string;
87
143
  description: string;
@@ -107,7 +163,13 @@ interface BuilderContractPropsContract {
107
163
  }
108
164
  interface BuilderContractExamples {
109
165
  exampleUsage: string | null;
110
- defaultData: null;
166
+ /**
167
+ * Canonical default / example props payload. Populated from
168
+ * BlockRegistryEntry.defaultProps when declared, otherwise null.
169
+ * Older consumers that expected this to always be null should treat
170
+ * an object value as advisory example data, not as a schema.
171
+ */
172
+ defaultData: Record<string, unknown> | null;
111
173
  }
112
174
  interface BuilderContractBlock {
113
175
  componentId: string;
@@ -121,6 +183,16 @@ interface BuilderContractBlock {
121
183
  propsContract: BuilderContractPropsContract;
122
184
  examples: BuilderContractExamples;
123
185
  source: BuilderContractBlockSource | null;
186
+ /**
187
+ * Human-readable usage guidance for AI prompts. Mirrors
188
+ * BlockRegistryEntry.importantUsageNotes when declared, otherwise null.
189
+ */
190
+ importantUsageNotes: string | null;
191
+ /**
192
+ * Structured, machine-readable usage requirements. Null when the
193
+ * registry entry does not declare any.
194
+ */
195
+ usageRequirements: BlockUsageRequirements | null;
124
196
  }
125
197
  interface BuilderContractMetadata {
126
198
  contractVersion: string;
@@ -195,6 +267,50 @@ interface BuilderContractBundle {
195
267
  pageRules: BuilderContractPageRules;
196
268
  }
197
269
 
270
+ /**
271
+ * Semantic Block Registry
272
+ *
273
+ * This registry maps semantic concepts to available UI blocks for AI-driven
274
+ * site generation. Each block entry contains:
275
+ * - id: Unique identifier for the block
276
+ * - name: Human-readable name
277
+ * - description: What the block does and when to use it
278
+ * - semanticTags: Array of semantic concepts this block represents
279
+ * - category: Block category (about, features, cta, testimonials, etc.)
280
+ * - component: Reference to the actual component
281
+ * - props: TypeScript type for the component's props
282
+ * - exampleUsage: Code example showing how to use the block
283
+ */
284
+
285
+ /**
286
+ * Block Registry - Central registry of all available UI blocks
287
+ */
288
+ declare const BLOCK_REGISTRY: Record<string, BlockRegistryEntry>;
289
+ /**
290
+ * Get blocks by semantic tag
291
+ */
292
+ declare function getBlocksBySemanticTag(tag: string): BlockRegistryEntry[];
293
+ /**
294
+ * Get blocks by category
295
+ */
296
+ declare function getBlocksByCategory(category: BlockCategory): BlockRegistryEntry[];
297
+ /**
298
+ * Get block by ID
299
+ */
300
+ declare function getBlockById(id: string): BlockRegistryEntry | undefined;
301
+ /**
302
+ * Get all available blocks
303
+ */
304
+ declare function getAllBlocks(): BlockRegistryEntry[];
305
+ /**
306
+ * Get all categories
307
+ */
308
+ declare function getAllCategories(): BlockCategory[];
309
+ /**
310
+ * Search blocks by query (searches name, description, and semantic tags)
311
+ */
312
+ declare function searchBlocks(query: string): BlockRegistryEntry[];
313
+
198
314
  declare const BUILDER_CONTRACT_VERSION = "v1";
199
315
  interface CreateBuilderContractBundleOptions {
200
316
  blocks: BlockRegistryEntry[];
@@ -205,4 +321,4 @@ interface CreateBuilderContractBundleOptions {
205
321
  }
206
322
  declare function createBuilderContractBundle({ blocks, uiVersion, exportedAt, source, blockSources, }: CreateBuilderContractBundleOptions): BuilderContractBundle;
207
323
 
208
- export { BLOCK_REGISTRY, BUILDER_CONTRACT_VERSION, type BlockCategory, type BlockMetadata, type BlockRegistryEntry, type BuilderContractBlock, type BuilderContractBlockSource, type BuilderContractBundle, type BuilderContractDesignTokens, type BuilderContractDynamicSourceDefinition, type BuilderContractDynamicSources, type BuilderContractExamples, type BuilderContractLayoutRole, type BuilderContractMetadata, type BuilderContractPageRules, type BuilderContractPropsContract, type BuilderContractSharedLayout, type BuilderContractSharedLayoutSection, createBuilderContractBundle, getAllBlocks, getAllCategories, getBlockById, getBlocksByCategory, getBlocksBySemanticTag, searchBlocks };
324
+ export { BLOCK_REGISTRY, BUILDER_CONTRACT_VERSION, type BlockCategory, type BlockContractFields, type BlockMediaSlot, type BlockMetadata, type BlockPropConstraint, type BlockRegistryEntry, type BlockUsageRequirements, type BuilderContractBlock, type BuilderContractBlockSource, type BuilderContractBundle, type BuilderContractDesignTokens, type BuilderContractDynamicSourceDefinition, type BuilderContractDynamicSources, type BuilderContractExamples, type BuilderContractLayoutRole, type BuilderContractMetadata, type BuilderContractPageRules, type BuilderContractPropsContract, type BuilderContractSharedLayout, type BuilderContractSharedLayoutSection, type MediaPixelClass, type MediaRole, type SiteCapability, createBuilderContractBundle, getAllBlocks, getAllCategories, getBlockById, getBlocksByCategory, getBlocksBySemanticTag, searchBlocks };
@@ -1,68 +1,124 @@
1
1
  /**
2
- * Semantic Block Registry
2
+ * Block Registry Types
3
3
  *
4
- * This registry maps semantic concepts to available UI blocks for AI-driven
5
- * site generation. Each block entry contains:
6
- * - id: Unique identifier for the block
7
- * - name: Human-readable name
8
- * - description: What the block does and when to use it
9
- * - semanticTags: Array of semantic concepts this block represents
10
- * - category: Block category (about, features, cta, testimonials, etc.)
11
- * - component: Reference to the actual component
12
- * - props: TypeScript type for the component's props
13
- * - exampleUsage: Code example showing how to use the block
14
- */
15
- interface BlockRegistryEntry$1<T = any> {
16
- id: string;
17
- name: string;
18
- description: string;
19
- semanticTags: string[];
20
- category: BlockCategory$1;
21
- component: React.ComponentType<T>;
22
- props: string;
23
- exampleUsage: string;
24
- }
25
- type BlockCategory$1 = "about" | "features" | "cta" | "testimonials" | "services" | "hero" | "footer" | "header" | "pricing" | "team" | "stats" | "faq" | "contact" | "carousel" | "gallery" | "timeline" | "process" | "benefits" | "comparison" | "background-pattern-hero" | "blog" | "article" | "case-studies-list" | "case-study-detail" | "navbar" | "logos" | "project-list" | "project-detail" | "list" | "offer-modal" | "banner" | "industries" | "resource-detail" | "service-detail" | "services-list" | "resource-list" | "link-page";
26
- /**
27
- * Block Registry - Central registry of all available UI blocks
28
- */
29
- declare const BLOCK_REGISTRY: Record<string, BlockRegistryEntry$1>;
30
- /**
31
- * Get blocks by semantic tag
4
+ * Shared type definitions for the block registry system.
32
5
  */
33
- declare function getBlocksBySemanticTag(tag: string): BlockRegistryEntry$1[];
6
+ type BlockCategory = "about" | "features" | "cta" | "testimonials" | "services" | "hero" | "footer" | "header" | "pricing" | "team" | "stats" | "faq" | "contact" | "carousel" | "gallery" | "timeline" | "process" | "benefits" | "comparison" | "background-pattern-hero" | "blog" | "article" | "case-studies-list" | "case-study-detail" | "navbar" | "logos" | "project-list" | "project-detail" | "list" | "offer-modal" | "banner" | "industries" | "resource-detail" | "service-detail" | "services-list" | "resource-list" | "link-page";
34
7
  /**
35
- * Get blocks by category
8
+ * Semantic role hints for a media slot. Consumers (semantic site builders,
9
+ * media classifiers) use these to scope which assets are eligible for a slot.
10
+ *
11
+ * - `logo`: brand logos / wordmarks (small, transparent backgrounds).
12
+ * - `favicon`: tiny brand icon.
13
+ * - `hero`: large hero/banner imagery.
14
+ * - `feature`: large feature/marketing imagery (non-logo).
15
+ * - `thumbnail`: small supporting imagery (e.g. card images, team thumbs).
16
+ * - `profile`: portrait/headshot of a person.
17
+ * - `avatar`: small profile / testimonial avatar.
18
+ * - `gallery`: imagery suited for galleries / grids.
19
+ * - `background`: large background imagery, often photographic.
20
+ * - `screenshot`: product screenshots / UI captures.
21
+ * - `illustration`: vector / illustrative art.
22
+ * - `video-thumbnail`: poster image for a video slot.
36
23
  */
37
- declare function getBlocksByCategory(category: BlockCategory$1): BlockRegistryEntry$1[];
24
+ type MediaRole = "logo" | "favicon" | "hero" | "feature" | "thumbnail" | "profile" | "avatar" | "gallery" | "background" | "screenshot" | "illustration" | "video-thumbnail";
25
+ /** Minimum pixel class expected for a media asset. */
26
+ type MediaPixelClass = "tiny" | "small" | "medium" | "large" | "xlarge";
38
27
  /**
39
- * Get block by ID
28
+ * Structured description of a single media slot inside a block's prop tree.
29
+ * The `path` is dot/bracket notation, e.g. `featureImage`, `smallImages[]`,
30
+ * `testimonial.avatarSrc`.
40
31
  */
41
- declare function getBlockById(id: string): BlockRegistryEntry$1 | undefined;
32
+ interface BlockMediaSlot {
33
+ path: string;
34
+ /** Allowed/expected semantic roles for this slot, in priority order. */
35
+ roles: MediaRole[];
36
+ /** Roles that must NOT be assigned to this slot. */
37
+ disallowedRoles?: MediaRole[];
38
+ /** Minimum acceptable pixel class for this slot. */
39
+ minPixelClass?: MediaPixelClass;
40
+ /** Preferred aspect ratio, e.g. "16:9", "1:1", "4:5". */
41
+ preferredAspect?: string;
42
+ /** Whether the block visually requires this slot to render correctly. */
43
+ required?: boolean;
44
+ /** Short note explaining the slot's intent (consumed by AI prompts). */
45
+ note?: string;
46
+ }
42
47
  /**
43
- * Get all available blocks
48
+ * Per-prop content constraints. Additive – consumers should treat missing
49
+ * fields as "no constraint declared" rather than rejecting payloads.
44
50
  */
45
- declare function getAllBlocks(): BlockRegistryEntry$1[];
51
+ interface BlockPropConstraint {
52
+ /** Whether the block requires this prop to render correctly. */
53
+ required?: boolean;
54
+ /** Maximum string length for text-shaped props. */
55
+ maxLength?: number;
56
+ /** Exact item count for array props (shorthand for minItems = maxItems). */
57
+ count?: number;
58
+ /** Minimum array length. */
59
+ minItems?: number;
60
+ /** Maximum array length. */
61
+ maxItems?: number;
62
+ /**
63
+ * Pinned values, by index for array props or as a single value for scalars.
64
+ * Used for the `actions[0].variant = "default"` / `actions[1].variant = "outline"` pattern.
65
+ */
66
+ pinnedValues?: Record<string, string | number | boolean>;
67
+ /** Free-form note about this prop (for AI prompts). */
68
+ note?: string;
69
+ }
46
70
  /**
47
- * Get all categories
71
+ * Capabilities the host site / data source must satisfy for the block to be
72
+ * suitable. Consumers (e.g. Octane) gate block selection on these BEFORE the
73
+ * block is offered to the model, so it cannot fabricate the missing input.
48
74
  */
49
- declare function getAllCategories(): BlockCategory$1[];
75
+ type SiteCapability = "reviews_or_testimonials" | "pricing_data" | "team_members" | "blog_posts" | "case_studies" | "metrics_or_stats" | "product_catalog" | "media_library" | "contact_info";
50
76
  /**
51
- * Search blocks by query (searches name, description, and semantic tags)
77
+ * Structured usage requirements for a block. This is the executable
78
+ * complement to `importantUsageNotes` (which remains for human-readable
79
+ * prompt context). When present, downstream consumers SHOULD enforce these
80
+ * at selection time and during post-generation validation.
52
81
  */
53
- declare function searchBlocks(query: string): BlockRegistryEntry$1[];
54
-
82
+ interface BlockUsageRequirements {
83
+ /** Names of props that are required for the block to render correctly. */
84
+ requiredProps?: string[];
85
+ /** Per-prop content/cardinality constraints, keyed by prop name/path. */
86
+ propConstraints?: Record<string, BlockPropConstraint>;
87
+ /** Media slot metadata, keyed by slot path. */
88
+ mediaSlots?: Record<string, BlockMediaSlot>;
89
+ /** Site capabilities required to safely select this block. */
90
+ requiresSiteCapabilities?: SiteCapability[];
91
+ /**
92
+ * Free-form structured rules that don't fit other fields. Consumers should
93
+ * treat unknown keys as advisory.
94
+ */
95
+ notes?: string[];
96
+ }
55
97
  /**
56
- * Block Registry Types
57
- *
58
- * Shared type definitions for the block registry system.
98
+ * Shared metadata fields that describe a block's contract. Used both by
99
+ * {@link BlockMetadata} (no component) and {@link BlockRegistryEntry}
100
+ * (with component).
59
101
  */
60
- type BlockCategory = "about" | "features" | "cta" | "testimonials" | "services" | "hero" | "footer" | "header" | "pricing" | "team" | "stats" | "faq" | "contact" | "carousel" | "gallery" | "timeline" | "process" | "benefits" | "comparison" | "background-pattern-hero" | "blog" | "article" | "case-studies-list" | "case-study-detail" | "navbar" | "logos" | "project-list" | "project-detail" | "list" | "offer-modal" | "banner" | "industries" | "resource-detail" | "service-detail" | "services-list" | "resource-list" | "link-page";
102
+ interface BlockContractFields {
103
+ /**
104
+ * Human-readable usage guidance for AI prompts. This remains advisory.
105
+ * For executable rules use {@link BlockContractFields.usageRequirements}.
106
+ */
107
+ importantUsageNotes?: string;
108
+ /** Structured, machine-readable usage requirements. */
109
+ usageRequirements?: BlockUsageRequirements;
110
+ /**
111
+ * Canonical default / example payload for the block, matching the prop
112
+ * shape. Optional. When supplied, consumers should prefer this over
113
+ * parsing `exampleUsage` JSX.
114
+ */
115
+ defaultProps?: Record<string, unknown>;
116
+ }
61
117
  /**
62
118
  * Metadata-only block registry entry (no component import)
63
119
  * Used for AI-driven component discovery without bundling all components
64
120
  */
65
- interface BlockMetadata {
121
+ interface BlockMetadata extends BlockContractFields {
66
122
  id: string;
67
123
  name: string;
68
124
  description: string;
@@ -81,7 +137,7 @@ interface BlockMetadata {
81
137
  * Full block registry entry with component reference
82
138
  * @deprecated Use BlockMetadata for new code - this type causes all components to be bundled
83
139
  */
84
- interface BlockRegistryEntry<T = any> {
140
+ interface BlockRegistryEntry<T = any> extends BlockContractFields {
85
141
  id: string;
86
142
  name: string;
87
143
  description: string;
@@ -107,7 +163,13 @@ interface BuilderContractPropsContract {
107
163
  }
108
164
  interface BuilderContractExamples {
109
165
  exampleUsage: string | null;
110
- defaultData: null;
166
+ /**
167
+ * Canonical default / example props payload. Populated from
168
+ * BlockRegistryEntry.defaultProps when declared, otherwise null.
169
+ * Older consumers that expected this to always be null should treat
170
+ * an object value as advisory example data, not as a schema.
171
+ */
172
+ defaultData: Record<string, unknown> | null;
111
173
  }
112
174
  interface BuilderContractBlock {
113
175
  componentId: string;
@@ -121,6 +183,16 @@ interface BuilderContractBlock {
121
183
  propsContract: BuilderContractPropsContract;
122
184
  examples: BuilderContractExamples;
123
185
  source: BuilderContractBlockSource | null;
186
+ /**
187
+ * Human-readable usage guidance for AI prompts. Mirrors
188
+ * BlockRegistryEntry.importantUsageNotes when declared, otherwise null.
189
+ */
190
+ importantUsageNotes: string | null;
191
+ /**
192
+ * Structured, machine-readable usage requirements. Null when the
193
+ * registry entry does not declare any.
194
+ */
195
+ usageRequirements: BlockUsageRequirements | null;
124
196
  }
125
197
  interface BuilderContractMetadata {
126
198
  contractVersion: string;
@@ -195,6 +267,50 @@ interface BuilderContractBundle {
195
267
  pageRules: BuilderContractPageRules;
196
268
  }
197
269
 
270
+ /**
271
+ * Semantic Block Registry
272
+ *
273
+ * This registry maps semantic concepts to available UI blocks for AI-driven
274
+ * site generation. Each block entry contains:
275
+ * - id: Unique identifier for the block
276
+ * - name: Human-readable name
277
+ * - description: What the block does and when to use it
278
+ * - semanticTags: Array of semantic concepts this block represents
279
+ * - category: Block category (about, features, cta, testimonials, etc.)
280
+ * - component: Reference to the actual component
281
+ * - props: TypeScript type for the component's props
282
+ * - exampleUsage: Code example showing how to use the block
283
+ */
284
+
285
+ /**
286
+ * Block Registry - Central registry of all available UI blocks
287
+ */
288
+ declare const BLOCK_REGISTRY: Record<string, BlockRegistryEntry>;
289
+ /**
290
+ * Get blocks by semantic tag
291
+ */
292
+ declare function getBlocksBySemanticTag(tag: string): BlockRegistryEntry[];
293
+ /**
294
+ * Get blocks by category
295
+ */
296
+ declare function getBlocksByCategory(category: BlockCategory): BlockRegistryEntry[];
297
+ /**
298
+ * Get block by ID
299
+ */
300
+ declare function getBlockById(id: string): BlockRegistryEntry | undefined;
301
+ /**
302
+ * Get all available blocks
303
+ */
304
+ declare function getAllBlocks(): BlockRegistryEntry[];
305
+ /**
306
+ * Get all categories
307
+ */
308
+ declare function getAllCategories(): BlockCategory[];
309
+ /**
310
+ * Search blocks by query (searches name, description, and semantic tags)
311
+ */
312
+ declare function searchBlocks(query: string): BlockRegistryEntry[];
313
+
198
314
  declare const BUILDER_CONTRACT_VERSION = "v1";
199
315
  interface CreateBuilderContractBundleOptions {
200
316
  blocks: BlockRegistryEntry[];
@@ -205,4 +321,4 @@ interface CreateBuilderContractBundleOptions {
205
321
  }
206
322
  declare function createBuilderContractBundle({ blocks, uiVersion, exportedAt, source, blockSources, }: CreateBuilderContractBundleOptions): BuilderContractBundle;
207
323
 
208
- export { BLOCK_REGISTRY, BUILDER_CONTRACT_VERSION, type BlockCategory, type BlockMetadata, type BlockRegistryEntry, type BuilderContractBlock, type BuilderContractBlockSource, type BuilderContractBundle, type BuilderContractDesignTokens, type BuilderContractDynamicSourceDefinition, type BuilderContractDynamicSources, type BuilderContractExamples, type BuilderContractLayoutRole, type BuilderContractMetadata, type BuilderContractPageRules, type BuilderContractPropsContract, type BuilderContractSharedLayout, type BuilderContractSharedLayoutSection, createBuilderContractBundle, getAllBlocks, getAllCategories, getBlockById, getBlocksByCategory, getBlocksBySemanticTag, searchBlocks };
324
+ export { BLOCK_REGISTRY, BUILDER_CONTRACT_VERSION, type BlockCategory, type BlockContractFields, type BlockMediaSlot, type BlockMetadata, type BlockPropConstraint, type BlockRegistryEntry, type BlockUsageRequirements, type BuilderContractBlock, type BuilderContractBlockSource, type BuilderContractBundle, type BuilderContractDesignTokens, type BuilderContractDynamicSourceDefinition, type BuilderContractDynamicSources, type BuilderContractExamples, type BuilderContractLayoutRole, type BuilderContractMetadata, type BuilderContractPageRules, type BuilderContractPropsContract, type BuilderContractSharedLayout, type BuilderContractSharedLayoutSection, type MediaPixelClass, type MediaRole, type SiteCapability, createBuilderContractBundle, getAllBlocks, getAllCategories, getBlockById, getBlocksByCategory, getBlocksBySemanticTag, searchBlocks };
package/dist/registry.js CHANGED
@@ -112020,7 +112020,97 @@ var BLOCK_REGISTRY = {
112020
112020
  category: "hero",
112021
112021
  component: HeroMentalHealthTeam,
112022
112022
  props: "HeroMentalHealthTeamProps",
112023
- exampleUsage: `<HeroMentalHealthTeam />`.trim()
112023
+ exampleUsage: `
112024
+ <HeroMentalHealthTeam
112025
+ heading="Compassionate care for your mental wellbeing"
112026
+ description="Our team of experienced mental health professionals is dedicated to providing compassionate care and support to individuals in need."
112027
+ smallImages={[
112028
+ { src: "/images/team-1.jpg", alt: "Dr. Smith" },
112029
+ { src: "/images/team-2.jpg", alt: "Dr. Johnson" },
112030
+ ]}
112031
+ testimonial={{
112032
+ quote:
112033
+ "The support I received changed my life. I'm so grateful for the compassionate care.",
112034
+ author: "Sarah M.",
112035
+ role: "Client",
112036
+ avatarSrc: "/images/avatar.jpg",
112037
+ }}
112038
+ featureImage={{ src: "/images/feature.jpg", alt: "Mental health support" }}
112039
+ actions={[
112040
+ { label: "Get Started", href: "#", variant: "default" },
112041
+ { label: "Talk to Sales", href: "#", variant: "outline" },
112042
+ ]}
112043
+ background="gray"
112044
+ />
112045
+ `.trim(),
112046
+ importantUsageNotes: "Only use if you have a valid testimonial - DO NOT MAKE UP A TESTIMONIAL/REVIEW. Supply exactly 2 images to the 'smallImages' prop and ensure you supply a 'featureImage' prop object. Do not exceed 40 characters for the 'heading' prop. Do not exceed 130 characters for the 'description' prop. If you supply multiple 'actions', ensure to use a variant of 'default' for the first action, and 'outline' for the second action to ensure proper visual distinction between the two CTAs. Follow the example props closely for this block.",
112047
+ usageRequirements: {
112048
+ requiredProps: ["heading", "smallImages", "featureImage", "testimonial"],
112049
+ propConstraints: {
112050
+ heading: { required: true, maxLength: 40 },
112051
+ description: { maxLength: 130 },
112052
+ smallImages: { required: true, count: 2, minItems: 2, maxItems: 2 },
112053
+ featureImage: { required: true },
112054
+ testimonial: {
112055
+ required: true,
112056
+ note: "Must be a real, sourced testimonial. Do not fabricate."
112057
+ },
112058
+ actions: {
112059
+ maxItems: 2,
112060
+ pinnedValues: {
112061
+ "0.variant": "default",
112062
+ "1.variant": "outline"
112063
+ }
112064
+ }
112065
+ },
112066
+ mediaSlots: {
112067
+ featureImage: {
112068
+ path: "featureImage",
112069
+ roles: ["feature", "hero"],
112070
+ disallowedRoles: ["logo", "favicon"],
112071
+ minPixelClass: "large",
112072
+ required: true,
112073
+ note: "Large feature image. Must not be a logo or favicon."
112074
+ },
112075
+ "smallImages[]": {
112076
+ path: "smallImages[]",
112077
+ roles: ["thumbnail", "profile", "feature"],
112078
+ disallowedRoles: ["logo", "favicon"],
112079
+ minPixelClass: "small",
112080
+ required: true,
112081
+ note: "Two team / supporting images. Must not be logos."
112082
+ },
112083
+ "testimonial.avatarSrc": {
112084
+ path: "testimonial.avatarSrc",
112085
+ roles: ["profile", "avatar"],
112086
+ disallowedRoles: ["logo", "favicon"],
112087
+ minPixelClass: "small",
112088
+ preferredAspect: "1:1",
112089
+ note: "Headshot/avatar for the testimonial author."
112090
+ }
112091
+ },
112092
+ requiresSiteCapabilities: ["reviews_or_testimonials", "media_library"]
112093
+ },
112094
+ defaultProps: {
112095
+ heading: "Compassionate care for your mental wellbeing",
112096
+ description: "Our team of experienced mental health professionals is dedicated to providing compassionate care and support to individuals in need.",
112097
+ smallImages: [
112098
+ { src: "/images/team-1.jpg", alt: "Dr. Smith" },
112099
+ { src: "/images/team-2.jpg", alt: "Dr. Johnson" }
112100
+ ],
112101
+ testimonial: {
112102
+ quote: "The support I received changed my life. I'm so grateful for the compassionate care.",
112103
+ author: "Sarah M.",
112104
+ role: "Client",
112105
+ avatarSrc: "/images/avatar.jpg"
112106
+ },
112107
+ featureImage: { src: "/images/feature.jpg", alt: "Mental health support" },
112108
+ actions: [
112109
+ { label: "Get Started", href: "#", variant: "default" },
112110
+ { label: "Talk to Sales", href: "#", variant: "outline" }
112111
+ ],
112112
+ background: "gray"
112113
+ }
112024
112114
  },
112025
112115
  "hero-mentorship-video-split": {
112026
112116
  id: "hero-mentorship-video-split",
@@ -120320,9 +120410,11 @@ function normalizeBlock(block, source) {
120320
120410
  },
120321
120411
  examples: {
120322
120412
  exampleUsage: block.exampleUsage || null,
120323
- defaultData: null
120413
+ defaultData: block.defaultProps ? JSON.parse(JSON.stringify(block.defaultProps)) : null
120324
120414
  },
120325
- source: source ?? null
120415
+ source: source ?? null,
120416
+ importantUsageNotes: block.importantUsageNotes ?? null,
120417
+ usageRequirements: block.usageRequirements ? JSON.parse(JSON.stringify(block.usageRequirements)) : null
120326
120418
  };
120327
120419
  }
120328
120420
  function createBuilderContractBundle({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opensite/ui",
3
- "version": "3.5.6",
3
+ "version": "3.5.7",
4
4
  "description": "Foundational UI component library for OpenSite Semantic Site Builder with tree-shakable exports and abstract styling",
5
5
  "keywords": [
6
6
  "react",