@pwfabric/authoring 0.0.0-stage → 1.0.0-rc.0

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.
@@ -0,0 +1,114 @@
1
+ /**
2
+ * defineFactory API
3
+ *
4
+ * Create factory functions that generate block compositions.
5
+ *
6
+ * @module @pwfabric/authoring/define-factory
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { defineFactory } from '@pwfabric/authoring'
11
+ * import { z } from 'zod'
12
+ *
13
+ * const MyPageFactory = defineFactory({
14
+ * id: 'my-page',
15
+ * name: 'My Page Factory',
16
+ * configSchema: z.object({
17
+ * title: z.string(),
18
+ * subtitle: z.string().optional(),
19
+ * }),
20
+ * build: (config) => [
21
+ * { type: 'heading', props: { text: config.title, level: 'h1' } },
22
+ * { type: 'text', props: { content: config.subtitle ?? '' } },
23
+ * ]
24
+ * })
25
+ * ```
26
+ */
27
+ import type { Block } from '@pwfabric/core';
28
+ import type { FactoryOptions, FactoryDefinition, FactoryConfig } from './types.js';
29
+ /**
30
+ * Reset the ID counter (useful for testing)
31
+ */
32
+ export declare function resetIdCounter(): void;
33
+ /**
34
+ * Define a factory function that generates block compositions
35
+ *
36
+ * Factories allow you to create reusable block patterns that can be
37
+ * customized with configuration. They automatically generate unique
38
+ * block IDs and validate configuration against an optional schema.
39
+ *
40
+ * @param options - Factory definition options
41
+ * @returns A frozen factory definition
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * import { defineFactory } from '@pwfabric/authoring'
46
+ * import { z } from 'zod'
47
+ *
48
+ * // Define a pricing section factory
49
+ * const PricingSectionFactory = defineFactory({
50
+ * id: 'pricing-section',
51
+ * name: 'Pricing Section',
52
+ * description: 'Create a pricing section with multiple tiers',
53
+ * configSchema: z.object({
54
+ * title: z.string(),
55
+ * tiers: z.array(z.object({
56
+ * name: z.string(),
57
+ * price: z.number(),
58
+ * features: z.array(z.string()),
59
+ * })),
60
+ * }),
61
+ * build: (config) => [
62
+ * {
63
+ * type: 'container',
64
+ * props: { direction: 'column', gap: 32 },
65
+ * children: [
66
+ * { type: 'heading', props: { text: config.title, level: 'h2' } },
67
+ * {
68
+ * type: 'grid',
69
+ * props: { columns: config.tiers.length },
70
+ * children: config.tiers.map((tier) => ({
71
+ * type: 'pricing-card',
72
+ * props: {
73
+ * title: tier.name,
74
+ * price: tier.price,
75
+ * features: tier.features,
76
+ * },
77
+ * })),
78
+ * },
79
+ * ],
80
+ * },
81
+ * ],
82
+ * })
83
+ *
84
+ * // Use the factory
85
+ * const blocks = PricingSectionFactory.build({
86
+ * title: 'Choose Your Plan',
87
+ * tiers: [
88
+ * { name: 'Basic', price: 9, features: ['Feature 1'] },
89
+ * { name: 'Pro', price: 29, features: ['Feature 1', 'Feature 2'] },
90
+ * ],
91
+ * })
92
+ * ```
93
+ */
94
+ export declare function defineFactory<TConfig extends FactoryConfig = FactoryConfig>(options: FactoryOptions<TConfig>): FactoryDefinition<TConfig>;
95
+ /**
96
+ * Check if a value is a factory definition
97
+ */
98
+ export declare function isFactoryDefinition(value: unknown): value is FactoryDefinition;
99
+ /**
100
+ * Compose multiple factory outputs into a single block array
101
+ *
102
+ * @param factories - Array of factory output block arrays
103
+ * @returns Combined block array
104
+ */
105
+ export declare function composeFactoryOutputs(...factories: readonly (readonly Block[])[]): readonly Block[];
106
+ /**
107
+ * Wrap factory output in a container block
108
+ *
109
+ * @param blocks - Factory output blocks
110
+ * @param containerProps - Props for the wrapper container
111
+ * @returns Single container block with children
112
+ */
113
+ export declare function wrapInContainer(blocks: readonly Block[], containerProps?: Record<string, unknown>): Block;
114
+ //# sourceMappingURL=define-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-factory.d.ts","sourceRoot":"","sources":["../src/define-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAG3C,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,aAAa,EAId,MAAM,YAAY,CAAA;AAgBnB;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAyFD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,wBAAgB,aAAa,CAAC,OAAO,SAAS,aAAa,GAAG,aAAa,EACzE,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,GAC/B,iBAAiB,CAAC,OAAO,CAAC,CA8B5B;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAY9E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,SAAS,EAAE,SAAS,CAAC,SAAS,KAAK,EAAE,CAAC,EAAE,GAC1C,SAAS,KAAK,EAAE,CAElB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,cAAc,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAC3C,KAAK,CAYP"}
@@ -0,0 +1,247 @@
1
+ /**
2
+ * defineFactory API
3
+ *
4
+ * Create factory functions that generate block compositions.
5
+ *
6
+ * @module @pwfabric/authoring/define-factory
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { defineFactory } from '@pwfabric/authoring'
11
+ * import { z } from 'zod'
12
+ *
13
+ * const MyPageFactory = defineFactory({
14
+ * id: 'my-page',
15
+ * name: 'My Page Factory',
16
+ * configSchema: z.object({
17
+ * title: z.string(),
18
+ * subtitle: z.string().optional(),
19
+ * }),
20
+ * build: (config) => [
21
+ * { type: 'heading', props: { text: config.title, level: 'h1' } },
22
+ * { type: 'text', props: { content: config.subtitle ?? '' } },
23
+ * ]
24
+ * })
25
+ * ```
26
+ */
27
+ import { DEFAULT_BLOCK_LAYOUT } from '@pwfabric/core';
28
+ import { blockRegistry } from '@pwfabric/runtime/blocks';
29
+ // ============================================================
30
+ // ID GENERATION
31
+ // ============================================================
32
+ let idCounter = 0;
33
+ /**
34
+ * Generate a unique block ID
35
+ */
36
+ function generateBlockId(type) {
37
+ idCounter += 1;
38
+ return `${type}-${idCounter}-${Date.now().toString(36)}`;
39
+ }
40
+ /**
41
+ * Reset the ID counter (useful for testing)
42
+ */
43
+ export function resetIdCounter() {
44
+ idCounter = 0;
45
+ }
46
+ // ============================================================
47
+ // VALIDATION
48
+ // ============================================================
49
+ /**
50
+ * Validate factory identifier
51
+ */
52
+ function validateFactoryId(id) {
53
+ if (typeof id !== 'string') {
54
+ throw new Error('Factory id must be a string');
55
+ }
56
+ if (id.length < 2 || id.length > 50) {
57
+ throw new Error('Factory id must be 2-50 characters');
58
+ }
59
+ const kebabCaseRegex = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
60
+ if (!kebabCaseRegex.test(id)) {
61
+ throw new Error(`Factory id "${id}" must be kebab-case (lowercase letters, numbers, hyphens, starting with a letter)`);
62
+ }
63
+ }
64
+ /**
65
+ * Validate factory config against schema
66
+ */
67
+ function validateConfig(config, schema) {
68
+ if (!schema) {
69
+ // No schema, accept any config
70
+ return {
71
+ valid: true,
72
+ config: config,
73
+ };
74
+ }
75
+ const result = schema.safeParse(config);
76
+ if (result.success) {
77
+ return {
78
+ valid: true,
79
+ config: result.data,
80
+ };
81
+ }
82
+ const errors = result.error.errors.map((e) => ({
83
+ path: e.path.join('.'),
84
+ message: e.message,
85
+ }));
86
+ return {
87
+ valid: false,
88
+ errors,
89
+ };
90
+ }
91
+ // ============================================================
92
+ // BLOCK SPEC TO BLOCK
93
+ // ============================================================
94
+ /**
95
+ * Convert a BlockSpec (without id) to a Block (with id)
96
+ */
97
+ function specToBlock(spec) {
98
+ const block = {
99
+ id: generateBlockId(spec.type),
100
+ type: spec.type,
101
+ props: spec.props,
102
+ layout: blockRegistry.get(spec.type)?.defaultLayout ?? DEFAULT_BLOCK_LAYOUT,
103
+ };
104
+ if (spec.children && spec.children.length > 0) {
105
+ return {
106
+ ...block,
107
+ children: spec.children.map(specToBlock),
108
+ };
109
+ }
110
+ return block;
111
+ }
112
+ // ============================================================
113
+ // DEFINE FACTORY
114
+ // ============================================================
115
+ /**
116
+ * Define a factory function that generates block compositions
117
+ *
118
+ * Factories allow you to create reusable block patterns that can be
119
+ * customized with configuration. They automatically generate unique
120
+ * block IDs and validate configuration against an optional schema.
121
+ *
122
+ * @param options - Factory definition options
123
+ * @returns A frozen factory definition
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * import { defineFactory } from '@pwfabric/authoring'
128
+ * import { z } from 'zod'
129
+ *
130
+ * // Define a pricing section factory
131
+ * const PricingSectionFactory = defineFactory({
132
+ * id: 'pricing-section',
133
+ * name: 'Pricing Section',
134
+ * description: 'Create a pricing section with multiple tiers',
135
+ * configSchema: z.object({
136
+ * title: z.string(),
137
+ * tiers: z.array(z.object({
138
+ * name: z.string(),
139
+ * price: z.number(),
140
+ * features: z.array(z.string()),
141
+ * })),
142
+ * }),
143
+ * build: (config) => [
144
+ * {
145
+ * type: 'container',
146
+ * props: { direction: 'column', gap: 32 },
147
+ * children: [
148
+ * { type: 'heading', props: { text: config.title, level: 'h2' } },
149
+ * {
150
+ * type: 'grid',
151
+ * props: { columns: config.tiers.length },
152
+ * children: config.tiers.map((tier) => ({
153
+ * type: 'pricing-card',
154
+ * props: {
155
+ * title: tier.name,
156
+ * price: tier.price,
157
+ * features: tier.features,
158
+ * },
159
+ * })),
160
+ * },
161
+ * ],
162
+ * },
163
+ * ],
164
+ * })
165
+ *
166
+ * // Use the factory
167
+ * const blocks = PricingSectionFactory.build({
168
+ * title: 'Choose Your Plan',
169
+ * tiers: [
170
+ * { name: 'Basic', price: 9, features: ['Feature 1'] },
171
+ * { name: 'Pro', price: 29, features: ['Feature 1', 'Feature 2'] },
172
+ * ],
173
+ * })
174
+ * ```
175
+ */
176
+ export function defineFactory(options) {
177
+ // Validate required fields
178
+ validateFactoryId(options.id);
179
+ if (typeof options.build !== 'function') {
180
+ throw new Error('Factory build function is required');
181
+ }
182
+ // Create the build wrapper that converts specs to blocks
183
+ const buildWithIds = (config) => {
184
+ const specs = options.build(config);
185
+ return specs.map(specToBlock);
186
+ };
187
+ // Create the validation function
188
+ const validateConfigFn = (config) => {
189
+ return validateConfig(config, options.configSchema);
190
+ };
191
+ const definition = {
192
+ id: options.id,
193
+ name: options.name ?? options.id,
194
+ description: options.description ?? '',
195
+ build: buildWithIds,
196
+ validateConfig: validateConfigFn,
197
+ // Only include configSchema if it's defined
198
+ ...(options.configSchema !== undefined && { configSchema: options.configSchema }),
199
+ };
200
+ return Object.freeze(definition);
201
+ }
202
+ // ============================================================
203
+ // UTILITY FUNCTIONS
204
+ // ============================================================
205
+ /**
206
+ * Check if a value is a factory definition
207
+ */
208
+ export function isFactoryDefinition(value) {
209
+ if (!value || typeof value !== 'object') {
210
+ return false;
211
+ }
212
+ const def = value;
213
+ return (typeof def.id === 'string' &&
214
+ typeof def.name === 'string' &&
215
+ typeof def.build === 'function' &&
216
+ typeof def.validateConfig === 'function');
217
+ }
218
+ /**
219
+ * Compose multiple factory outputs into a single block array
220
+ *
221
+ * @param factories - Array of factory output block arrays
222
+ * @returns Combined block array
223
+ */
224
+ export function composeFactoryOutputs(...factories) {
225
+ return factories.flat();
226
+ }
227
+ /**
228
+ * Wrap factory output in a container block
229
+ *
230
+ * @param blocks - Factory output blocks
231
+ * @param containerProps - Props for the wrapper container
232
+ * @returns Single container block with children
233
+ */
234
+ export function wrapInContainer(blocks, containerProps = {}) {
235
+ return {
236
+ id: generateBlockId('container'),
237
+ type: 'container',
238
+ props: {
239
+ direction: 'column',
240
+ gap: 24,
241
+ ...containerProps,
242
+ },
243
+ layout: blockRegistry.get('container')?.defaultLayout ?? DEFAULT_BLOCK_LAYOUT,
244
+ children: [...blocks],
245
+ };
246
+ }
247
+ //# sourceMappingURL=define-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-factory.js","sourceRoot":"","sources":["../src/define-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @pwfabric/authoring
3
+ *
4
+ * The surface a pack author writes against: define a block, compose a factory,
5
+ * declare a capability, register and validate what you built.
6
+ *
7
+ * It holds no HTTP client: talking to a hosting service is that service's
8
+ * own package. The scaffolding templates in the authoring tooling emit
9
+ * `import { defineBlock } from ...`, so this is the module name a third-party
10
+ * author reads first.
11
+ *
12
+ * @module @pwfabric/authoring
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { defineBlock, createCustomBlockRegistry } from '@pwfabric/authoring'
17
+ * import { z } from 'zod'
18
+ *
19
+ * const MyBlock = defineBlock({
20
+ * type: 'my-block',
21
+ * name: 'My Block',
22
+ * schema: z.object({ title: z.string() }),
23
+ * defaultProps: { title: 'Default' },
24
+ * component: ({ props }) => <div>{props.title}</div>
25
+ * })
26
+ *
27
+ * const registry = createCustomBlockRegistry()
28
+ * registry.register(MyBlock)
29
+ * ```
30
+ */
31
+ export * from '@pwfabric/runtime';
32
+ export type { CustomBlockOptions, CustomBlockComponentProps, CustomBlockComponent, CustomBlockContext, CustomBlockDefinition, FactoryConfig, BlockSpec, FactoryOptions, FactoryDefinition, FactoryValidationResult, FactoryValidationError, ICustomBlockRegistry, BlockValidationResult, BlockValidationError, PropsValidationResult, InferBlockProps, InferFactoryConfig, InferSchemaProps, } from './types.js';
33
+ export { defineBlock, isCustomBlockDefinition, createBlockInstance } from './define-block.js';
34
+ export { validateBlockDefinition } from './define-block.js';
35
+ export type { BlockDefinitionIssue } from './define-block.js';
36
+ export { defineFactory, isFactoryDefinition, composeFactoryOutputs, wrapInContainer, resetIdCounter, } from './define-factory.js';
37
+ export { CapabilityBuilder, defineCapability } from '@pwfabric/contracts';
38
+ export { CustomBlockRegistry, createCustomBlockRegistry, getCustomBlockRegistry, resetGlobalRegistry, mergeRegistries, mergeWithBaseComponents, } from './registry.js';
39
+ export { validateProps, validatePropsWithDefaults, validateBlock, validateBlockTree, createBlockValidator, createPropsValidator, formatValidationErrors, hasErrors, isBlock, isBlockArray, } from './validation.js';
40
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,cAAc,mBAAmB,CAAA;AAMjC,YAAY,EAEV,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EAGrB,aAAa,EACb,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EAGtB,oBAAoB,EAGpB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EAGrB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,YAAY,CAAA;AAMnB,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAM7D,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,cAAc,GACf,MAAM,qBAAqB,CAAA;AAM5B,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAMzE,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,uBAAuB,GACxB,MAAM,eAAe,CAAA;AAMtB,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,OAAO,EACP,YAAY,GACb,MAAM,iBAAiB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @pwfabric/authoring
3
+ *
4
+ * The surface a pack author writes against: define a block, compose a factory,
5
+ * declare a capability, register and validate what you built.
6
+ *
7
+ * It holds no HTTP client: talking to a hosting service is that service's
8
+ * own package. The scaffolding templates in the authoring tooling emit
9
+ * `import { defineBlock } from ...`, so this is the module name a third-party
10
+ * author reads first.
11
+ *
12
+ * @module @pwfabric/authoring
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { defineBlock, createCustomBlockRegistry } from '@pwfabric/authoring'
17
+ * import { z } from 'zod'
18
+ *
19
+ * const MyBlock = defineBlock({
20
+ * type: 'my-block',
21
+ * name: 'My Block',
22
+ * schema: z.object({ title: z.string() }),
23
+ * defaultProps: { title: 'Default' },
24
+ * component: ({ props }) => <div>{props.title}</div>
25
+ * })
26
+ *
27
+ * const registry = createCustomBlockRegistry()
28
+ * registry.register(MyBlock)
29
+ * ```
30
+ */
31
+ // Re-export runtime (which includes core and contracts)
32
+ export * from '@pwfabric/runtime';
33
+ // ============================================================
34
+ // DEFINE BLOCK API
35
+ // ============================================================
36
+ export { defineBlock, isCustomBlockDefinition, createBlockInstance } from './define-block.js';
37
+ // single-source field-severity gate for authoring/install.
38
+ export { validateBlockDefinition } from './define-block.js';
39
+ // ============================================================
40
+ // DEFINE FACTORY API
41
+ // ============================================================
42
+ export { defineFactory, isFactoryDefinition, composeFactoryOutputs, wrapInContainer, resetIdCounter, } from './define-factory.js';
43
+ // ============================================================
44
+ // DEFINE CAPABILITY API
45
+ // ============================================================
46
+ export { CapabilityBuilder, defineCapability } from '@pwfabric/contracts';
47
+ // ============================================================
48
+ // REGISTRY API
49
+ // ============================================================
50
+ export { CustomBlockRegistry, createCustomBlockRegistry, getCustomBlockRegistry, resetGlobalRegistry, mergeRegistries, mergeWithBaseComponents, } from './registry.js';
51
+ // ============================================================
52
+ // VALIDATION API
53
+ // ============================================================
54
+ export { validateProps, validatePropsWithDefaults, validateBlock, validateBlockTree, createBlockValidator, createPropsValidator, formatValidationErrors, hasErrors, isBlock, isBlockArray, } from './validation.js';
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,wDAAwD;AACxD,cAAc,mBAAmB,CAAA;AAoCjC,+DAA+D;AAC/D,mBAAmB;AACnB,+DAA+D;AAE/D,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC7F,2DAA2D;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAG3D,+DAA+D;AAC/D,qBAAqB;AACrB,+DAA+D;AAE/D,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,EACf,cAAc,GACf,MAAM,qBAAqB,CAAA;AAE5B,+DAA+D;AAC/D,wBAAwB;AACxB,+DAA+D;AAE/D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAEzE,+DAA+D;AAC/D,eAAe;AACf,+DAA+D;AAE/D,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,uBAAuB,GACxB,MAAM,eAAe,CAAA;AAEtB,+DAA+D;AAC/D,iBAAiB;AACjB,+DAA+D;AAE/D,OAAO,EACL,aAAa,EACb,yBAAyB,EACzB,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,OAAO,EACP,YAAY,GACb,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * CustomBlockRegistry
3
+ *
4
+ * Registry for managing custom block definitions.
5
+ *
6
+ * @module @pwfabric/authoring/registry
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createCustomBlockRegistry, defineBlock } from '@pwfabric/authoring'
11
+ * import { z } from 'zod'
12
+ *
13
+ * const registry = createCustomBlockRegistry()
14
+ *
15
+ * const MyBlock = defineBlock({
16
+ * type: 'my-block',
17
+ * name: 'My Block',
18
+ * schema: z.object({ title: z.string() }),
19
+ * defaultProps: { title: 'Default' },
20
+ * component: ({ props }) => <div>{props.title}</div>
21
+ * })
22
+ *
23
+ * registry.register(MyBlock)
24
+ *
25
+ * // Use with SurfaceRenderer
26
+ * <SurfaceRenderer components={registry.getComponents()} />
27
+ * ```
28
+ */
29
+ import type { BlockCategory } from '@pwfabric/core';
30
+ import type { BlockComponentRegistry } from '@pwfabric/runtime';
31
+ import type { CustomBlockDefinition, ICustomBlockRegistry } from './types.js';
32
+ /**
33
+ * CustomBlockRegistry
34
+ *
35
+ * Manages registration and retrieval of custom block definitions.
36
+ * Provides a bridge between custom block definitions and the
37
+ * SurfaceRenderer component registry.
38
+ */
39
+ export declare class CustomBlockRegistry implements ICustomBlockRegistry {
40
+ private readonly definitions;
41
+ /**
42
+ * Register a custom block definition
43
+ *
44
+ * @param definition - The custom block definition to register
45
+ * @throws Error if block type already registered
46
+ */
47
+ register<TProps extends Record<string, unknown>>(definition: CustomBlockDefinition<TProps>): void;
48
+ /**
49
+ * Register multiple custom block definitions
50
+ *
51
+ * @param definitions - Array of custom block definitions
52
+ */
53
+ registerMany(definitions: readonly CustomBlockDefinition[]): void;
54
+ /**
55
+ * Get a custom block definition by type
56
+ *
57
+ * @param type - Block type identifier
58
+ * @returns The block definition or undefined
59
+ */
60
+ get(type: string): CustomBlockDefinition | undefined;
61
+ /**
62
+ * Check if a block type is registered
63
+ *
64
+ * @param type - Block type identifier
65
+ * @returns True if registered
66
+ */
67
+ has(type: string): boolean;
68
+ /**
69
+ * Get all registered custom block definitions
70
+ *
71
+ * @returns Array of all block definitions
72
+ */
73
+ list(): readonly CustomBlockDefinition[];
74
+ /**
75
+ * Get block definitions by category
76
+ *
77
+ * @param category - Block category
78
+ * @returns Array of block definitions in category
79
+ */
80
+ getByCategory(category: BlockCategory): readonly CustomBlockDefinition[];
81
+ /**
82
+ * Get all registered block types
83
+ *
84
+ * @returns Array of block type identifiers
85
+ */
86
+ types(): readonly string[];
87
+ /**
88
+ * Unregister a custom block
89
+ *
90
+ * @param type - Block type identifier
91
+ * @returns True if block was unregistered
92
+ */
93
+ unregister(type: string): boolean;
94
+ /**
95
+ * Clear all registrations
96
+ */
97
+ clear(): void;
98
+ /**
99
+ * Get number of registered blocks
100
+ */
101
+ get size(): number;
102
+ /**
103
+ * Get a component registry for use with SurfaceRenderer
104
+ *
105
+ * This method creates a BlockComponentRegistry that can be passed
106
+ * to the SurfaceRenderer's `components` prop to enable rendering
107
+ * of custom blocks.
108
+ *
109
+ * @returns BlockComponentRegistry with all registered custom blocks
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * import { SurfaceRenderer } from '@pwfabric/runtime'
114
+ *
115
+ * const registry = createCustomBlockRegistry()
116
+ * registry.register(MyCustomBlock)
117
+ *
118
+ * // Pass to SurfaceRenderer
119
+ * <SurfaceRenderer
120
+ * surface={mySurface}
121
+ * components={registry.getComponents()}
122
+ * />
123
+ * ```
124
+ */
125
+ getComponents(): BlockComponentRegistry;
126
+ }
127
+ /**
128
+ * Create a new CustomBlockRegistry
129
+ *
130
+ * @returns A new CustomBlockRegistry instance
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * const registry = createCustomBlockRegistry()
135
+ * registry.register(MyBlock)
136
+ * ```
137
+ */
138
+ export declare function createCustomBlockRegistry(): CustomBlockRegistry;
139
+ export declare function getCustomBlockRegistry(): CustomBlockRegistry;
140
+ /**
141
+ * Reset the global registry
142
+ *
143
+ * Useful for testing or when you need to clear all registrations.
144
+ */
145
+ export declare function resetGlobalRegistry(): void;
146
+ /**
147
+ * Merge multiple custom block registries into one
148
+ *
149
+ * @param registries - Registries to merge
150
+ * @returns A new registry containing all blocks from input registries
151
+ * @throws Error if there are duplicate block types
152
+ */
153
+ export declare function mergeRegistries(...registries: readonly CustomBlockRegistry[]): CustomBlockRegistry;
154
+ /**
155
+ * Merge a custom block registry with a base BlockComponentRegistry
156
+ *
157
+ * This is useful when you want to extend the default block components
158
+ * with custom blocks.
159
+ *
160
+ * @param baseComponents - The base component registry (e.g., defaultBlockComponents)
161
+ * @param customRegistry - The custom block registry
162
+ * @returns A merged BlockComponentRegistry
163
+ */
164
+ export declare function mergeWithBaseComponents(baseComponents: BlockComponentRegistry, customRegistry: CustomBlockRegistry): BlockComponentRegistry;
165
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAS,MAAM,gBAAgB,CAAA;AAC1D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAC/D,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EAGrB,MAAM,YAAY,CAAA;AAOnB;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,oBAAoB;IAC9D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2C;IAEvE;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,UAAU,EAAE,qBAAqB,CAAC,MAAM,CAAC,GACxC,IAAI;IAOP;;;;OAIG;IACH,YAAY,CAAC,WAAW,EAAE,SAAS,qBAAqB,EAAE,GAAG,IAAI;IAMjE;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAIpD;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;;;OAIG;IACH,IAAI,IAAI,SAAS,qBAAqB,EAAE;IAIxC;;;;;OAKG;IACH,aAAa,CAAC,QAAQ,EAAE,aAAa,GAAG,SAAS,qBAAqB,EAAE;IAIxE;;;;OAIG;IACH,KAAK,IAAI,SAAS,MAAM,EAAE;IAI1B;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,aAAa,IAAI,sBAAsB;CASxC;AA4ED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,IAAI,mBAAmB,CAE/D;AAUD,wBAAgB,sBAAsB,IAAI,mBAAmB,CAK5D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,GAAG,UAAU,EAAE,SAAS,mBAAmB,EAAE,GAC5C,mBAAmB,CAUrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,sBAAsB,EACtC,cAAc,EAAE,mBAAmB,GAClC,sBAAsB,CAKxB"}