@bagelink/blox 1.5.17 → 1.5.20
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/blox.css +720 -68
- package/dist/components/base/Button.vue.d.ts.map +1 -1
- package/dist/components/base/Container.vue.d.ts.map +1 -1
- package/dist/components/base/Image.vue.d.ts.map +1 -1
- package/dist/components/base/Spacer.vue.d.ts.map +1 -1
- package/dist/components/base/Text.vue.d.ts.map +1 -1
- package/dist/components/base/Title.vue.d.ts.map +1 -1
- package/dist/components/blocks/BigImage.vue.d.ts +12 -0
- package/dist/components/blocks/BigImage.vue.d.ts.map +1 -0
- package/dist/components/blocks/BigQuote.vue.d.ts +14 -0
- package/dist/components/blocks/BigQuote.vue.d.ts.map +1 -0
- package/dist/components/blocks/BlockFooter.vue.d.ts +17 -0
- package/dist/components/blocks/BlockFooter.vue.d.ts.map +1 -0
- package/dist/components/blocks/BlockNav.vue.d.ts +22 -0
- package/dist/components/blocks/BlockNav.vue.d.ts.map +1 -0
- package/dist/components/blocks/Cards.vue.d.ts +18 -0
- package/dist/components/blocks/Cards.vue.d.ts.map +1 -0
- package/dist/components/blocks/Contact.vue.d.ts +22 -0
- package/dist/components/blocks/Contact.vue.d.ts.map +1 -0
- package/dist/components/blocks/CountDown.vue.d.ts +76 -0
- package/dist/components/blocks/CountDown.vue.d.ts.map +1 -0
- package/dist/components/blocks/Cta.vue.d.ts +15 -0
- package/dist/components/blocks/Cta.vue.d.ts.map +1 -0
- package/dist/components/blocks/Faq.vue.d.ts +20 -0
- package/dist/components/blocks/Faq.vue.d.ts.map +1 -0
- package/dist/components/blocks/Grid.vue.d.ts +24 -0
- package/dist/components/blocks/Grid.vue.d.ts.map +1 -0
- package/dist/components/blocks/Icons.vue.d.ts +16 -0
- package/dist/components/blocks/Icons.vue.d.ts.map +1 -0
- package/dist/components/blocks/IconsList.vue.d.ts +22 -0
- package/dist/components/blocks/IconsList.vue.d.ts.map +1 -0
- package/dist/components/blocks/ImageCarousel.vue.d.ts +16 -0
- package/dist/components/blocks/ImageCarousel.vue.d.ts.map +1 -0
- package/dist/components/blocks/ImageLinkBoxes.vue.d.ts +14 -0
- package/dist/components/blocks/ImageLinkBoxes.vue.d.ts.map +1 -0
- package/dist/components/blocks/Logos.vue.d.ts +17 -0
- package/dist/components/blocks/Logos.vue.d.ts.map +1 -0
- package/dist/components/blocks/PopUp.vue.d.ts +23 -0
- package/dist/components/blocks/PopUp.vue.d.ts.map +1 -0
- package/dist/components/blocks/PriceTable.vue.d.ts +24 -0
- package/dist/components/blocks/PriceTable.vue.d.ts.map +1 -0
- package/dist/components/blocks/Space.vue.d.ts +25 -0
- package/dist/components/blocks/Space.vue.d.ts.map +1 -0
- package/dist/components/blocks/Tabs.vue.d.ts +15 -0
- package/dist/components/blocks/Tabs.vue.d.ts.map +1 -0
- package/dist/components/blocks/Team.vue.d.ts +19 -0
- package/dist/components/blocks/Team.vue.d.ts.map +1 -0
- package/dist/components/blocks/Testimonials.vue.d.ts +18 -0
- package/dist/components/blocks/Testimonials.vue.d.ts.map +1 -0
- package/dist/components/blocks/Text.vue.d.ts +10 -0
- package/dist/components/blocks/Text.vue.d.ts.map +1 -0
- package/dist/components/blocks/TextImage.vue.d.ts +20 -0
- package/dist/components/blocks/TextImage.vue.d.ts.map +1 -0
- package/dist/components/blocks/TextSide.vue.d.ts +19 -0
- package/dist/components/blocks/TextSide.vue.d.ts.map +1 -0
- package/dist/components/blocks/Title.vue.d.ts +16 -0
- package/dist/components/blocks/Title.vue.d.ts.map +1 -0
- package/dist/components/blocks/TitleSide.vue.d.ts +21 -0
- package/dist/components/blocks/TitleSide.vue.d.ts.map +1 -0
- package/dist/components/blocks/VideoBox.vue.d.ts +15 -0
- package/dist/components/blocks/VideoBox.vue.d.ts.map +1 -0
- package/dist/components/blocks/blocks.d.ts +27 -0
- package/dist/components/blocks/blocks.d.ts.map +1 -0
- package/dist/components/index.d.ts +4 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/config/baseComponents.d.ts.map +1 -1
- package/dist/config/blockComponents.d.ts +41 -0
- package/dist/config/blockComponents.d.ts.map +1 -0
- package/dist/core/communication.d.ts.map +1 -1
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/renderer.d.ts.map +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.cjs +9223 -472
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +9124 -458
- package/dist/setup.d.ts +4 -4
- package/dist/setup.d.ts.map +1 -1
- package/dist/utils/componentPreviewGenerator.d.ts +113 -0
- package/dist/utils/componentPreviewGenerator.d.ts.map +1 -0
- package/dist/utils/normalizer.d.ts.map +1 -1
- package/dist/utils/styles.d.ts.map +1 -1
- package/dist/views/ExternalPreview.vue.d.ts.map +1 -1
- package/dist/views/RenderPage.vue.d.ts.map +1 -1
- package/package.json +3 -2
- package/components/base/Button.vue +0 -140
- package/components/base/Container.vue +0 -64
- package/components/base/Image.vue +0 -75
- package/components/base/Spacer.vue +0 -33
- package/components/base/Text.vue +0 -37
- package/components/base/Title.vue +0 -55
- package/components/index.ts +0 -20
- package/config/baseComponents.ts +0 -364
- package/core/communication.ts +0 -140
- package/core/registry.ts +0 -108
- package/core/renderer.ts +0 -217
- package/core/types.ts +0 -148
- package/dist/example-setup.d.ts +0 -1
- package/dist/example-setup.d.ts.map +0 -1
- package/dist/styles.d.ts +0 -8
- package/dist/styles.d.ts.map +0 -1
- package/dist/vite.config.d.ts +0 -3
- package/dist/vite.config.d.ts.map +0 -1
- package/index.ts +0 -43
- package/setup.ts +0 -472
- package/utils/normalizer.ts +0 -74
- package/utils/styles.ts +0 -228
- package/views/ExternalPreview.vue +0 -415
- package/views/RenderPage.vue +0 -127
package/setup.ts
DELETED
|
@@ -1,472 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Blox Setup and Registration
|
|
3
|
-
*
|
|
4
|
-
* Provides a simple, fluent API for setting up the Blox library
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { App } from 'vue'
|
|
8
|
-
import type { Router } from 'vue-router'
|
|
9
|
-
import { baseComponentConfigs, type ComponentConfig } from './config/baseComponents'
|
|
10
|
-
import { registerComponent, registerComponents as registerComponentsInRegistry } from './core/registry'
|
|
11
|
-
import ExternalPreview from './views/ExternalPreview.vue'
|
|
12
|
-
import RenderPage from './views/RenderPage.vue'
|
|
13
|
-
|
|
14
|
-
export interface BloxInstance {
|
|
15
|
-
/**
|
|
16
|
-
* Register one or more components with the Blox library
|
|
17
|
-
* Accepts either a single component config or an array of component configs
|
|
18
|
-
*/
|
|
19
|
-
registerComponents: (
|
|
20
|
-
components: ComponentConfig | ComponentConfig[],
|
|
21
|
-
options?: RegisterOptions
|
|
22
|
-
) => BloxInstance
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Register routes for preview pages with your Vue Router
|
|
26
|
-
*/
|
|
27
|
-
registerRoutes: (router: Router, options?: RouteOptions) => BloxInstance
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Get all registered component configurations
|
|
31
|
-
*/
|
|
32
|
-
getRegisteredComponents: () => ComponentConfig[]
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Get components by category
|
|
36
|
-
*/
|
|
37
|
-
getComponentsByCategory: (category: string) => ComponentConfig[]
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Get a list of registered component IDs
|
|
41
|
-
*/
|
|
42
|
-
getComponentIds: () => string[]
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Check if a component is registered
|
|
46
|
-
*/
|
|
47
|
-
hasComponent: (id: string) => boolean
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Install the Blox plugin into your Vue app
|
|
51
|
-
*/
|
|
52
|
-
install: (app: App) => void
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface RegisterOptions {
|
|
56
|
-
/**
|
|
57
|
-
* Category to assign to the components
|
|
58
|
-
*/
|
|
59
|
-
category?: string
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Skip validation for component configs
|
|
63
|
-
* @default false
|
|
64
|
-
*/
|
|
65
|
-
skipValidation?: boolean
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface RouteOptions {
|
|
69
|
-
/**
|
|
70
|
-
* Base path for the preview routes
|
|
71
|
-
* @default '/blox'
|
|
72
|
-
*/
|
|
73
|
-
basePath?: string
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Path for the external preview route
|
|
77
|
-
* @default '/preview/:pageId?'
|
|
78
|
-
*/
|
|
79
|
-
previewPath?: string
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Path for the render page route
|
|
83
|
-
* @default '/render/:pageId?'
|
|
84
|
-
*/
|
|
85
|
-
renderPath?: string
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Additional route meta properties
|
|
89
|
-
*/
|
|
90
|
-
meta?: Record<string, any>
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export interface BloxOptions {
|
|
94
|
-
/**
|
|
95
|
-
* Enable debug mode for additional logging
|
|
96
|
-
* @default false
|
|
97
|
-
*/
|
|
98
|
-
debug?: boolean
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Automatically register base components on first registerComponents call
|
|
102
|
-
* @default true
|
|
103
|
-
*/
|
|
104
|
-
autoRegisterBaseComponents?: boolean
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Validation error class
|
|
109
|
-
*/
|
|
110
|
-
export class ComponentValidationError extends Error {
|
|
111
|
-
constructor(message: string, public componentId?: string) {
|
|
112
|
-
super(message)
|
|
113
|
-
this.name = 'ComponentValidationError'
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Validate a component configuration
|
|
119
|
-
*/
|
|
120
|
-
function validateComponentConfig(config: ComponentConfig): void {
|
|
121
|
-
const errors: string[] = []
|
|
122
|
-
|
|
123
|
-
if (!config.id || typeof config.id !== 'string') {
|
|
124
|
-
errors.push('Component must have a valid "id" (string)')
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (!config.label || typeof config.label !== 'string') {
|
|
128
|
-
errors.push('Component must have a valid "label" (string)')
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (!config.component) {
|
|
132
|
-
errors.push('Component must have a "component" property (Vue component or async function)')
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (config.component && typeof config.component !== 'function' && typeof config.component !== 'object') {
|
|
136
|
-
errors.push('Component "component" must be a Vue component or async function')
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (config.content && !Array.isArray(config.content)) {
|
|
140
|
-
errors.push('Component "content" must be an array')
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (config.settings && !Array.isArray(config.settings)) {
|
|
144
|
-
errors.push('Component "settings" must be an array')
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (errors.length > 0) {
|
|
148
|
-
throw new ComponentValidationError(
|
|
149
|
-
`Invalid component configuration for "${config.id || 'unknown'}":\n${errors.map(e => ` - ${e}`).join('\n')}`,
|
|
150
|
-
config.id
|
|
151
|
-
)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Calculate Levenshtein distance between two strings
|
|
157
|
-
* Used for "did you mean" suggestions
|
|
158
|
-
*/
|
|
159
|
-
function levenshteinDistance(a: string, b: string): number {
|
|
160
|
-
const matrix: number[][] = []
|
|
161
|
-
|
|
162
|
-
for (let i = 0; i <= b.length; i++) {
|
|
163
|
-
matrix[i] = [i]
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
for (let j = 0; j <= a.length; j++) {
|
|
167
|
-
matrix[0][j] = j
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
for (let i = 1; i <= b.length; i++) {
|
|
171
|
-
for (let j = 1; j <= a.length; j++) {
|
|
172
|
-
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
173
|
-
matrix[i][j] = matrix[i - 1][j - 1]
|
|
174
|
-
} else {
|
|
175
|
-
matrix[i][j] = Math.min(
|
|
176
|
-
matrix[i - 1][j - 1] + 1,
|
|
177
|
-
matrix[i][j - 1] + 1,
|
|
178
|
-
matrix[i - 1][j] + 1
|
|
179
|
-
)
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return matrix[b.length][a.length]
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Find similar component IDs (for "did you mean" suggestions)
|
|
189
|
-
*/
|
|
190
|
-
function findSimilarIds(targetId: string, allIds: string[], maxSuggestions: number = 3): string[] {
|
|
191
|
-
return allIds
|
|
192
|
-
.map(id => ({ id, distance: levenshteinDistance(targetId.toLowerCase(), id.toLowerCase()) }))
|
|
193
|
-
.filter(item => item.distance <= 3) // Only show suggestions within 3 edits
|
|
194
|
-
.sort((a, b) => a.distance - b.distance)
|
|
195
|
-
.slice(0, maxSuggestions)
|
|
196
|
-
.map(item => item.id)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Create better error message for missing component
|
|
201
|
-
*/
|
|
202
|
-
function createMissingComponentError(id: string, registeredIds: string[]): Error {
|
|
203
|
-
const suggestions = findSimilarIds(id, registeredIds)
|
|
204
|
-
let message = `Component "${id}" is not registered.`
|
|
205
|
-
|
|
206
|
-
if (suggestions.length > 0) {
|
|
207
|
-
message += `\n\nDid you mean: ${suggestions.map(s => `"${s}"`).join(', ')}?`
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
message += `\n\nAvailable components: ${registeredIds.join(', ')}`
|
|
211
|
-
|
|
212
|
-
return new Error(message)
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Create a new Blox instance with a fluent API
|
|
217
|
-
*
|
|
218
|
-
* @param options - Configuration options for the Blox instance
|
|
219
|
-
*
|
|
220
|
-
* @example
|
|
221
|
-
* ```ts
|
|
222
|
-
* import { createBlox, ButtonConfig, TextConfig } from '@bagelink/blox'
|
|
223
|
-
* import { MyCustomComp } from './components'
|
|
224
|
-
*
|
|
225
|
-
* const blox = createBlox({ debug: true })
|
|
226
|
-
* blox.registerComponents([ButtonConfig, TextConfig, MyCustomComp])
|
|
227
|
-
* blox.registerRoutes(router)
|
|
228
|
-
*
|
|
229
|
-
* app.use(blox)
|
|
230
|
-
* ```
|
|
231
|
-
*/
|
|
232
|
-
export function createBlox(options: BloxOptions = {}): BloxInstance {
|
|
233
|
-
const {
|
|
234
|
-
debug = false,
|
|
235
|
-
autoRegisterBaseComponents = true,
|
|
236
|
-
} = options
|
|
237
|
-
|
|
238
|
-
const registeredConfigs: ComponentConfig[] = []
|
|
239
|
-
let hasRegisteredBaseComponents = false
|
|
240
|
-
|
|
241
|
-
const log = (...args: any[]) => {
|
|
242
|
-
if (debug) {
|
|
243
|
-
console.log('[Blox]', ...args)
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const instance: BloxInstance = {
|
|
248
|
-
registerComponents(
|
|
249
|
-
components: ComponentConfig | ComponentConfig[],
|
|
250
|
-
registerOptions: RegisterOptions = {}
|
|
251
|
-
) {
|
|
252
|
-
const { category, skipValidation = false } = registerOptions
|
|
253
|
-
const configs = Array.isArray(components) ? components : [components]
|
|
254
|
-
|
|
255
|
-
// Auto-register base components on first call if enabled
|
|
256
|
-
if (!hasRegisteredBaseComponents && autoRegisterBaseComponents) {
|
|
257
|
-
const componentMap: Record<string, any> = {}
|
|
258
|
-
baseComponentConfigs.forEach((config) => {
|
|
259
|
-
componentMap[config.id] = config.component
|
|
260
|
-
registeredConfigs.push(config)
|
|
261
|
-
})
|
|
262
|
-
registerComponentsInRegistry(componentMap)
|
|
263
|
-
hasRegisteredBaseComponents = true
|
|
264
|
-
log('Registered base components:', Object.keys(componentMap))
|
|
265
|
-
if (!debug) {
|
|
266
|
-
console.log('✅ Registered base components:', Object.keys(componentMap))
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Register the provided components
|
|
271
|
-
configs.forEach((config) => {
|
|
272
|
-
// Validate config
|
|
273
|
-
if (!skipValidation) {
|
|
274
|
-
try {
|
|
275
|
-
validateComponentConfig(config)
|
|
276
|
-
} catch (error) {
|
|
277
|
-
if (error instanceof ComponentValidationError) {
|
|
278
|
-
console.error('❌ Component validation failed:')
|
|
279
|
-
console.error(error.message)
|
|
280
|
-
if (debug) {
|
|
281
|
-
console.error('Component config:', config)
|
|
282
|
-
}
|
|
283
|
-
throw error
|
|
284
|
-
}
|
|
285
|
-
throw error
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Apply category if provided in options
|
|
290
|
-
const finalConfig = category ? { ...config, category } : config
|
|
291
|
-
|
|
292
|
-
// Check for duplicate IDs
|
|
293
|
-
if (registeredConfigs.some(c => c.id === finalConfig.id)) {
|
|
294
|
-
const msg = `Component "${finalConfig.id}" is already registered. Overwriting...`
|
|
295
|
-
console.warn(`⚠️ ${msg}`)
|
|
296
|
-
const index = registeredConfigs.findIndex(c => c.id === finalConfig.id)
|
|
297
|
-
registeredConfigs.splice(index, 1)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// For async components, store the factory function
|
|
301
|
-
// They will be resolved when actually needed
|
|
302
|
-
registerComponent(finalConfig.id, finalConfig.component)
|
|
303
|
-
registeredConfigs.push(finalConfig)
|
|
304
|
-
|
|
305
|
-
const categoryMsg = finalConfig.category ? ` (${finalConfig.category})` : ''
|
|
306
|
-
log(`Registered component: ${finalConfig.id}${categoryMsg}`)
|
|
307
|
-
if (!debug) {
|
|
308
|
-
console.log(`✅ Registered component: ${finalConfig.id}${categoryMsg}`)
|
|
309
|
-
}
|
|
310
|
-
})
|
|
311
|
-
|
|
312
|
-
return instance
|
|
313
|
-
},
|
|
314
|
-
|
|
315
|
-
registerRoutes(router: Router, routeOptions: RouteOptions = {}) {
|
|
316
|
-
const {
|
|
317
|
-
basePath = '/blox',
|
|
318
|
-
previewPath = '/preview/:pageId?',
|
|
319
|
-
renderPath = '/render/:pageId?',
|
|
320
|
-
meta = {},
|
|
321
|
-
} = routeOptions
|
|
322
|
-
|
|
323
|
-
// Add the external preview route
|
|
324
|
-
router.addRoute({
|
|
325
|
-
path: `${basePath}${previewPath}`,
|
|
326
|
-
name: 'blox-preview',
|
|
327
|
-
component: ExternalPreview,
|
|
328
|
-
meta: { blox: true, ...meta },
|
|
329
|
-
})
|
|
330
|
-
|
|
331
|
-
// Add the render page route
|
|
332
|
-
router.addRoute({
|
|
333
|
-
path: `${basePath}${renderPath}`,
|
|
334
|
-
name: 'blox-render',
|
|
335
|
-
component: RenderPage,
|
|
336
|
-
meta: { blox: true, ...meta },
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
const routes = {
|
|
340
|
-
preview: `${basePath}${previewPath}`,
|
|
341
|
-
render: `${basePath}${renderPath}`,
|
|
342
|
-
}
|
|
343
|
-
log('Registered Blox routes:', routes)
|
|
344
|
-
if (!debug) {
|
|
345
|
-
console.log('✅ Registered Blox routes:', routes)
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
return instance
|
|
349
|
-
},
|
|
350
|
-
|
|
351
|
-
getRegisteredComponents() {
|
|
352
|
-
return [...registeredConfigs]
|
|
353
|
-
},
|
|
354
|
-
|
|
355
|
-
getComponentsByCategory(category: string) {
|
|
356
|
-
return registeredConfigs.filter(config => config.category === category)
|
|
357
|
-
},
|
|
358
|
-
|
|
359
|
-
getComponentIds() {
|
|
360
|
-
return registeredConfigs.map(config => config.id)
|
|
361
|
-
},
|
|
362
|
-
|
|
363
|
-
hasComponent(id: string) {
|
|
364
|
-
return registeredConfigs.some(config => config.id === id)
|
|
365
|
-
},
|
|
366
|
-
|
|
367
|
-
install(app: App) {
|
|
368
|
-
// Make the registered configs available globally
|
|
369
|
-
app.config.globalProperties.$blox = {
|
|
370
|
-
configs: registeredConfigs,
|
|
371
|
-
getComponent: (id: string) => {
|
|
372
|
-
const config = registeredConfigs.find(c => c.id === id)
|
|
373
|
-
if (!config && debug) {
|
|
374
|
-
const error = createMissingComponentError(id, this.getComponentIds())
|
|
375
|
-
console.error(error.message)
|
|
376
|
-
}
|
|
377
|
-
return config
|
|
378
|
-
},
|
|
379
|
-
getComponentsByCategory: (category: string) => this.getComponentsByCategory(category),
|
|
380
|
-
hasComponent: (id: string) => registeredConfigs.some(c => c.id === id),
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Provide for composition API
|
|
384
|
-
app.provide('blox', {
|
|
385
|
-
configs: registeredConfigs,
|
|
386
|
-
getComponent: (id: string) => {
|
|
387
|
-
const config = registeredConfigs.find(c => c.id === id)
|
|
388
|
-
if (!config && debug) {
|
|
389
|
-
const error = createMissingComponentError(id, this.getComponentIds())
|
|
390
|
-
console.error(error.message)
|
|
391
|
-
}
|
|
392
|
-
return config
|
|
393
|
-
},
|
|
394
|
-
getComponentsByCategory: (category: string) => this.getComponentsByCategory(category),
|
|
395
|
-
hasComponent: (id: string) => registeredConfigs.some(c => c.id === id),
|
|
396
|
-
})
|
|
397
|
-
|
|
398
|
-
log('Blox plugin installed with', registeredConfigs.length, 'components')
|
|
399
|
-
if (!debug) {
|
|
400
|
-
console.log('✅ Blox plugin installed')
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (debug) {
|
|
404
|
-
console.log('[Blox] Registered components:', this.getComponentIds())
|
|
405
|
-
const categories = [
|
|
406
|
-
...new Set(
|
|
407
|
-
registeredConfigs
|
|
408
|
-
.map(c => c.category)
|
|
409
|
-
.filter((cat): cat is string => Boolean(cat))
|
|
410
|
-
)
|
|
411
|
-
]
|
|
412
|
-
console.log('[Blox] Categories:', categories)
|
|
413
|
-
console.log('[Blox] Debug mode enabled')
|
|
414
|
-
}
|
|
415
|
-
},
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
return instance
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* Helper to create a custom component configuration with better TypeScript inference
|
|
423
|
-
*/
|
|
424
|
-
export function createComponentConfig<T extends ComponentConfig>(config: T): T {
|
|
425
|
-
return config
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* Get all component configurations (base + custom)
|
|
430
|
-
* This returns both the Vue components and their editor schemas
|
|
431
|
-
*/
|
|
432
|
-
export function getAllComponentConfigs(customConfigs: ComponentConfig[] = []): ComponentConfig[] {
|
|
433
|
-
return [...baseComponentConfigs, ...customConfigs]
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Register all base components from the library
|
|
438
|
-
* Call this in your project's setup to make base components available
|
|
439
|
-
*
|
|
440
|
-
* @deprecated Use `createBlox().registerComponents()` instead for a simpler API
|
|
441
|
-
*/
|
|
442
|
-
export function registerBaseComponents(): void {
|
|
443
|
-
const componentMap: Record<string, any> = {}
|
|
444
|
-
|
|
445
|
-
baseComponentConfigs.forEach((config) => {
|
|
446
|
-
componentMap[config.id] = config.component
|
|
447
|
-
})
|
|
448
|
-
|
|
449
|
-
registerComponentsInRegistry(componentMap)
|
|
450
|
-
console.log('✅ Registered base components:', Object.keys(componentMap))
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* Register a single custom component
|
|
455
|
-
*
|
|
456
|
-
* @deprecated Use `createBlox().registerComponents()` instead for a simpler API
|
|
457
|
-
*/
|
|
458
|
-
export function registerCustomComponent(config: ComponentConfig): void {
|
|
459
|
-
registerComponent(config.id, config.component)
|
|
460
|
-
console.log(`✅ Registered custom component: ${config.id}`)
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* Register multiple custom components
|
|
465
|
-
*
|
|
466
|
-
* @deprecated Use `createBlox().registerComponents()` instead for a simpler API
|
|
467
|
-
*/
|
|
468
|
-
export function registerCustomComponents(configs: ComponentConfig[]): void {
|
|
469
|
-
configs.forEach((config) => {
|
|
470
|
-
registerCustomComponent(config)
|
|
471
|
-
})
|
|
472
|
-
}
|
package/utils/normalizer.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Data Normalization Utilities
|
|
3
|
-
*
|
|
4
|
-
* Normalizes component data for proper rendering
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Convert string values to proper types for component props
|
|
9
|
-
*/
|
|
10
|
-
export function normalizeComponentData(data: Record<string, any>): Record<string, any> {
|
|
11
|
-
const normalized: Record<string, any> = {}
|
|
12
|
-
|
|
13
|
-
// Fields that should remain as strings even if they look like numbers
|
|
14
|
-
const stringFields = ['title', 'subTitle', 'btnTxt', 'tag', 'customId', 'height', 'url', 'href']
|
|
15
|
-
|
|
16
|
-
for (const [key, value] of Object.entries(data)) {
|
|
17
|
-
if (typeof value === 'string') {
|
|
18
|
-
// Convert string booleans to actual booleans
|
|
19
|
-
if (value === 'true') {
|
|
20
|
-
normalized[key] = true
|
|
21
|
-
} else if (value === 'false') {
|
|
22
|
-
normalized[key] = false
|
|
23
|
-
} else if (!Number.isNaN(Number(value)) && value !== '' && !stringFields.includes(key)) {
|
|
24
|
-
// Convert string numbers to numbers (but not for text fields)
|
|
25
|
-
normalized[key] = Number(value)
|
|
26
|
-
} else {
|
|
27
|
-
normalized[key] = value
|
|
28
|
-
}
|
|
29
|
-
} else {
|
|
30
|
-
normalized[key] = value
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Provide default props to avoid Vue warnings for missing required props
|
|
35
|
-
if (!normalized.items) {
|
|
36
|
-
normalized.items = []
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Ensure height is always a string if it exists
|
|
40
|
-
if (normalized.height !== undefined && typeof normalized.height === 'number') {
|
|
41
|
-
normalized.height = String(normalized.height)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (normalized.height === 'auto') {
|
|
45
|
-
// Convert auto height strings to valid numbers for components that expect numbers
|
|
46
|
-
delete normalized.height
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return normalized
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Deep clone an object
|
|
54
|
-
*/
|
|
55
|
-
export function deepClone<T>(obj: T): T {
|
|
56
|
-
return JSON.parse(JSON.stringify(obj))
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Merge objects deeply
|
|
61
|
-
*/
|
|
62
|
-
export function deepMerge(target: any, source: any): any {
|
|
63
|
-
const result = { ...target }
|
|
64
|
-
|
|
65
|
-
for (const key in source) {
|
|
66
|
-
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
67
|
-
result[key] = deepMerge(result[key] || {}, source[key])
|
|
68
|
-
} else {
|
|
69
|
-
result[key] = source[key]
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return result
|
|
74
|
-
}
|