@flow.os/style 0.0.1-dev.1771785969 → 0.0.1-dev.1771840262
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/README.md +18 -1
- package/index.ts +29 -15
- package/package.json +6 -1
- package/react.ts +68 -0
- package/resolve.ts +44 -1
- package/server.ts +299 -0
- package/shorthand.ts +34 -0
- package/style-builder/button.ts +41 -0
- package/style-builder/constants.ts +16 -0
- package/style-builder/dom.ts +18 -0
- package/style-builder/index.ts +48 -0
- package/style-builder/panel.ts +69 -0
- package/style-builder/position.ts +25 -0
- package/visual-builder.ts +822 -0
- package/vite-plugin.ts +86 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flow Style Builder – pulsante tondo fisso in un angolo,
|
|
3
|
+
* al click apre il pannello laterale (sx o dx in base alla posizione).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { BUTTON_ID, PANEL_ID } from './constants.js';
|
|
7
|
+
import { createPanel } from './panel.js';
|
|
8
|
+
import { createButton } from './button.js';
|
|
9
|
+
import { flowStyleBuilder } from './position.js';
|
|
10
|
+
import type { FlowStyleBuilderPosition } from './position.js';
|
|
11
|
+
|
|
12
|
+
export type { FlowStyleBuilderPosition };
|
|
13
|
+
export { flowStyleBuilder };
|
|
14
|
+
|
|
15
|
+
export type FlowStyleBuilderOptions = {
|
|
16
|
+
/** Iframe che mostra l'app (stesso origin). */
|
|
17
|
+
previewIframe?: HTMLIFrameElement;
|
|
18
|
+
/** Posizione del pulsante (obbligatoria da flow.config). */
|
|
19
|
+
position: FlowStyleBuilderPosition;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Inizializza il Flow Style Builder: pulsante fisso in angolo + pannello laterale al click. */
|
|
23
|
+
export function initFlowStyleBuilder(options: FlowStyleBuilderOptions): void {
|
|
24
|
+
if (document.getElementById(BUTTON_ID) || document.getElementById(PANEL_ID)) return;
|
|
25
|
+
|
|
26
|
+
const corner = options.position;
|
|
27
|
+
let panelOpen = false;
|
|
28
|
+
const panelRight = corner === 'top-right' || corner === 'bottom-right';
|
|
29
|
+
|
|
30
|
+
const { element: panel, open: openPanel, close: closePanel } = createPanel(panelRight, () => {
|
|
31
|
+
panelOpen = false;
|
|
32
|
+
closePanel();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
document.body.appendChild(panel);
|
|
36
|
+
|
|
37
|
+
const btn = createButton(corner, () => {
|
|
38
|
+
if (panelOpen) {
|
|
39
|
+
panelOpen = false;
|
|
40
|
+
closePanel();
|
|
41
|
+
} else {
|
|
42
|
+
panelOpen = true;
|
|
43
|
+
openPanel();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
document.body.appendChild(btn);
|
|
48
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Pannello laterale del Flow Style Builder. */
|
|
2
|
+
|
|
3
|
+
import { createEl } from './dom.js';
|
|
4
|
+
import { PANEL_ID, PANEL_WIDTH, THEME } from './constants.js';
|
|
5
|
+
|
|
6
|
+
export function createPanel(initialRight: boolean, onClose: () => void): {
|
|
7
|
+
element: HTMLDivElement;
|
|
8
|
+
open: () => void;
|
|
9
|
+
close: () => void;
|
|
10
|
+
} {
|
|
11
|
+
const panel = createEl('div', {
|
|
12
|
+
position: 'fixed',
|
|
13
|
+
top: '0',
|
|
14
|
+
width: `${PANEL_WIDTH}px`,
|
|
15
|
+
height: '100vh',
|
|
16
|
+
background: THEME.bg,
|
|
17
|
+
color: THEME.text,
|
|
18
|
+
fontFamily: 'ui-sans-serif, system-ui, sans-serif',
|
|
19
|
+
fontSize: '12px',
|
|
20
|
+
boxShadow: '0 0 24px rgba(0,0,0,0.4)',
|
|
21
|
+
display: 'none',
|
|
22
|
+
flexDirection: 'column',
|
|
23
|
+
zIndex: '2147483646',
|
|
24
|
+
overflow: 'hidden',
|
|
25
|
+
});
|
|
26
|
+
panel.id = PANEL_ID;
|
|
27
|
+
|
|
28
|
+
function open(): void {
|
|
29
|
+
const s = panel.style as unknown as Record<string, string>;
|
|
30
|
+
s['right'] = initialRight ? '0' : '';
|
|
31
|
+
s['left'] = initialRight ? '' : '0';
|
|
32
|
+
panel.style.display = 'flex';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function close(): void {
|
|
36
|
+
panel.style.display = 'none';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const header = createEl('div', {
|
|
40
|
+
padding: '10px 12px',
|
|
41
|
+
borderBottom: `1px solid ${THEME.border}`,
|
|
42
|
+
display: 'flex',
|
|
43
|
+
alignItems: 'center',
|
|
44
|
+
justifyContent: 'space-between',
|
|
45
|
+
background: THEME.surface,
|
|
46
|
+
});
|
|
47
|
+
const title = createEl('span', { fontWeight: '600', fontSize: '13px' });
|
|
48
|
+
title.textContent = 'Flow Style Builder';
|
|
49
|
+
const closeBtn = createEl('button', {
|
|
50
|
+
padding: '6px',
|
|
51
|
+
border: `1px solid ${THEME.border}`,
|
|
52
|
+
borderRadius: '6px',
|
|
53
|
+
background: 'transparent',
|
|
54
|
+
color: THEME.muted,
|
|
55
|
+
cursor: 'pointer',
|
|
56
|
+
}) as HTMLButtonElement;
|
|
57
|
+
closeBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>';
|
|
58
|
+
closeBtn.title = 'Chiudi';
|
|
59
|
+
closeBtn.addEventListener('click', onClose);
|
|
60
|
+
header.appendChild(title);
|
|
61
|
+
header.appendChild(closeBtn);
|
|
62
|
+
panel.appendChild(header);
|
|
63
|
+
|
|
64
|
+
const body = createEl('div', { flex: '1', overflow: 'auto', padding: '12px', color: THEME.muted });
|
|
65
|
+
body.textContent = 'Contenuto da aggiungere.';
|
|
66
|
+
panel.appendChild(body);
|
|
67
|
+
|
|
68
|
+
return { element: panel, open, close };
|
|
69
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Posizione del pulsante: uno dei quattro angoli. */
|
|
2
|
+
|
|
3
|
+
import { MARGIN } from './constants.js';
|
|
4
|
+
|
|
5
|
+
export type FlowStyleBuilderPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
6
|
+
|
|
7
|
+
/** Passa la posizione (es. flowStyleBuilder: flowStyleBuilder('bottom-right') in flow.config). */
|
|
8
|
+
export function flowStyleBuilder(position: FlowStyleBuilderPosition): FlowStyleBuilderPosition {
|
|
9
|
+
return position;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function cornerToStyles(corner: FlowStyleBuilderPosition): Partial<CSSStyleDeclaration> {
|
|
13
|
+
const m = `${MARGIN}px`;
|
|
14
|
+
switch (corner) {
|
|
15
|
+
case 'top-left':
|
|
16
|
+
return { top: m, left: m, right: '', bottom: '' };
|
|
17
|
+
case 'top-right':
|
|
18
|
+
return { top: m, left: '', right: m, bottom: '' };
|
|
19
|
+
case 'bottom-left':
|
|
20
|
+
return { top: '', left: m, right: '', bottom: m };
|
|
21
|
+
case 'bottom-right':
|
|
22
|
+
default:
|
|
23
|
+
return { top: '', left: '', right: m, bottom: m };
|
|
24
|
+
}
|
|
25
|
+
}
|