@woodylab/payload 0.0.121 → 0.0.123
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/config/react/Card.d.ts +6 -0
- package/dist/config/react/Card.js +4 -0
- package/dist/config/react/ComponentRenderer.d.ts +1 -0
- package/dist/config/react/ComponentRenderer.js +29 -0
- package/dist/config/react/PageRenderer.d.ts +4 -0
- package/dist/config/react/PageRenderer.js +36 -0
- package/dist/config/react/ViewBlock.d.ts +1 -0
- package/dist/config/react/ViewBlock.js +62 -0
- package/dist/config/react/index.d.ts +5 -0
- package/dist/config/react/index.js +5 -0
- package/dist/config/react/registry.d.ts +1 -0
- package/dist/config/react/registry.js +5 -0
- package/dist/config/utils/resolveInlineComponent.d.ts +4 -0
- package/dist/config/utils/resolveInlineComponent.js +35 -0
- package/dist/config/utils/resolveViewRow.d.ts +4 -0
- package/dist/config/utils/resolveViewRow.js +15 -0
- package/package.json +1 -1
- package/dist/generateCssVars.d.ts +0 -11
- package/dist/generateCssVars.js +0 -110
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ComponentRenderer({ type, view, data }: any): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// components/ComponentRenderer.tsx
|
|
2
|
+
'use client';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
import { componentRegistry } from './registry';
|
|
5
|
+
function getValueByPath(obj, path) {
|
|
6
|
+
return path.split('.').reduce((acc, key) => acc?.[key], obj);
|
|
7
|
+
}
|
|
8
|
+
export function ComponentRenderer({ type, view, data }) {
|
|
9
|
+
if (type !== 'view')
|
|
10
|
+
return null;
|
|
11
|
+
const rows = data[view.dataSet];
|
|
12
|
+
const Container = componentRegistry[view.component.componentName];
|
|
13
|
+
const Row = componentRegistry[view.rowComponent.componentName];
|
|
14
|
+
if (!Container || !Row)
|
|
15
|
+
return null;
|
|
16
|
+
const containerClassNames = Array.isArray(view.viewMode)
|
|
17
|
+
? view.viewMode.map((mode) => mode?.className || '').join(' ')
|
|
18
|
+
: '';
|
|
19
|
+
return (_jsx(Container, { className: containerClassNames, children: rows.map((item, i) => {
|
|
20
|
+
const props = {};
|
|
21
|
+
for (const [k, v] of Object.entries(view.rowPropsMapping ?? {})) {
|
|
22
|
+
props[k] = getValueByPath(item, v);
|
|
23
|
+
}
|
|
24
|
+
const rowClassNames = Array.isArray(view.rowViewMode)
|
|
25
|
+
? view.rowViewMode.map((mode) => mode?.className || '').join(' ')
|
|
26
|
+
: '';
|
|
27
|
+
return _jsx(Row, { ...props, className: rowClassNames }, i);
|
|
28
|
+
}) }));
|
|
29
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// #TODO Gestire doppio caricamento dati:
|
|
3
|
+
// 1 lato payload usando come già fatto api interne di payload mappando i campi in un blocco di tipo view dedicato
|
|
4
|
+
import { resolveInlineComponent } from '../utils/resolveInlineComponent';
|
|
5
|
+
import { ViewBlock } from './ViewBlock';
|
|
6
|
+
// 2 recupero dati sempre lato server chiamando un EP in maniera asincrona e gestendo il corretto binding
|
|
7
|
+
export async function PageRenderer({ layout, serverData, }) {
|
|
8
|
+
const resolvedLayout = layout.map((block, index) => {
|
|
9
|
+
if (block.blockType !== 'view')
|
|
10
|
+
return block;
|
|
11
|
+
console.log(block);
|
|
12
|
+
console.log(serverData);
|
|
13
|
+
return {
|
|
14
|
+
blockType: block.blockType,
|
|
15
|
+
component: block.component,
|
|
16
|
+
viewMode: block.viewMode,
|
|
17
|
+
containerProps: block.containerProps,
|
|
18
|
+
rowComponent: block.rowComponent,
|
|
19
|
+
rowViewMode: block.rowViewMode,
|
|
20
|
+
rowPropsMapping: block.rowPropsMapping,
|
|
21
|
+
rowChildren: block.rowChildren,
|
|
22
|
+
_resolvedData: serverData[index] ?? [],
|
|
23
|
+
_resolvedOk: true,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
return (_jsx(_Fragment, { children: resolvedLayout.map((block, i) => {
|
|
27
|
+
if (block.blockType === 'view') {
|
|
28
|
+
return _jsx(ViewBlock, { ...block }, i);
|
|
29
|
+
}
|
|
30
|
+
const resolved = resolveInlineComponent(block);
|
|
31
|
+
if (!resolved)
|
|
32
|
+
return null;
|
|
33
|
+
const { Component, props } = resolved;
|
|
34
|
+
return _jsx(Component, { ...props }, i);
|
|
35
|
+
}) }));
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ViewBlock(block: any): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { componentRegistry } from './registry';
|
|
4
|
+
function resolveClassName(viewMode) {
|
|
5
|
+
if (Array.isArray(viewMode) && viewMode.length > 0) {
|
|
6
|
+
return viewMode
|
|
7
|
+
.map((vm) => vm?.css.className)
|
|
8
|
+
.filter(Boolean)
|
|
9
|
+
.join(' ');
|
|
10
|
+
}
|
|
11
|
+
return viewMode?.css.className ?? '';
|
|
12
|
+
}
|
|
13
|
+
export function ViewBlock(block) {
|
|
14
|
+
const { component, viewMode, rowComponent, rowViewMode, containerProps = {}, rowPropsMapping = {}, rowChildren = [], _resolvedData = [], _resolvedOk = true, } = block;
|
|
15
|
+
const Container = componentRegistry[component.componentName];
|
|
16
|
+
const Row = componentRegistry[rowComponent.componentName];
|
|
17
|
+
if (!Container || !Row)
|
|
18
|
+
return null;
|
|
19
|
+
if (!_resolvedOk) {
|
|
20
|
+
return (_jsx(Container, { className: resolveClassName(viewMode), children: _jsx("div", { className: "text-red-600", children: "Impossibile caricare i dati" }) }));
|
|
21
|
+
}
|
|
22
|
+
//#TODO gestire rendering di molteplici rowChildren al mometno stampa solo il primo elemento dell'array
|
|
23
|
+
// --- helper per render figli di riga (con sourceProps mapping) ---
|
|
24
|
+
const renderRowChildren = (children, item) => {
|
|
25
|
+
return children.map((child, idx) => {
|
|
26
|
+
const ChildComp = componentRegistry[child.definition?.componentName];
|
|
27
|
+
if (!ChildComp)
|
|
28
|
+
return null;
|
|
29
|
+
const childVM = Array.isArray(child.viewMode) ? child.viewMode[0] : child.viewMode;
|
|
30
|
+
const hasSourceProps = child.sourceProps &&
|
|
31
|
+
typeof child.sourceProps === 'object' &&
|
|
32
|
+
Object.keys(child.sourceProps).length > 0;
|
|
33
|
+
let finalProps = {};
|
|
34
|
+
if (hasSourceProps) {
|
|
35
|
+
for (const [key, path] of Object.entries(child.sourceProps)) {
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
finalProps[key] = path
|
|
38
|
+
.toString()
|
|
39
|
+
.split('.')
|
|
40
|
+
.reduce((acc, k) => acc?.[k], item);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// fallback ai props statici
|
|
45
|
+
finalProps = child.staticProps || {};
|
|
46
|
+
}
|
|
47
|
+
return _jsx(ChildComp, { ...finalProps, className: resolveClassName(childVM) }, idx);
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
return (_jsx(Container, { className: resolveClassName(viewMode), ...containerProps, children: _resolvedData.map((item, i) => {
|
|
51
|
+
const props = {};
|
|
52
|
+
// mapping valori verso props della card
|
|
53
|
+
for (const [key, path] of Object.entries(rowPropsMapping)) {
|
|
54
|
+
// @ts-ignore
|
|
55
|
+
props[key] = path
|
|
56
|
+
.toString()
|
|
57
|
+
.split('.')
|
|
58
|
+
.reduce((acc, k) => acc?.[k], item);
|
|
59
|
+
}
|
|
60
|
+
return (_jsx(Row, { ...props, className: resolveClassName(rowViewMode), children: rowChildren?.length > 0 ? renderRowChildren(rowChildren, item) : null }, i));
|
|
61
|
+
}) }));
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const componentRegistry: Record<string, any>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// uims/resolveInlineComponent.ts
|
|
2
|
+
import { componentRegistry } from '../react';
|
|
3
|
+
export function resolveInlineComponent(block) {
|
|
4
|
+
const { definition, viewMode } = block;
|
|
5
|
+
if (!definition)
|
|
6
|
+
return null;
|
|
7
|
+
const Component = componentRegistry[definition.componentName];
|
|
8
|
+
if (!Component)
|
|
9
|
+
return null;
|
|
10
|
+
/* Caso CTA (inline typed) */
|
|
11
|
+
if (block.blockType === 'cta-block') {
|
|
12
|
+
return {
|
|
13
|
+
Component,
|
|
14
|
+
props: {
|
|
15
|
+
title: block.title,
|
|
16
|
+
description: block.description,
|
|
17
|
+
action: block.actionLabel
|
|
18
|
+
? {
|
|
19
|
+
label: block.actionLabel,
|
|
20
|
+
href: block.actionHref,
|
|
21
|
+
}
|
|
22
|
+
: undefined,
|
|
23
|
+
className: viewMode?.css.className ?? definition.defaultStyle,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/* Caso component-instance generico */
|
|
28
|
+
return {
|
|
29
|
+
Component,
|
|
30
|
+
props: {
|
|
31
|
+
...(block.props ?? {}),
|
|
32
|
+
className: viewMode?.css.className ?? definition.defaultStyle,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// uims/resolveViewRow.ts
|
|
2
|
+
import { componentRegistry } from '../react';
|
|
3
|
+
export function resolveViewRow({ item, rowComponent, rowViewMode, rowPropsMapping }) {
|
|
4
|
+
const Row = componentRegistry[rowComponent.componentName];
|
|
5
|
+
console.log(rowComponent);
|
|
6
|
+
if (!Row)
|
|
7
|
+
return null;
|
|
8
|
+
const props = {};
|
|
9
|
+
for (const prop in rowPropsMapping) {
|
|
10
|
+
const path = rowPropsMapping[prop];
|
|
11
|
+
props[prop] = path.split('.').reduce((acc, key) => acc?.[key], item);
|
|
12
|
+
}
|
|
13
|
+
props.className = rowViewMode?.css.className ?? rowComponent.defaultStyle;
|
|
14
|
+
return { Row, props };
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
declare function generateCssVars(settings: {
|
|
2
|
-
headingFont?: string;
|
|
3
|
-
textFont?: string;
|
|
4
|
-
foregroundColor?: string;
|
|
5
|
-
primaryColor?: string;
|
|
6
|
-
secondaryColor?: string;
|
|
7
|
-
accentColor?: string;
|
|
8
|
-
darkColor?: string;
|
|
9
|
-
lightColor?: string;
|
|
10
|
-
}): string;
|
|
11
|
-
export default generateCssVars;
|
package/dist/generateCssVars.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import hexToRgb from './hexToRgb';
|
|
2
|
-
function generateCssVars(settings) {
|
|
3
|
-
// Gestione robusta dei font
|
|
4
|
-
const fontWeights = [300, 400, 500, 600, 700, 800];
|
|
5
|
-
const fontsToImport = [settings.headingFont, settings.textFont]
|
|
6
|
-
.filter(Boolean)
|
|
7
|
-
.map((f) => {
|
|
8
|
-
if (!f)
|
|
9
|
-
return '';
|
|
10
|
-
// Aggiungiamo il parametro wght per specificare i pesi da caricare
|
|
11
|
-
return `@import url('https://fonts.googleapis.com/css2?family=${f.replace(/ /g, '+')}:wght@${fontWeights.join(';')}&display=swap');`;
|
|
12
|
-
})
|
|
13
|
-
.join('\n');
|
|
14
|
-
const generateOpacityVariants = (color, name) => {
|
|
15
|
-
if (!color) {
|
|
16
|
-
return '';
|
|
17
|
-
}
|
|
18
|
-
try {
|
|
19
|
-
const rgbValue = hexToRgb(color);
|
|
20
|
-
if (!rgbValue ||
|
|
21
|
-
typeof rgbValue.r !== 'number' ||
|
|
22
|
-
typeof rgbValue.g !== 'number' ||
|
|
23
|
-
typeof rgbValue.b !== 'number') {
|
|
24
|
-
console.warn(`Impossibile convertire il colore ${name}: ${color}`);
|
|
25
|
-
return '';
|
|
26
|
-
}
|
|
27
|
-
const { r, g, b } = rgbValue;
|
|
28
|
-
const opacityVars = Array.from({ length: 9 }, (_, i) => {
|
|
29
|
-
const opacity = (i + 1) * 10;
|
|
30
|
-
return `--color-${name}-${opacity}: rgba(${r}, ${g}, ${b}, ${opacity / 100});`;
|
|
31
|
-
}).join('\n');
|
|
32
|
-
return `
|
|
33
|
-
--color-${name}: rgb(${r}, ${g}, ${b}); /* Default (opacità 1) */
|
|
34
|
-
${opacityVars}
|
|
35
|
-
`;
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
console.warn(`Errore nella generazione delle varianti di opacità per ${name}: ${error}`);
|
|
39
|
-
return '';
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
const generateBrightnessVariants = (color, name) => {
|
|
43
|
-
if (!color) {
|
|
44
|
-
return '';
|
|
45
|
-
}
|
|
46
|
-
try {
|
|
47
|
-
const rgbValue = hexToRgb(color);
|
|
48
|
-
if (!rgbValue ||
|
|
49
|
-
typeof rgbValue.r !== 'number' ||
|
|
50
|
-
typeof rgbValue.g !== 'number' ||
|
|
51
|
-
typeof rgbValue.b !== 'number') {
|
|
52
|
-
console.warn(`Impossibile convertire il colore ${name}: ${color}`);
|
|
53
|
-
return '';
|
|
54
|
-
}
|
|
55
|
-
const { r, g, b } = rgbValue;
|
|
56
|
-
const clamp = (value) => Math.max(0, Math.min(255, Math.round(value)));
|
|
57
|
-
const mixWith = (target, amount) => clamp(r + (target - r) * amount) +
|
|
58
|
-
',' +
|
|
59
|
-
clamp(g + (target - g) * amount) +
|
|
60
|
-
',' +
|
|
61
|
-
clamp(b + (target - b) * amount);
|
|
62
|
-
const lighter = Array.from({ length: 4 }, (_, i) => {
|
|
63
|
-
const step = (i + 1) / 5;
|
|
64
|
-
return `--color-${name}-light-${i + 1}: rgb(${mixWith(255, step)});`;
|
|
65
|
-
}).join('\n');
|
|
66
|
-
const darker = Array.from({ length: 4 }, (_, i) => {
|
|
67
|
-
const step = (i + 1) / 5;
|
|
68
|
-
return `--color-${name}-dark-${i + 1}: rgb(${mixWith(0, step)});`;
|
|
69
|
-
}).join('\n');
|
|
70
|
-
return `--color-${name}: rgb(${r}, ${g}, ${b});
|
|
71
|
-
${lighter}
|
|
72
|
-
${darker}
|
|
73
|
-
`;
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
console.warn(`Errore nella generazione delle varianti di brightness per ${name}: ${error}`);
|
|
77
|
-
return '';
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
// Genera variabili solo per i colori forniti
|
|
81
|
-
const primaryVars = `${generateOpacityVariants(settings.primaryColor, 'primary')} ${generateBrightnessVariants(settings.primaryColor, 'primary')}`;
|
|
82
|
-
const secondaryVars = `${generateOpacityVariants(settings.secondaryColor, 'secondary')} ${generateBrightnessVariants(settings.secondaryColor, 'secondary')}`;
|
|
83
|
-
const accentVars = `${generateOpacityVariants(settings.secondaryColor, 'accent')} ${generateBrightnessVariants(settings.secondaryColor, 'accent')}`;
|
|
84
|
-
const darkVars = `${generateOpacityVariants(settings.secondaryColor, 'dark')} ${generateBrightnessVariants(settings.secondaryColor, 'dark')}`;
|
|
85
|
-
const lightVars = `${generateOpacityVariants(settings.secondaryColor, 'light')} ${generateBrightnessVariants(settings.secondaryColor, 'light')}`;
|
|
86
|
-
// Genera i valori dei font in modo sicuro
|
|
87
|
-
const headingFontValue = settings.headingFont
|
|
88
|
-
? `'${settings.headingFont}', sans-serif`
|
|
89
|
-
: 'system-layout, sans-serif';
|
|
90
|
-
const textFontValue = settings.textFont
|
|
91
|
-
? `'${settings.textFont}', sans-serif`
|
|
92
|
-
: 'system-layout, sans-serif';
|
|
93
|
-
return `
|
|
94
|
-
${fontsToImport}
|
|
95
|
-
|
|
96
|
-
:root {
|
|
97
|
-
--font-heading: ${headingFontValue};
|
|
98
|
-
--font-text: ${textFontValue};
|
|
99
|
-
--color-white: #ffffff;
|
|
100
|
-
--color-black: #000000;
|
|
101
|
-
--color-foreground: ${settings.foregroundColor || '#FFFFFF'};
|
|
102
|
-
${primaryVars}
|
|
103
|
-
${secondaryVars}
|
|
104
|
-
${accentVars}
|
|
105
|
-
${darkVars}
|
|
106
|
-
${lightVars}
|
|
107
|
-
}
|
|
108
|
-
`;
|
|
109
|
-
}
|
|
110
|
-
export default generateCssVars;
|