@b10cks/vue 0.9.6

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present – Coder's Cantina e.U.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("vue");class c{static instance;eventListeners={};isEnabled=!1;constructor(){this.isEnabled=this.isIframe()}init(){this.isEnabled&&window&&window.addEventListener("message",this.handleMessage)}static getInstance(){return c.instance||(c.instance=new c),c.instance}isInPreviewMode(){return this.isEnabled}isIframe(){return window&&window.self!==window.top}handleMessage=t=>{if(!t.data||typeof t.data!="object")return;const{type:s,payload:n}=t.data;this.notifyListeners(s,n)};notifyListeners(t,s){const n=this.eventListeners[t];n&&n.forEach(r=>r(s))}on(t,s){return this.isEnabled?(this.eventListeners[t]||(this.eventListeners[t]=[]),this.eventListeners[t].push(s),()=>{this.eventListeners[t]=this.eventListeners[t].filter(n=>n!==s)}):()=>{}}selectItem(t){this.isEnabled&&window.parent.postMessage({type:"SELECT_UPDATE",payload:{selectedItem:t}},"*")}updateField(t,s,n){this.isEnabled&&window.parent.postMessage({type:"FIELD_UPDATE",payload:{itemId:t,field:s,value:n}},"*")}destroy(){this.isEnabled&&(window.removeEventListener("message",this.handleMessage),this.isEnabled=!1),this.eventListeners={}}}const a=c.getInstance(),f={mounted(e,t,s){if(!a.isInPreviewMode())return;const{id:n}=t.value;if(!n){console.warn("v-editable directive requires a block with an id");return}e.classList.add("b10cks-preview");const r=i=>{i.preventDefault(),i.stopPropagation(),a.selectItem(n)},u=({selectedItem:i})=>{s.el&&(i===n?(s.el.classList.add("b10cks-selected"),b(e)):s.el.classList.remove("b10cks-selected"))},l=({selectedItem:i})=>{s.el&&(i===n?s.el.classList.add("b10cks-hover"):s.el.classList.remove("b10cks-hover"))},p=({content:i})=>{if(i&&i.id===n){const d=s.ctx;d.parent.attrs.block=i,d.update(),d.props.block=i,d.update()}};e.addEventListener("click",r),a.on("SELECT_UPDATE",u),a.on("HOVER_UPDATE",l),a.on("CONTENT_UPDATE",p),e._editableCleanup=()=>{e.removeEventListener("click",r)}},updated(e,t,s){a.isInPreviewMode()&&t.value!==t.oldValue&&(e._editableCleanup&&e._editableCleanup(),f.mounted(e,t,s))},unmounted(e){a.isInPreviewMode()&&(e._editableCleanup&&(e._editableCleanup(),delete e._editableCleanup),e.classList.remove("b10cks-preview","b10cks-selected"))}};function b(e){e.scrollIntoView&&e.scrollIntoView({behavior:"smooth"})}if(a.isInPreviewMode()){const e=document.createElement("style");e.innerHTML=`
2
+ .b10cks-hover,
3
+ .b10cks-preview:hover {
4
+ outline: 2px dashed rgba(59, 130, 246, 0.5);
5
+ outline-offset: 2px;
6
+ }
7
+ .b10cks-selected {
8
+ outline: 2px solid rgb(59, 130, 246) !important;
9
+ outline-offset: 2px;
10
+ }
11
+ `,document.head.appendChild(e)}const h={mounted(e,t){const{id:s,field:n}=t.value;a.isInPreviewMode()&&(e.setAttribute("contenteditable","true"),e.addEventListener("input",r=>{a.updateField(s,n,r.target.innerText)}))}},m={key:1},k=o.defineComponent({__name:"B10cksComponent",props:{block:{}},setup(e,{expose:t}){const s=e,n=o.useTemplateRef("blockRef");t({value:n});const r=o.shallowRef(null),u=o.computed(()=>s.block?.block||null);return o.watch(()=>u.value,async l=>{if(!l){r.value=null;return}const p=l.replace(/^([a-z])/,i=>i.toUpperCase()).replace(/([a-z])([A-Z])/g,"$1$2");try{r.value=o.defineAsyncComponent({loader:()=>import(`~/b10cks/${p}.vue`),timeout:3e3,onError:(i,d,v)=>{console.warn(`Failed to load block component for type "${l}":`,i),v()}})}catch(i){console.error(`Error resolving component for block type "${l}":`,i)}},{immediate:!0}),(l,p)=>r.value?(o.openBlock(),o.createBlock(o.resolveDynamicComponent(r.value),o.mergeProps({key:0,ref_key:"blockRef",ref:n},{...l.$props,...l.$attrs}),null,16)):(o.openBlock(),o.createElementBlock("div",m,'Component for block type "'+o.toDisplayString(u.value)+'" not found.',1))}}),E={install(e,t){e.provide("b10cksVueOptions",t),e.directive("editable",f),e.directive("editable-field",h),e.component("B10cksComponent",k)}};exports.B10cksVue=E;exports.previewBridge=a;
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/preview-bridge.ts","../src/directives/v-editable.ts","../src/directives/v-editable-content.ts","../src/components/B10cksComponent.vue","../src/index.ts"],"sourcesContent":["export type ContentUpdateEvent = {\n content: Record<string, any>;\n};\n\nexport type SelectUpdateEvent = {\n selectedItem: string;\n};\n\nexport type EventType = 'CONTENT_UPDATE' | 'SELECT_UPDATE' | 'HOVER_UPDATE';\n\nexport type EventPayloadMap = {\n 'CONTENT_UPDATE': ContentUpdateEvent;\n 'SELECT_UPDATE': SelectUpdateEvent;\n 'HOVER_UPDATE': SelectUpdateEvent;\n};\n\nexport type BridgeEvent = {\n type: EventType;\n payload: ContentUpdateEvent | SelectUpdateEvent;\n b10cksId?: string;\n};\n\ntype EventCallback<T> = (payload: T) => void;\n\nclass PreviewBridge {\n private static instance: PreviewBridge\n private eventListeners: {\n [key in EventType]?: Array<EventCallback<EventPayloadMap[key]>>;\n } = {}\n\n private isEnabled = false\n\n private constructor() {\n this.isEnabled = this.isIframe()\n }\n\n\n public init(): void {\n if (this.isEnabled && window) {\n window.addEventListener('message', this.handleMessage)\n }\n }\n\n public static getInstance(): PreviewBridge {\n if (!PreviewBridge.instance) {\n PreviewBridge.instance = new PreviewBridge()\n }\n return PreviewBridge.instance\n }\n\n public isInPreviewMode(): boolean {\n return this.isEnabled\n }\n\n private isIframe(): boolean {\n return window && window.self !== window.top\n }\n\n private handleMessage = (event: MessageEvent): void => {\n if (!event.data || typeof event.data !== 'object') return\n const { type, payload } = event.data as BridgeEvent\n\n this.notifyListeners(type as EventType, payload)\n }\n\n private notifyListeners<T extends EventType>(type: T, payload: EventPayloadMap[T]): void {\n const listeners = this.eventListeners[type] as Array<EventCallback<EventPayloadMap[T]>> | undefined\n\n if (listeners) {\n listeners.forEach(listener => listener(payload))\n }\n }\n\n public on<T extends EventType>(\n eventType: T,\n callback: EventCallback<EventPayloadMap[T]>\n ): () => void {\n if (!this.isEnabled) return () => {\n }\n\n if (!this.eventListeners[eventType]) {\n this.eventListeners[eventType] = []\n }\n\n (this.eventListeners[eventType] as Array<EventCallback<EventPayloadMap[T]>>).push(callback)\n\n return () => {\n this.eventListeners[eventType] = (this.eventListeners[eventType] as Array<EventCallback<EventPayloadMap[T]>>)\n .filter(listener => listener !== callback) as never\n }\n }\n\n public selectItem(selectedItem: string): void {\n if (!this.isEnabled) return\n\n window.parent.postMessage(\n {\n type: 'SELECT_UPDATE',\n payload: { selectedItem }\n },\n '*'\n )\n }\n\n public updateField(itemId: string, field: string, value: string): void {\n if (!this.isEnabled) return\n\n window.parent.postMessage(\n {\n type: 'FIELD_UPDATE',\n payload: { itemId, field, value }\n },\n '*'\n )\n }\n\n public destroy(): void {\n if (this.isEnabled) {\n window.removeEventListener('message', this.handleMessage)\n this.isEnabled = false\n }\n this.eventListeners = {}\n }\n}\n\nexport const previewBridge = PreviewBridge.getInstance()","import type { DirectiveBinding, VNode } from 'vue'\nimport type { SelectUpdateEvent } from '../preview-bridge'\nimport { previewBridge } from '../preview-bridge'\n\ninterface EditableElement extends HTMLElement {\n _editableCleanup?: () => void\n}\n\nexport const EditableDirective = {\n mounted(el: EditableElement, binding: DirectiveBinding, node: VNode) {\n if (!previewBridge.isInPreviewMode()) return\n const { id: itemId } = binding.value\n\n if (!itemId) {\n console.warn('v-editable directive requires a block with an id')\n return\n }\n\n el.classList.add('b10cks-preview')\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n previewBridge.selectItem(itemId)\n }\n\n const handleSelectionChange = ({ selectedItem }: SelectUpdateEvent) => {\n if (!node.el) return\n\n if (selectedItem === itemId) {\n node.el.classList.add('b10cks-selected')\n scrollIntoViewIfNeeded(el)\n } else {\n node.el.classList.remove('b10cks-selected')\n }\n }\n\n const handleHoverChange = ({ selectedItem }: SelectUpdateEvent) => {\n if (!node.el) return\n\n if (selectedItem === itemId) {\n node.el.classList.add('b10cks-hover')\n } else {\n node.el.classList.remove('b10cks-hover')\n }\n }\n\n const handleUpdate = ({ content }: { content: any }) => {\n if (content && content.id === itemId) {\n const ctx = (node as any).ctx\n ctx.parent.attrs.block = content\n ctx.update()\n ctx.props.block = content\n ctx.update()\n }\n }\n\n el.addEventListener('click', handleClick)\n previewBridge.on('SELECT_UPDATE', handleSelectionChange)\n previewBridge.on('HOVER_UPDATE', handleHoverChange)\n previewBridge.on('CONTENT_UPDATE', handleUpdate)\n\n el._editableCleanup = () => {\n el.removeEventListener('click', handleClick)\n }\n },\n\n updated(el: EditableElement, binding: DirectiveBinding, vnode: VNode) {\n if (!previewBridge.isInPreviewMode()) return\n\n if (binding.value !== binding.oldValue) {\n if (el._editableCleanup) {\n el._editableCleanup()\n }\n\n EditableDirective.mounted(el, binding, vnode)\n }\n },\n\n unmounted(el: EditableElement) {\n if (!previewBridge.isInPreviewMode()) return\n\n if (el._editableCleanup) {\n el._editableCleanup()\n delete el._editableCleanup\n }\n\n el.classList.remove('b10cks-preview', 'b10cks-selected')\n }\n}\n\nfunction scrollIntoViewIfNeeded(el: HTMLElement) {\n if (el.scrollIntoView) {\n el.scrollIntoView({ behavior: 'smooth' })\n }\n}\n\nif (previewBridge.isInPreviewMode()) {\n const style = document.createElement('style')\n style.innerHTML = `\n .b10cks-hover,\n .b10cks-preview:hover {\n outline: 2px dashed rgba(59, 130, 246, 0.5);\n outline-offset: 2px;\n }\n .b10cks-selected {\n outline: 2px solid rgb(59, 130, 246) !important;\n outline-offset: 2px;\n }\n `\n document.head.appendChild(style)\n}","import { previewBridge } from '../preview-bridge'\nimport type { Directive, DirectiveBinding } from 'vue'\n\nexport const EditableContentDirective: Directive<HTMLElement> = {\n mounted(el: HTMLElement, binding: DirectiveBinding) {\n const { id: itemId, field } = binding.value\n if (!previewBridge.isInPreviewMode()) return\n el.setAttribute('contenteditable', 'true')\n\n el.addEventListener('input', (event: Event) => {\n previewBridge.updateField(itemId, field, (event.target as HTMLInputElement).innerText)\n })\n }\n}\n","<script setup lang=\"ts\">\nimport { type Component, computed, watch, useTemplateRef, defineAsyncComponent, shallowRef, inject } from 'vue'\nimport type { IBContent } from '@b10cks/client'\n\nconst props = defineProps<{\n block: IBContent<string> & Record<string, never>,\n}>()\n\nconst blockRef = useTemplateRef('blockRef')\ndefineExpose({ value: blockRef })\n\nconst resolvedComponent = shallowRef<Component | null>(null)\nconst componentName = computed(() => props.block?.block || null)\n\nwatch(() => componentName.value,\n async (newComponentName: string | null) => {\n if (!newComponentName) {\n resolvedComponent.value = null\n return\n }\n\n const pascalCaseBlockType = newComponentName\n .replace(/^([a-z])/, (match: string) => match.toUpperCase())\n .replace(/([a-z])([A-Z])/g, '$1$2')\n\n try {\n resolvedComponent.value = defineAsyncComponent({\n loader: () => import(`~/b10cks/${pascalCaseBlockType}.vue`),\n timeout: 3000,\n onError: (error, retry, fail) => {\n console.warn(`Failed to load block component for type \"${newComponentName}\":`, error)\n fail()\n }\n })\n } catch (error) {\n console.error(`Error resolving component for block type \"${newComponentName}\":`, error)\n }\n },\n { immediate: true }\n)\n</script>\n<template>\n <component :is=\"resolvedComponent\" v-if=\"resolvedComponent\" ref=\"blockRef\" v-bind=\"{ ...$props, ...$attrs }\" />\n <div v-else>Component for block type \"{{ componentName }}\" not found.</div>\n</template>","import type { Plugin } from 'vue'\nimport type { B10cksVuePluginOptions } from './types'\n\nimport { EditableDirective } from './directives/v-editable'\nimport { EditableContentDirective } from './directives/v-editable-content'\nimport B10cksComponent from './components/B10cksComponent.vue'\n\nexport { previewBridge } from './preview-bridge'\n\nexport const B10cksVue: Plugin = {\n install(app, pluginOptions: B10cksVuePluginOptions) {\n app.provide('b10cksVueOptions', pluginOptions)\n\n app.directive('editable', EditableDirective)\n app.directive('editable-field', EditableContentDirective)\n app.component('B10cksComponent', B10cksComponent)\n }\n}"],"names":["PreviewBridge","event","type","payload","listeners","listener","eventType","callback","selectedItem","itemId","field","value","previewBridge","EditableDirective","el","binding","node","handleClick","e","handleSelectionChange","scrollIntoViewIfNeeded","handleHoverChange","handleUpdate","content","ctx","vnode","style","EditableContentDirective","props","__props","blockRef","useTemplateRef","__expose","resolvedComponent","shallowRef","componentName","computed","watch","newComponentName","pascalCaseBlockType","match","defineAsyncComponent","error","retry","fail","_createBlock","_resolveDynamicComponent","_mergeProps","$props","$attrs","_openBlock","_createElementBlock","_hoisted_1","_toDisplayString","B10cksVue","app","pluginOptions","B10cksComponent"],"mappings":"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"}
package/dist/index.mjs ADDED
@@ -0,0 +1,159 @@
1
+ import { defineComponent as b, useTemplateRef as h, shallowRef as m, computed as k, watch as E, defineAsyncComponent as w, createBlock as L, createElementBlock as y, openBlock as p, resolveDynamicComponent as C, mergeProps as I, toDisplayString as g } from "vue";
2
+ class l {
3
+ static instance;
4
+ eventListeners = {};
5
+ isEnabled = !1;
6
+ constructor() {
7
+ this.isEnabled = this.isIframe();
8
+ }
9
+ init() {
10
+ this.isEnabled && window && window.addEventListener("message", this.handleMessage);
11
+ }
12
+ static getInstance() {
13
+ return l.instance || (l.instance = new l()), l.instance;
14
+ }
15
+ isInPreviewMode() {
16
+ return this.isEnabled;
17
+ }
18
+ isIframe() {
19
+ return window && window.self !== window.top;
20
+ }
21
+ handleMessage = (t) => {
22
+ if (!t.data || typeof t.data != "object") return;
23
+ const { type: s, payload: n } = t.data;
24
+ this.notifyListeners(s, n);
25
+ };
26
+ notifyListeners(t, s) {
27
+ const n = this.eventListeners[t];
28
+ n && n.forEach((o) => o(s));
29
+ }
30
+ on(t, s) {
31
+ return this.isEnabled ? (this.eventListeners[t] || (this.eventListeners[t] = []), this.eventListeners[t].push(s), () => {
32
+ this.eventListeners[t] = this.eventListeners[t].filter((n) => n !== s);
33
+ }) : () => {
34
+ };
35
+ }
36
+ selectItem(t) {
37
+ this.isEnabled && window.parent.postMessage(
38
+ {
39
+ type: "SELECT_UPDATE",
40
+ payload: { selectedItem: t }
41
+ },
42
+ "*"
43
+ );
44
+ }
45
+ updateField(t, s, n) {
46
+ this.isEnabled && window.parent.postMessage(
47
+ {
48
+ type: "FIELD_UPDATE",
49
+ payload: { itemId: t, field: s, value: n }
50
+ },
51
+ "*"
52
+ );
53
+ }
54
+ destroy() {
55
+ this.isEnabled && (window.removeEventListener("message", this.handleMessage), this.isEnabled = !1), this.eventListeners = {};
56
+ }
57
+ }
58
+ const r = l.getInstance(), f = {
59
+ mounted(e, t, s) {
60
+ if (!r.isInPreviewMode()) return;
61
+ const { id: n } = t.value;
62
+ if (!n) {
63
+ console.warn("v-editable directive requires a block with an id");
64
+ return;
65
+ }
66
+ e.classList.add("b10cks-preview");
67
+ const o = (i) => {
68
+ i.preventDefault(), i.stopPropagation(), r.selectItem(n);
69
+ }, d = ({ selectedItem: i }) => {
70
+ s.el && (i === n ? (s.el.classList.add("b10cks-selected"), _(e)) : s.el.classList.remove("b10cks-selected"));
71
+ }, a = ({ selectedItem: i }) => {
72
+ s.el && (i === n ? s.el.classList.add("b10cks-hover") : s.el.classList.remove("b10cks-hover"));
73
+ }, u = ({ content: i }) => {
74
+ if (i && i.id === n) {
75
+ const c = s.ctx;
76
+ c.parent.attrs.block = i, c.update(), c.props.block = i, c.update();
77
+ }
78
+ };
79
+ e.addEventListener("click", o), r.on("SELECT_UPDATE", d), r.on("HOVER_UPDATE", a), r.on("CONTENT_UPDATE", u), e._editableCleanup = () => {
80
+ e.removeEventListener("click", o);
81
+ };
82
+ },
83
+ updated(e, t, s) {
84
+ r.isInPreviewMode() && t.value !== t.oldValue && (e._editableCleanup && e._editableCleanup(), f.mounted(e, t, s));
85
+ },
86
+ unmounted(e) {
87
+ r.isInPreviewMode() && (e._editableCleanup && (e._editableCleanup(), delete e._editableCleanup), e.classList.remove("b10cks-preview", "b10cks-selected"));
88
+ }
89
+ };
90
+ function _(e) {
91
+ e.scrollIntoView && e.scrollIntoView({ behavior: "smooth" });
92
+ }
93
+ if (r.isInPreviewMode()) {
94
+ const e = document.createElement("style");
95
+ e.innerHTML = `
96
+ .b10cks-hover,
97
+ .b10cks-preview:hover {
98
+ outline: 2px dashed rgba(59, 130, 246, 0.5);
99
+ outline-offset: 2px;
100
+ }
101
+ .b10cks-selected {
102
+ outline: 2px solid rgb(59, 130, 246) !important;
103
+ outline-offset: 2px;
104
+ }
105
+ `, document.head.appendChild(e);
106
+ }
107
+ const M = {
108
+ mounted(e, t) {
109
+ const { id: s, field: n } = t.value;
110
+ r.isInPreviewMode() && (e.setAttribute("contenteditable", "true"), e.addEventListener("input", (o) => {
111
+ r.updateField(s, n, o.target.innerText);
112
+ }));
113
+ }
114
+ }, D = { key: 1 }, P = /* @__PURE__ */ b({
115
+ __name: "B10cksComponent",
116
+ props: {
117
+ block: {}
118
+ },
119
+ setup(e, { expose: t }) {
120
+ const s = e, n = h("blockRef");
121
+ t({ value: n });
122
+ const o = m(null), d = k(() => s.block?.block || null);
123
+ return E(
124
+ () => d.value,
125
+ async (a) => {
126
+ if (!a) {
127
+ o.value = null;
128
+ return;
129
+ }
130
+ const u = a.replace(/^([a-z])/, (i) => i.toUpperCase()).replace(/([a-z])([A-Z])/g, "$1$2");
131
+ try {
132
+ o.value = w({
133
+ loader: () => import(`~/b10cks/${u}.vue`),
134
+ timeout: 3e3,
135
+ onError: (i, c, v) => {
136
+ console.warn(`Failed to load block component for type "${a}":`, i), v();
137
+ }
138
+ });
139
+ } catch (i) {
140
+ console.error(`Error resolving component for block type "${a}":`, i);
141
+ }
142
+ },
143
+ { immediate: !0 }
144
+ ), (a, u) => o.value ? (p(), L(C(o.value), I({
145
+ key: 0,
146
+ ref_key: "blockRef",
147
+ ref: n
148
+ }, { ...a.$props, ...a.$attrs }), null, 16)) : (p(), y("div", D, 'Component for block type "' + g(d.value) + '" not found.', 1));
149
+ }
150
+ }), x = {
151
+ install(e, t) {
152
+ e.provide("b10cksVueOptions", t), e.directive("editable", f), e.directive("editable-field", M), e.component("B10cksComponent", P);
153
+ }
154
+ };
155
+ export {
156
+ x as B10cksVue,
157
+ r as previewBridge
158
+ };
159
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/preview-bridge.ts","../src/directives/v-editable.ts","../src/directives/v-editable-content.ts","../src/components/B10cksComponent.vue","../src/index.ts"],"sourcesContent":["export type ContentUpdateEvent = {\n content: Record<string, any>;\n};\n\nexport type SelectUpdateEvent = {\n selectedItem: string;\n};\n\nexport type EventType = 'CONTENT_UPDATE' | 'SELECT_UPDATE' | 'HOVER_UPDATE';\n\nexport type EventPayloadMap = {\n 'CONTENT_UPDATE': ContentUpdateEvent;\n 'SELECT_UPDATE': SelectUpdateEvent;\n 'HOVER_UPDATE': SelectUpdateEvent;\n};\n\nexport type BridgeEvent = {\n type: EventType;\n payload: ContentUpdateEvent | SelectUpdateEvent;\n b10cksId?: string;\n};\n\ntype EventCallback<T> = (payload: T) => void;\n\nclass PreviewBridge {\n private static instance: PreviewBridge\n private eventListeners: {\n [key in EventType]?: Array<EventCallback<EventPayloadMap[key]>>;\n } = {}\n\n private isEnabled = false\n\n private constructor() {\n this.isEnabled = this.isIframe()\n }\n\n\n public init(): void {\n if (this.isEnabled && window) {\n window.addEventListener('message', this.handleMessage)\n }\n }\n\n public static getInstance(): PreviewBridge {\n if (!PreviewBridge.instance) {\n PreviewBridge.instance = new PreviewBridge()\n }\n return PreviewBridge.instance\n }\n\n public isInPreviewMode(): boolean {\n return this.isEnabled\n }\n\n private isIframe(): boolean {\n return window && window.self !== window.top\n }\n\n private handleMessage = (event: MessageEvent): void => {\n if (!event.data || typeof event.data !== 'object') return\n const { type, payload } = event.data as BridgeEvent\n\n this.notifyListeners(type as EventType, payload)\n }\n\n private notifyListeners<T extends EventType>(type: T, payload: EventPayloadMap[T]): void {\n const listeners = this.eventListeners[type] as Array<EventCallback<EventPayloadMap[T]>> | undefined\n\n if (listeners) {\n listeners.forEach(listener => listener(payload))\n }\n }\n\n public on<T extends EventType>(\n eventType: T,\n callback: EventCallback<EventPayloadMap[T]>\n ): () => void {\n if (!this.isEnabled) return () => {\n }\n\n if (!this.eventListeners[eventType]) {\n this.eventListeners[eventType] = []\n }\n\n (this.eventListeners[eventType] as Array<EventCallback<EventPayloadMap[T]>>).push(callback)\n\n return () => {\n this.eventListeners[eventType] = (this.eventListeners[eventType] as Array<EventCallback<EventPayloadMap[T]>>)\n .filter(listener => listener !== callback) as never\n }\n }\n\n public selectItem(selectedItem: string): void {\n if (!this.isEnabled) return\n\n window.parent.postMessage(\n {\n type: 'SELECT_UPDATE',\n payload: { selectedItem }\n },\n '*'\n )\n }\n\n public updateField(itemId: string, field: string, value: string): void {\n if (!this.isEnabled) return\n\n window.parent.postMessage(\n {\n type: 'FIELD_UPDATE',\n payload: { itemId, field, value }\n },\n '*'\n )\n }\n\n public destroy(): void {\n if (this.isEnabled) {\n window.removeEventListener('message', this.handleMessage)\n this.isEnabled = false\n }\n this.eventListeners = {}\n }\n}\n\nexport const previewBridge = PreviewBridge.getInstance()","import type { DirectiveBinding, VNode } from 'vue'\nimport type { SelectUpdateEvent } from '../preview-bridge'\nimport { previewBridge } from '../preview-bridge'\n\ninterface EditableElement extends HTMLElement {\n _editableCleanup?: () => void\n}\n\nexport const EditableDirective = {\n mounted(el: EditableElement, binding: DirectiveBinding, node: VNode) {\n if (!previewBridge.isInPreviewMode()) return\n const { id: itemId } = binding.value\n\n if (!itemId) {\n console.warn('v-editable directive requires a block with an id')\n return\n }\n\n el.classList.add('b10cks-preview')\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n previewBridge.selectItem(itemId)\n }\n\n const handleSelectionChange = ({ selectedItem }: SelectUpdateEvent) => {\n if (!node.el) return\n\n if (selectedItem === itemId) {\n node.el.classList.add('b10cks-selected')\n scrollIntoViewIfNeeded(el)\n } else {\n node.el.classList.remove('b10cks-selected')\n }\n }\n\n const handleHoverChange = ({ selectedItem }: SelectUpdateEvent) => {\n if (!node.el) return\n\n if (selectedItem === itemId) {\n node.el.classList.add('b10cks-hover')\n } else {\n node.el.classList.remove('b10cks-hover')\n }\n }\n\n const handleUpdate = ({ content }: { content: any }) => {\n if (content && content.id === itemId) {\n const ctx = (node as any).ctx\n ctx.parent.attrs.block = content\n ctx.update()\n ctx.props.block = content\n ctx.update()\n }\n }\n\n el.addEventListener('click', handleClick)\n previewBridge.on('SELECT_UPDATE', handleSelectionChange)\n previewBridge.on('HOVER_UPDATE', handleHoverChange)\n previewBridge.on('CONTENT_UPDATE', handleUpdate)\n\n el._editableCleanup = () => {\n el.removeEventListener('click', handleClick)\n }\n },\n\n updated(el: EditableElement, binding: DirectiveBinding, vnode: VNode) {\n if (!previewBridge.isInPreviewMode()) return\n\n if (binding.value !== binding.oldValue) {\n if (el._editableCleanup) {\n el._editableCleanup()\n }\n\n EditableDirective.mounted(el, binding, vnode)\n }\n },\n\n unmounted(el: EditableElement) {\n if (!previewBridge.isInPreviewMode()) return\n\n if (el._editableCleanup) {\n el._editableCleanup()\n delete el._editableCleanup\n }\n\n el.classList.remove('b10cks-preview', 'b10cks-selected')\n }\n}\n\nfunction scrollIntoViewIfNeeded(el: HTMLElement) {\n if (el.scrollIntoView) {\n el.scrollIntoView({ behavior: 'smooth' })\n }\n}\n\nif (previewBridge.isInPreviewMode()) {\n const style = document.createElement('style')\n style.innerHTML = `\n .b10cks-hover,\n .b10cks-preview:hover {\n outline: 2px dashed rgba(59, 130, 246, 0.5);\n outline-offset: 2px;\n }\n .b10cks-selected {\n outline: 2px solid rgb(59, 130, 246) !important;\n outline-offset: 2px;\n }\n `\n document.head.appendChild(style)\n}","import { previewBridge } from '../preview-bridge'\nimport type { Directive, DirectiveBinding } from 'vue'\n\nexport const EditableContentDirective: Directive<HTMLElement> = {\n mounted(el: HTMLElement, binding: DirectiveBinding) {\n const { id: itemId, field } = binding.value\n if (!previewBridge.isInPreviewMode()) return\n el.setAttribute('contenteditable', 'true')\n\n el.addEventListener('input', (event: Event) => {\n previewBridge.updateField(itemId, field, (event.target as HTMLInputElement).innerText)\n })\n }\n}\n","<script setup lang=\"ts\">\nimport { type Component, computed, watch, useTemplateRef, defineAsyncComponent, shallowRef, inject } from 'vue'\nimport type { IBContent } from '@b10cks/client'\n\nconst props = defineProps<{\n block: IBContent<string> & Record<string, never>,\n}>()\n\nconst blockRef = useTemplateRef('blockRef')\ndefineExpose({ value: blockRef })\n\nconst resolvedComponent = shallowRef<Component | null>(null)\nconst componentName = computed(() => props.block?.block || null)\n\nwatch(() => componentName.value,\n async (newComponentName: string | null) => {\n if (!newComponentName) {\n resolvedComponent.value = null\n return\n }\n\n const pascalCaseBlockType = newComponentName\n .replace(/^([a-z])/, (match: string) => match.toUpperCase())\n .replace(/([a-z])([A-Z])/g, '$1$2')\n\n try {\n resolvedComponent.value = defineAsyncComponent({\n loader: () => import(`~/b10cks/${pascalCaseBlockType}.vue`),\n timeout: 3000,\n onError: (error, retry, fail) => {\n console.warn(`Failed to load block component for type \"${newComponentName}\":`, error)\n fail()\n }\n })\n } catch (error) {\n console.error(`Error resolving component for block type \"${newComponentName}\":`, error)\n }\n },\n { immediate: true }\n)\n</script>\n<template>\n <component :is=\"resolvedComponent\" v-if=\"resolvedComponent\" ref=\"blockRef\" v-bind=\"{ ...$props, ...$attrs }\" />\n <div v-else>Component for block type \"{{ componentName }}\" not found.</div>\n</template>","import type { Plugin } from 'vue'\nimport type { B10cksVuePluginOptions } from './types'\n\nimport { EditableDirective } from './directives/v-editable'\nimport { EditableContentDirective } from './directives/v-editable-content'\nimport B10cksComponent from './components/B10cksComponent.vue'\n\nexport { previewBridge } from './preview-bridge'\n\nexport const B10cksVue: Plugin = {\n install(app, pluginOptions: B10cksVuePluginOptions) {\n app.provide('b10cksVueOptions', pluginOptions)\n\n app.directive('editable', EditableDirective)\n app.directive('editable-field', EditableContentDirective)\n app.component('B10cksComponent', B10cksComponent)\n }\n}"],"names":["PreviewBridge","event","type","payload","listeners","listener","eventType","callback","selectedItem","itemId","field","value","previewBridge","EditableDirective","el","binding","node","handleClick","e","handleSelectionChange","scrollIntoViewIfNeeded","handleHoverChange","handleUpdate","content","ctx","vnode","style","EditableContentDirective","props","__props","blockRef","useTemplateRef","__expose","resolvedComponent","shallowRef","componentName","computed","watch","newComponentName","pascalCaseBlockType","match","defineAsyncComponent","error","retry","fail","_createBlock","_resolveDynamicComponent","_mergeProps","$props","$attrs","_openBlock","_createElementBlock","_hoisted_1","_toDisplayString","B10cksVue","app","pluginOptions","B10cksComponent"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { IBContent } from '../../../client/src';
2
+ type __VLS_Props = {
3
+ block: IBContent<string> & Record<string, never>;
4
+ };
5
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {
6
+ value: Readonly<import('vue').ShallowRef<unknown>>;
7
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
8
+ blockRef: unknown;
9
+ }, any>;
10
+ export default _default;
@@ -0,0 +1,2 @@
1
+ import { Directive } from 'vue';
2
+ export declare const EditableContentDirective: Directive<HTMLElement>;
@@ -0,0 +1,10 @@
1
+ import { DirectiveBinding, VNode } from 'vue';
2
+ interface EditableElement extends HTMLElement {
3
+ _editableCleanup?: () => void;
4
+ }
5
+ export declare const EditableDirective: {
6
+ mounted(el: EditableElement, binding: DirectiveBinding, node: VNode): void;
7
+ updated(el: EditableElement, binding: DirectiveBinding, vnode: VNode): void;
8
+ unmounted(el: EditableElement): void;
9
+ };
10
+ export {};
@@ -0,0 +1,3 @@
1
+ import { Plugin } from 'vue';
2
+ export { previewBridge } from './preview-bridge';
3
+ export declare const B10cksVue: Plugin;
@@ -0,0 +1,36 @@
1
+ export type ContentUpdateEvent = {
2
+ content: Record<string, any>;
3
+ };
4
+ export type SelectUpdateEvent = {
5
+ selectedItem: string;
6
+ };
7
+ export type EventType = 'CONTENT_UPDATE' | 'SELECT_UPDATE' | 'HOVER_UPDATE';
8
+ export type EventPayloadMap = {
9
+ 'CONTENT_UPDATE': ContentUpdateEvent;
10
+ 'SELECT_UPDATE': SelectUpdateEvent;
11
+ 'HOVER_UPDATE': SelectUpdateEvent;
12
+ };
13
+ export type BridgeEvent = {
14
+ type: EventType;
15
+ payload: ContentUpdateEvent | SelectUpdateEvent;
16
+ b10cksId?: string;
17
+ };
18
+ type EventCallback<T> = (payload: T) => void;
19
+ declare class PreviewBridge {
20
+ private static instance;
21
+ private eventListeners;
22
+ private isEnabled;
23
+ private constructor();
24
+ init(): void;
25
+ static getInstance(): PreviewBridge;
26
+ isInPreviewMode(): boolean;
27
+ private isIframe;
28
+ private handleMessage;
29
+ private notifyListeners;
30
+ on<T extends EventType>(eventType: T, callback: EventCallback<EventPayloadMap[T]>): () => void;
31
+ selectItem(selectedItem: string): void;
32
+ updateField(itemId: string, field: string, value: string): void;
33
+ destroy(): void;
34
+ }
35
+ export declare const previewBridge: PreviewBridge;
36
+ export {};
@@ -0,0 +1,3 @@
1
+ import { B10cksApiClientOptions } from '../../client/src';
2
+ export interface B10cksVuePluginOptions extends B10cksApiClientOptions {
3
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@b10cks/vue",
3
+ "license": "MIT",
4
+ "version": "0.9.6",
5
+ "author": "Michael Wallner @ Coder's Cantina",
6
+ "description": "SDK to integrate b10cks into your vue applications",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "main": "./dist/index.js",
16
+ "module": "./dist/index.mjs",
17
+ "types": "./dist/index.d.ts",
18
+ "source": "src/index.ts",
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/b10cks/sdk.git",
25
+ "directory": "packages/vue"
26
+ },
27
+ "peerDependencies": {
28
+ "vue": "^3.5.21"
29
+ },
30
+ "release": {
31
+ "branches": [
32
+ "main"
33
+ ]
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "devDependencies": {
39
+ "typescript": "^5.9.0",
40
+ "vite": "^7.1.4",
41
+ "vite-plugin-dts": "^4.5.4",
42
+ "vue": "^3.4.0"
43
+ },
44
+ "dependencies": {
45
+ "@b10cks/client": "^0.9.6"
46
+ },
47
+ "scripts": {
48
+ "build": "vite build",
49
+ "dev": "vite build --watch",
50
+ "test": "vitest",
51
+ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts --fix",
52
+ "clean": "rm -rf dist"
53
+ }
54
+ }