@bagelink/blox 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +844 -0
- package/components/base/Button.vue +140 -0
- package/components/base/Container.vue +64 -0
- package/components/base/Image.vue +75 -0
- package/components/base/Spacer.vue +33 -0
- package/components/base/Text.vue +37 -0
- package/components/base/Title.vue +55 -0
- package/components/index.ts +20 -0
- package/config/baseComponents.ts +342 -0
- package/core/communication.ts +140 -0
- package/core/registry.ts +108 -0
- package/core/renderer.ts +217 -0
- package/core/types.ts +148 -0
- package/dist/blox.css +296 -0
- package/dist/components/base/Button.vue.d.ts +26 -0
- package/dist/components/base/Button.vue.d.ts.map +1 -0
- package/dist/components/base/Container.vue.d.ts +37 -0
- package/dist/components/base/Container.vue.d.ts.map +1 -0
- package/dist/components/base/Image.vue.d.ts +26 -0
- package/dist/components/base/Image.vue.d.ts.map +1 -0
- package/dist/components/base/Spacer.vue.d.ts +16 -0
- package/dist/components/base/Spacer.vue.d.ts.map +1 -0
- package/dist/components/base/Text.vue.d.ts +13 -0
- package/dist/components/base/Text.vue.d.ts.map +1 -0
- package/dist/components/base/Title.vue.d.ts +14 -0
- package/dist/components/base/Title.vue.d.ts.map +1 -0
- package/dist/components/index.d.ts +18 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/config/baseComponents.d.ts +39 -0
- package/dist/config/baseComponents.d.ts.map +1 -0
- package/dist/core/communication.d.ts +44 -0
- package/dist/core/communication.d.ts.map +1 -0
- package/dist/core/registry.d.ts +56 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/renderer.d.ts +27 -0
- package/dist/core/renderer.d.ts.map +1 -0
- package/dist/core/types.d.ts +105 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/index.cjs +1305 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +1260 -0
- package/dist/setup.d.ts +24 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/utils/normalizer.d.ts +18 -0
- package/dist/utils/normalizer.d.ts.map +1 -0
- package/dist/utils/styles.d.ts +13 -0
- package/dist/utils/styles.d.ts.map +1 -0
- package/dist/views/ExternalPreview.vue.d.ts +12 -0
- package/dist/views/ExternalPreview.vue.d.ts.map +1 -0
- package/dist/views/RenderPage.vue.d.ts +10 -0
- package/dist/views/RenderPage.vue.d.ts.map +1 -0
- package/dist/vite.config.d.ts +3 -0
- package/dist/vite.config.d.ts.map +1 -0
- package/index.ts +27 -0
- package/package.json +94 -0
- package/setup.ts +56 -0
- package/utils/normalizer.ts +74 -0
- package/utils/styles.ts +228 -0
- package/views/ExternalPreview.vue +420 -0
- package/views/RenderPage.vue +127 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Base Button Component
|
|
4
|
+
*
|
|
5
|
+
* A customizable button/link component
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
btnTxt?: string
|
|
10
|
+
btnUrl?: string
|
|
11
|
+
btnTarget?: '_self' | '_blank' | '_parent' | '_top'
|
|
12
|
+
variant?: 'primary' | 'secondary' | 'outline' | 'ghost'
|
|
13
|
+
size?: 'sm' | 'md' | 'lg'
|
|
14
|
+
align?: 'left' | 'center' | 'right'
|
|
15
|
+
fullWidth?: boolean
|
|
16
|
+
isMobile?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
20
|
+
btnTxt: 'Click Me',
|
|
21
|
+
btnUrl: '#',
|
|
22
|
+
btnTarget: '_self',
|
|
23
|
+
variant: 'primary',
|
|
24
|
+
size: 'md',
|
|
25
|
+
align: 'left',
|
|
26
|
+
fullWidth: false,
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
function handleClick(e: MouseEvent) {
|
|
30
|
+
// Emit event for analytics tracking if needed
|
|
31
|
+
console.log('Button clicked:', props.btnTxt)
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<div :class="`button-wrapper align-${align}`">
|
|
37
|
+
<a
|
|
38
|
+
:href="btnUrl"
|
|
39
|
+
:target="btnTarget"
|
|
40
|
+
:rel="btnTarget === '_blank' ? 'noopener noreferrer' : undefined"
|
|
41
|
+
class="btn" :class="[
|
|
42
|
+
`btn-${variant}`,
|
|
43
|
+
`btn-${size}`,
|
|
44
|
+
{ 'btn-full-width': fullWidth },
|
|
45
|
+
]"
|
|
46
|
+
@click="handleClick"
|
|
47
|
+
>
|
|
48
|
+
{{ btnTxt }}
|
|
49
|
+
</a>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<style scoped>
|
|
54
|
+
.button-wrapper {
|
|
55
|
+
display: flex;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.button-wrapper.align-left {
|
|
59
|
+
justify-content: flex-start;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.button-wrapper.align-center {
|
|
63
|
+
justify-content: center;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.button-wrapper.align-right {
|
|
67
|
+
justify-content: flex-end;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.btn {
|
|
71
|
+
display: inline-block;
|
|
72
|
+
padding: 0.75rem 1.5rem;
|
|
73
|
+
text-decoration: none;
|
|
74
|
+
border-radius: 6px;
|
|
75
|
+
font-weight: 500;
|
|
76
|
+
transition: all 0.2s;
|
|
77
|
+
cursor: pointer;
|
|
78
|
+
border: 2px solid transparent;
|
|
79
|
+
text-align: center;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.btn-full-width {
|
|
83
|
+
width: 100%;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Sizes */
|
|
87
|
+
.btn-sm {
|
|
88
|
+
padding: 0.5rem 1rem;
|
|
89
|
+
font-size: 0.875rem;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.btn-md {
|
|
93
|
+
padding: 0.75rem 1.5rem;
|
|
94
|
+
font-size: 1rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.btn-lg {
|
|
98
|
+
padding: 1rem 2rem;
|
|
99
|
+
font-size: 1.125rem;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Variants */
|
|
103
|
+
.btn-primary {
|
|
104
|
+
background: #3b82f6;
|
|
105
|
+
color: white;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.btn-primary:hover {
|
|
109
|
+
background: #2563eb;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.btn-secondary {
|
|
113
|
+
background: #6b7280;
|
|
114
|
+
color: white;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.btn-secondary:hover {
|
|
118
|
+
background: #4b5563;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.btn-outline {
|
|
122
|
+
background: transparent;
|
|
123
|
+
border-color: #3b82f6;
|
|
124
|
+
color: #3b82f6;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.btn-outline:hover {
|
|
128
|
+
background: #3b82f6;
|
|
129
|
+
color: white;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.btn-ghost {
|
|
133
|
+
background: transparent;
|
|
134
|
+
color: #3b82f6;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.btn-ghost:hover {
|
|
138
|
+
background: rgba(59, 130, 246, 0.1);
|
|
139
|
+
}
|
|
140
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Base Container Component
|
|
4
|
+
*
|
|
5
|
+
* A wrapper component for grouping other blocks
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
maxWidth?: number | string
|
|
10
|
+
padding?: number | string
|
|
11
|
+
gap?: number // Gap between child elements in pixels
|
|
12
|
+
layout?: 'vertical' | 'horizontal' | 'grid'
|
|
13
|
+
columns?: number // For grid layout
|
|
14
|
+
isMobile?: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
18
|
+
maxWidth: 1200,
|
|
19
|
+
padding: 20,
|
|
20
|
+
gap: 16,
|
|
21
|
+
layout: 'vertical',
|
|
22
|
+
columns: 3,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const containerStyle = {
|
|
26
|
+
maxWidth: typeof props.maxWidth === 'number' ? `${props.maxWidth}px` : props.maxWidth,
|
|
27
|
+
padding: typeof props.padding === 'number' ? `${props.padding}px` : props.padding,
|
|
28
|
+
gap: `${props.gap}px`,
|
|
29
|
+
}
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<div class="container" :class="[`layout-${layout}`]" :style="containerStyle">
|
|
34
|
+
<slot />
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<style scoped>
|
|
39
|
+
.container {
|
|
40
|
+
margin: 0 auto;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.layout-vertical {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.layout-horizontal {
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-direction: row;
|
|
51
|
+
flex-wrap: wrap;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.layout-grid {
|
|
55
|
+
display: grid;
|
|
56
|
+
grid-template-columns: repeat(v-bind(columns), 1fr);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@media (max-width: 768px) {
|
|
60
|
+
.layout-grid {
|
|
61
|
+
grid-template-columns: 1fr;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Base Image Component
|
|
4
|
+
*
|
|
5
|
+
* Displays an image with optional link and captions
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
src?: string
|
|
10
|
+
alt?: string
|
|
11
|
+
caption?: string
|
|
12
|
+
link?: string
|
|
13
|
+
linkTarget?: '_self' | '_blank' | '_parent' | '_top'
|
|
14
|
+
objectFit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'
|
|
15
|
+
aspectRatio?: string // e.g., '16/9', '4/3', '1/1'
|
|
16
|
+
isMobile?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
20
|
+
src: '',
|
|
21
|
+
alt: '',
|
|
22
|
+
caption: '',
|
|
23
|
+
link: '',
|
|
24
|
+
linkTarget: '_self',
|
|
25
|
+
objectFit: 'cover',
|
|
26
|
+
aspectRatio: 'auto',
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const imageStyle = {
|
|
30
|
+
objectFit: props.objectFit,
|
|
31
|
+
aspectRatio: props.aspectRatio,
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<figure class="image-wrapper">
|
|
37
|
+
<a
|
|
38
|
+
v-if="link"
|
|
39
|
+
:href="link"
|
|
40
|
+
:target="linkTarget"
|
|
41
|
+
:rel="linkTarget === '_blank' ? 'noopener noreferrer' : undefined"
|
|
42
|
+
class="image-link"
|
|
43
|
+
>
|
|
44
|
+
<img :src="src" :alt="alt" :style="imageStyle" class="image">
|
|
45
|
+
</a>
|
|
46
|
+
<img v-else :src="src" :alt="alt" :style="imageStyle" class="image">
|
|
47
|
+
<figcaption v-if="caption" class="image-caption">
|
|
48
|
+
{{ caption }}
|
|
49
|
+
</figcaption>
|
|
50
|
+
</figure>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<style scoped>
|
|
54
|
+
.image-wrapper {
|
|
55
|
+
margin: 0;
|
|
56
|
+
padding: 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.image-link {
|
|
60
|
+
display: block;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.image {
|
|
64
|
+
width: 100%;
|
|
65
|
+
height: auto;
|
|
66
|
+
display: block;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.image-caption {
|
|
70
|
+
margin-top: 0.5rem;
|
|
71
|
+
font-size: 0.875rem;
|
|
72
|
+
color: #6b7280;
|
|
73
|
+
text-align: center;
|
|
74
|
+
}
|
|
75
|
+
</style>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Base Spacer Component
|
|
4
|
+
*
|
|
5
|
+
* Creates vertical spacing between blocks
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
height?: number | string // Height in pixels or 'auto'
|
|
10
|
+
heightMobile?: number | string
|
|
11
|
+
isMobile?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
15
|
+
height: 40,
|
|
16
|
+
heightMobile: undefined,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
function computedHeight() {
|
|
20
|
+
const h = props.isMobile && props.heightMobile ? props.heightMobile : props.height
|
|
21
|
+
return typeof h === 'number' ? `${h}px` : h
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<div class="spacer" :style="{ height: computedHeight() }" />
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<style scoped>
|
|
30
|
+
.spacer {
|
|
31
|
+
width: 100%;
|
|
32
|
+
}
|
|
33
|
+
</style>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Base Text Component
|
|
4
|
+
*
|
|
5
|
+
* A simple text/paragraph component for displaying rich content
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
content?: string
|
|
10
|
+
tag?: 'p' | 'div' | 'span' | 'article' | 'section'
|
|
11
|
+
align?: 'left' | 'center' | 'right' | 'justify'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { content = '', tag = 'div', align = 'left' } = defineProps<Props>()
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<component :is="tag" :class="`text-align-${align}`" v-html="content" />
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<style scoped>
|
|
22
|
+
.text-align-left {
|
|
23
|
+
text-align: left;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.text-align-center {
|
|
27
|
+
text-align: center;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.text-align-right {
|
|
31
|
+
text-align: right;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.text-align-justify {
|
|
35
|
+
text-align: justify;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Base Title Component
|
|
4
|
+
*
|
|
5
|
+
* Renders headings with customizable tag and styling
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
title?: string
|
|
10
|
+
subTitle?: string
|
|
11
|
+
tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
|
|
12
|
+
align?: 'left' | 'center' | 'right'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { title = '', subTitle = '', tag = 'h2', align = 'left' } = defineProps<Props>()
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<div :class="`title-wrapper text-align-${align}`">
|
|
20
|
+
<component :is="tag" v-if="title" class="title">
|
|
21
|
+
{{ title }}
|
|
22
|
+
</component>
|
|
23
|
+
<p v-if="subTitle" class="subtitle">
|
|
24
|
+
{{ subTitle }}
|
|
25
|
+
</p>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<style scoped>
|
|
30
|
+
.title-wrapper {
|
|
31
|
+
margin-bottom: 1rem;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.title {
|
|
35
|
+
margin: 0 0 0.5rem 0;
|
|
36
|
+
line-height: 1.2;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.subtitle {
|
|
40
|
+
margin: 0;
|
|
41
|
+
opacity: 0.8;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.text-align-left {
|
|
45
|
+
text-align: left;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.text-align-center {
|
|
49
|
+
text-align: center;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.text-align-right {
|
|
53
|
+
text-align: right;
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Exports
|
|
3
|
+
*
|
|
4
|
+
* Export all base components for easy importing
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { default as Button } from './base/Button.vue'
|
|
8
|
+
export * from './base/Button.vue'
|
|
9
|
+
export { default as Container } from './base/Container.vue'
|
|
10
|
+
export * from './base/Container.vue'
|
|
11
|
+
export { default as Image } from './base/Image.vue'
|
|
12
|
+
export * from './base/Image.vue'
|
|
13
|
+
|
|
14
|
+
export { default as Spacer } from './base/Spacer.vue'
|
|
15
|
+
export * from './base/Spacer.vue'
|
|
16
|
+
export { default as Text } from './base/Text.vue'
|
|
17
|
+
// Re-export for convenience
|
|
18
|
+
export * from './base/Text.vue'
|
|
19
|
+
export { default as Title } from './base/Title.vue'
|
|
20
|
+
export * from './base/Title.vue'
|