@simple-builder/react 1.0.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.
- package/dist/build-container-client-FBOVSG6E.mjs +1268 -0
- package/dist/build-container-client-JPFTBMJ3.js +1302 -0
- package/dist/builder-content-I65E3YF2.mjs +21 -0
- package/dist/builder-content-XP2KWHHT.js +43 -0
- package/dist/chunk-4CD23J5W.js +38 -0
- package/dist/chunk-7K7IGTF3.mjs +40 -0
- package/dist/chunk-KZNIT2AQ.mjs +266 -0
- package/dist/chunk-LKNRLBTK.mjs +16 -0
- package/dist/chunk-TEAHH2DG.js +293 -0
- package/dist/chunk-VMHWPKU4.js +42 -0
- package/dist/index.css +1063 -0
- package/dist/index.d.mts +61 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +51 -0
- package/dist/index.mjs +22 -0
- package/package.json +72 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BuildContainer } from './chunk-LKNRLBTK.mjs';
|
|
2
|
+
import { BuilderProvider, useBuilder, Button } from './chunk-KZNIT2AQ.mjs';
|
|
3
|
+
import './chunk-7K7IGTF3.mjs';
|
|
4
|
+
import * as React2 from 'react';
|
|
5
|
+
|
|
6
|
+
var BuilderHeader = () => {
|
|
7
|
+
const { save } = useBuilder();
|
|
8
|
+
return /* @__PURE__ */ React2.createElement("div", { className: "grid grid-cols-3 gap-4 items-center p-2 shadow-lg sticky inset-x-0 top-0 bg-sb-background z-30" }, /* @__PURE__ */ React2.createElement("div", { className: "flex gap-4 items-center" }, /* @__PURE__ */ React2.createElement(Button, { variant: "ghost", size: "sm", onClick: save }, "Opslaan")));
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/components/builder-content.tsx
|
|
12
|
+
var BuilderContent = (props) => {
|
|
13
|
+
return /* @__PURE__ */ React2.createElement(BuilderProvider, { content: props.content }, /* @__PURE__ */ React2.createElement(BuilderContentInner, null));
|
|
14
|
+
};
|
|
15
|
+
var BuilderContentInner = () => {
|
|
16
|
+
const { content } = useBuilder();
|
|
17
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(BuilderHeader, null), /* @__PURE__ */ React2.createElement(BuildContainer, { name: "root", edit: true, multiple: true, content }));
|
|
18
|
+
};
|
|
19
|
+
var builder_content_default = BuilderContent;
|
|
20
|
+
|
|
21
|
+
export { builder_content_default as default };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunk4CD23J5W_js = require('./chunk-4CD23J5W.js');
|
|
4
|
+
var chunkTEAHH2DG_js = require('./chunk-TEAHH2DG.js');
|
|
5
|
+
require('./chunk-VMHWPKU4.js');
|
|
6
|
+
var React2 = require('react');
|
|
7
|
+
|
|
8
|
+
function _interopNamespace(e) {
|
|
9
|
+
if (e && e.__esModule) return e;
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
|
|
27
|
+
|
|
28
|
+
var BuilderHeader = () => {
|
|
29
|
+
const { save } = chunkTEAHH2DG_js.useBuilder();
|
|
30
|
+
return /* @__PURE__ */ React2__namespace.createElement("div", { className: "grid grid-cols-3 gap-4 items-center p-2 shadow-lg sticky inset-x-0 top-0 bg-sb-background z-30" }, /* @__PURE__ */ React2__namespace.createElement("div", { className: "flex gap-4 items-center" }, /* @__PURE__ */ React2__namespace.createElement(chunkTEAHH2DG_js.Button, { variant: "ghost", size: "sm", onClick: save }, "Opslaan")));
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/components/builder-content.tsx
|
|
34
|
+
var BuilderContent = (props) => {
|
|
35
|
+
return /* @__PURE__ */ React2__namespace.createElement(chunkTEAHH2DG_js.BuilderProvider, { content: props.content }, /* @__PURE__ */ React2__namespace.createElement(BuilderContentInner, null));
|
|
36
|
+
};
|
|
37
|
+
var BuilderContentInner = () => {
|
|
38
|
+
const { content } = chunkTEAHH2DG_js.useBuilder();
|
|
39
|
+
return /* @__PURE__ */ React2__namespace.createElement(React2__namespace.Fragment, null, /* @__PURE__ */ React2__namespace.createElement(BuilderHeader, null), /* @__PURE__ */ React2__namespace.createElement(chunk4CD23J5W_js.BuildContainer, { name: "root", edit: true, multiple: true, content }));
|
|
40
|
+
};
|
|
41
|
+
var builder_content_default = BuilderContent;
|
|
42
|
+
|
|
43
|
+
module.exports = builder_content_default;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkVMHWPKU4_js = require('./chunk-VMHWPKU4.js');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
|
|
6
|
+
function _interopNamespace(e) {
|
|
7
|
+
if (e && e.__esModule) return e;
|
|
8
|
+
var n = Object.create(null);
|
|
9
|
+
if (e) {
|
|
10
|
+
Object.keys(e).forEach(function (k) {
|
|
11
|
+
if (k !== 'default') {
|
|
12
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
13
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () { return e[k]; }
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
n.default = e;
|
|
21
|
+
return Object.freeze(n);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
25
|
+
|
|
26
|
+
var BuildContainerInner = React__namespace.lazy(
|
|
27
|
+
() => import('./build-container-client-JPFTBMJ3.js')
|
|
28
|
+
);
|
|
29
|
+
var BuildContainer = (props) => {
|
|
30
|
+
const { content, edit, name } = props;
|
|
31
|
+
const items = Array.isArray(content) ? content : content?.[name] || [];
|
|
32
|
+
if (!edit) {
|
|
33
|
+
return items.map((item) => chunkVMHWPKU4_js.builder.bindComponent(item));
|
|
34
|
+
}
|
|
35
|
+
return /* @__PURE__ */ React__namespace.createElement(BuildContainerInner, { ...props });
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
exports.BuildContainer = BuildContainer;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
|
|
3
|
+
// src/lib/builder.ts
|
|
4
|
+
var builder = /* @__PURE__ */ (() => {
|
|
5
|
+
const components = [];
|
|
6
|
+
return {
|
|
7
|
+
register: (component, config) => {
|
|
8
|
+
if (components.find(({ name }) => name === config.name)) {
|
|
9
|
+
console.log(
|
|
10
|
+
`[simple-builder]: Component ${config.name} already registered.`
|
|
11
|
+
);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
components.push({
|
|
15
|
+
component,
|
|
16
|
+
...config
|
|
17
|
+
});
|
|
18
|
+
},
|
|
19
|
+
getComponents: () => components,
|
|
20
|
+
getComponent: (name) => {
|
|
21
|
+
return components.find((c) => c.name === name);
|
|
22
|
+
},
|
|
23
|
+
bindComponent: ({ content, ...block }, edit) => {
|
|
24
|
+
const component = components.find(({ name }) => name === block.component);
|
|
25
|
+
if (!component) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`[simple-builder]: Component ${block.component} not found`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
const Element = createElement(component.component, {
|
|
31
|
+
key: block.id,
|
|
32
|
+
builder: { id: block.id, content, edit },
|
|
33
|
+
...block.props
|
|
34
|
+
});
|
|
35
|
+
return Element;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
|
|
40
|
+
export { builder };
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { builder } from './chunk-7K7IGTF3.mjs';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
6
|
+
import { cva } from 'class-variance-authority';
|
|
7
|
+
|
|
8
|
+
function cn(...inputs) {
|
|
9
|
+
return twMerge(clsx(inputs));
|
|
10
|
+
}
|
|
11
|
+
var insertAt = (items, index, item) => {
|
|
12
|
+
return Array.isArray(items) ? [...items.slice(0, index), item, ...items.slice(index)] : [item];
|
|
13
|
+
};
|
|
14
|
+
var spacing = {
|
|
15
|
+
parse: (input) => {
|
|
16
|
+
const matches = input.match(/(\d+)/gm);
|
|
17
|
+
const [top = 0, right = 0, bottom = 0, left = 0] = matches?.map((match) => +match) || [];
|
|
18
|
+
switch (matches?.length) {
|
|
19
|
+
case 1:
|
|
20
|
+
return { top, right: top, bottom: top, left: top };
|
|
21
|
+
case 2:
|
|
22
|
+
return { top, bottom: top, left: right, right };
|
|
23
|
+
case 3:
|
|
24
|
+
return { top, right, left: right, bottom };
|
|
25
|
+
default:
|
|
26
|
+
return { top, right, bottom, left };
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
isIndipendent: (input) => {
|
|
30
|
+
const { top, right, bottom, left } = spacing.parse(input);
|
|
31
|
+
return top !== bottom || right !== left;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// src/components/context/builder-context.tsx
|
|
36
|
+
var BuilderContext = React.createContext(
|
|
37
|
+
null
|
|
38
|
+
);
|
|
39
|
+
var BuilderProvider = (props) => {
|
|
40
|
+
const url = props.url ?? "/api/simple-builder";
|
|
41
|
+
const [content, setContent] = React.useState(
|
|
42
|
+
props.content ?? []
|
|
43
|
+
);
|
|
44
|
+
const getItem = React.useCallback(
|
|
45
|
+
(id) => {
|
|
46
|
+
const res = findRecursive(content, (item) => item.id === id);
|
|
47
|
+
console.log("RES", res);
|
|
48
|
+
return res;
|
|
49
|
+
},
|
|
50
|
+
[content]
|
|
51
|
+
);
|
|
52
|
+
const patchItem = React.useCallback(
|
|
53
|
+
(id, patch) => {
|
|
54
|
+
setContent(
|
|
55
|
+
(content2) => mapRecursive(content2, (item) => {
|
|
56
|
+
if (item.id === id) {
|
|
57
|
+
return {
|
|
58
|
+
...item,
|
|
59
|
+
...patch
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return item;
|
|
63
|
+
})
|
|
64
|
+
);
|
|
65
|
+
},
|
|
66
|
+
[setContent, mapRecursive]
|
|
67
|
+
);
|
|
68
|
+
const addContent = React.useCallback(
|
|
69
|
+
(name, container, parent, index = 0) => {
|
|
70
|
+
const component = builder.getComponent(name);
|
|
71
|
+
if (!component) {
|
|
72
|
+
throw new Error(`[simple-builder]: Component "${name}" not found`);
|
|
73
|
+
}
|
|
74
|
+
const entry = {
|
|
75
|
+
id: crypto.randomUUID(),
|
|
76
|
+
component: component.name,
|
|
77
|
+
...parent && { parent },
|
|
78
|
+
...component.inputs && {
|
|
79
|
+
props: component.inputs.reduce(
|
|
80
|
+
(acc, input) => ({
|
|
81
|
+
...acc,
|
|
82
|
+
[input.name]: input.defaultValue
|
|
83
|
+
}),
|
|
84
|
+
{}
|
|
85
|
+
)
|
|
86
|
+
},
|
|
87
|
+
...component.defaultStyles && {
|
|
88
|
+
styles: component.defaultStyles
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
if (!parent) {
|
|
92
|
+
setContent((content2) => insertAt(content2, index, entry));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
setContent(
|
|
96
|
+
(content2) => mapRecursive(content2, (item) => {
|
|
97
|
+
if (item.id === parent) {
|
|
98
|
+
return {
|
|
99
|
+
...item,
|
|
100
|
+
content: {
|
|
101
|
+
...item.content,
|
|
102
|
+
[container]: insertAt(item.content?.[container], index, entry)
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return item;
|
|
107
|
+
})
|
|
108
|
+
);
|
|
109
|
+
},
|
|
110
|
+
[setContent, mapRecursive]
|
|
111
|
+
);
|
|
112
|
+
const deleteContent = React.useCallback(
|
|
113
|
+
(id) => setContent((prev) => filterRecursive(prev, (item) => item.id !== id)),
|
|
114
|
+
[setContent, filterRecursive]
|
|
115
|
+
);
|
|
116
|
+
const bringUp = React.useCallback(
|
|
117
|
+
(id) => {
|
|
118
|
+
setContent(
|
|
119
|
+
(content2) => mapRecursive(content2, (item, index, arr) => {
|
|
120
|
+
if (item.id === id && index > 0) {
|
|
121
|
+
return arr[index - 1];
|
|
122
|
+
}
|
|
123
|
+
if (arr[index + 1]?.id === id) {
|
|
124
|
+
return arr[index + 1];
|
|
125
|
+
}
|
|
126
|
+
return item;
|
|
127
|
+
})
|
|
128
|
+
);
|
|
129
|
+
},
|
|
130
|
+
[setContent, mapRecursive]
|
|
131
|
+
);
|
|
132
|
+
const bringDown = React.useCallback(
|
|
133
|
+
(id) => {
|
|
134
|
+
setContent(
|
|
135
|
+
(content2) => mapRecursive(content2, (item, index, arr) => {
|
|
136
|
+
if (item.id === id && index < arr.length - 1) {
|
|
137
|
+
return arr[index + 1];
|
|
138
|
+
}
|
|
139
|
+
if (arr[index - 1]?.id === id) {
|
|
140
|
+
return arr[index - 1];
|
|
141
|
+
}
|
|
142
|
+
return item;
|
|
143
|
+
})
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
[setContent, mapRecursive]
|
|
147
|
+
);
|
|
148
|
+
const save = React.useCallback(async () => {
|
|
149
|
+
const slug = window.location.pathname;
|
|
150
|
+
await fetch(`${url}/page/update`, {
|
|
151
|
+
method: "POST",
|
|
152
|
+
body: JSON.stringify({
|
|
153
|
+
slug,
|
|
154
|
+
content
|
|
155
|
+
})
|
|
156
|
+
});
|
|
157
|
+
}, [content]);
|
|
158
|
+
return /* @__PURE__ */ React.createElement(
|
|
159
|
+
BuilderContext.Provider,
|
|
160
|
+
{
|
|
161
|
+
value: {
|
|
162
|
+
url,
|
|
163
|
+
content,
|
|
164
|
+
setContent,
|
|
165
|
+
getItem,
|
|
166
|
+
patchItem,
|
|
167
|
+
addContent,
|
|
168
|
+
bringUp,
|
|
169
|
+
bringDown,
|
|
170
|
+
deleteContent,
|
|
171
|
+
save
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
props.children
|
|
175
|
+
);
|
|
176
|
+
};
|
|
177
|
+
var useBuilder = () => {
|
|
178
|
+
const context = React.useContext(BuilderContext);
|
|
179
|
+
if (!context) {
|
|
180
|
+
throw new Error(
|
|
181
|
+
"[simple-builder]: useBuilder must be used within a BuilderProvider"
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
return context;
|
|
185
|
+
};
|
|
186
|
+
var filterRecursive = (items, predicate, key = "content") => {
|
|
187
|
+
return items.filter(predicate).map((item) => ({
|
|
188
|
+
...item,
|
|
189
|
+
...item[key] && {
|
|
190
|
+
[key]: Object.entries(item[key] ?? {}).reduce(
|
|
191
|
+
(acc, [name, content]) => ({
|
|
192
|
+
...acc,
|
|
193
|
+
[name]: filterRecursive(content, predicate, key)
|
|
194
|
+
}),
|
|
195
|
+
{}
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
}));
|
|
199
|
+
};
|
|
200
|
+
var mapRecursive = (items, predicate, key = "content") => {
|
|
201
|
+
return items.map(predicate).map((item) => ({
|
|
202
|
+
...item,
|
|
203
|
+
...item[key] && {
|
|
204
|
+
[key]: Object.entries(item[key] ?? {}).reduce(
|
|
205
|
+
(acc, [name, content]) => ({
|
|
206
|
+
...acc,
|
|
207
|
+
[name]: mapRecursive(content, predicate, key)
|
|
208
|
+
}),
|
|
209
|
+
{}
|
|
210
|
+
)
|
|
211
|
+
}
|
|
212
|
+
}));
|
|
213
|
+
};
|
|
214
|
+
var findRecursive = (items, predicate, key = "content") => {
|
|
215
|
+
for (const item of items) {
|
|
216
|
+
if (predicate(item)) {
|
|
217
|
+
return item;
|
|
218
|
+
}
|
|
219
|
+
if (item[key]) {
|
|
220
|
+
const keys = Object.keys(item[key] ?? {});
|
|
221
|
+
for (const x of keys) {
|
|
222
|
+
const found = findRecursive(item[key][x], predicate, key);
|
|
223
|
+
if (found) {
|
|
224
|
+
return found;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
var buttonVariants = cva(
|
|
231
|
+
"inline-flex uppercase items-center justify-center whitespace-nowrap rounded-md text-xs font-semibold ring-offset-sb-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sb-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
232
|
+
{
|
|
233
|
+
variants: {
|
|
234
|
+
variant: {
|
|
235
|
+
primary: "bg-sb-primary text-sb-primary-foreground hover:bg-sb-primary/90",
|
|
236
|
+
destructive: "bg-sb-destructive text-sb-destructive-foreground hover:bg-sb-destructive/90",
|
|
237
|
+
outline: "border border-sb-input bg-sb-background hover:bg-sb-accent hover:text-sb-accent-foreground",
|
|
238
|
+
ghost: "hover:bg-sb-accent hover:text-sb-accent-foreground"
|
|
239
|
+
},
|
|
240
|
+
size: {
|
|
241
|
+
default: "h-10 px-4 py-2",
|
|
242
|
+
sm: "h-8 px-3 py-1"
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
defaultVariants: {
|
|
246
|
+
variant: "primary",
|
|
247
|
+
size: "default"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
var Button = React.forwardRef(
|
|
252
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
253
|
+
const Comp = asChild ? Slot : "button";
|
|
254
|
+
return /* @__PURE__ */ React.createElement(
|
|
255
|
+
Comp,
|
|
256
|
+
{
|
|
257
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
258
|
+
ref,
|
|
259
|
+
...props
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
Button.displayName = "Button";
|
|
265
|
+
|
|
266
|
+
export { BuilderProvider, Button, buttonVariants, cn, spacing, useBuilder };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { builder } from './chunk-7K7IGTF3.mjs';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
var BuildContainerInner = React.lazy(
|
|
5
|
+
() => import('./build-container-client-FBOVSG6E.mjs')
|
|
6
|
+
);
|
|
7
|
+
var BuildContainer = (props) => {
|
|
8
|
+
const { content, edit, name } = props;
|
|
9
|
+
const items = Array.isArray(content) ? content : content?.[name] || [];
|
|
10
|
+
if (!edit) {
|
|
11
|
+
return items.map((item) => builder.bindComponent(item));
|
|
12
|
+
}
|
|
13
|
+
return /* @__PURE__ */ React.createElement(BuildContainerInner, { ...props });
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { BuildContainer };
|