create-flow-os 0.0.1-dev.1771840262 → 0.0.1-dev.1771979366

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.
Files changed (230) hide show
  1. package/package.json +8 -23
  2. package/{profiles/server/packages/style → src/create}/index.ts +31 -30
  3. package/src/index.ts +14 -0
  4. package/src/init/index.ts +66 -0
  5. package/src/init/lib.ts +36 -0
  6. package/src/init/scaffold.ts +43 -0
  7. package/LICENSE +0 -97
  8. package/README.md +0 -26
  9. package/bin/index.js +0 -1215
  10. package/config.json +0 -89
  11. package/lib/utils.ts +0 -91
  12. package/packages/client/client/root.css +0 -9
  13. package/packages/client/client/root.tsx +0 -6
  14. package/packages/client/client/routes/404.tsx +0 -24
  15. package/packages/client/client/routes/index.tsx +0 -48
  16. package/packages/server/server/routes/hello.get.ts +0 -3
  17. package/profiles/client/.dockerignore +0 -12
  18. package/profiles/client/.oxfmtrc.json +0 -7
  19. package/profiles/client/.oxlintrc.json +0 -13
  20. package/profiles/client/.vscode/settings.json +0 -12
  21. package/profiles/client/Dockerfile +0 -26
  22. package/profiles/client/README.md +0 -34
  23. package/profiles/client/bun.lock +0 -352
  24. package/profiles/client/client/root.css +0 -9
  25. package/profiles/client/client/root.tsx +0 -6
  26. package/profiles/client/client/routes/404.tsx +0 -24
  27. package/profiles/client/client/routes/about.tsx +0 -7
  28. package/profiles/client/client/routes/index.tsx +0 -48
  29. package/profiles/client/flow.config.ts +0 -6
  30. package/profiles/client/index.html +0 -5
  31. package/profiles/client/package.json +0 -32
  32. package/profiles/client/packages/client/LICENSE +0 -97
  33. package/profiles/client/packages/client/build/config.ts +0 -211
  34. package/profiles/client/packages/client/build/vite.ts +0 -98
  35. package/profiles/client/packages/client/features/attrs.ts +0 -32
  36. package/profiles/client/packages/client/features/class-flow.ts +0 -116
  37. package/profiles/client/packages/client/features/index.ts +0 -8
  38. package/profiles/client/packages/client/features/pseudo-injector.ts +0 -40
  39. package/profiles/client/packages/client/features/style-flow.ts +0 -106
  40. package/profiles/client/packages/client/features/style.ts +0 -27
  41. package/profiles/client/packages/client/features/utils.ts +0 -4
  42. package/profiles/client/packages/client/features/viewport.ts +0 -20
  43. package/profiles/client/packages/client/index.ts +0 -7
  44. package/profiles/client/packages/client/package.json +0 -48
  45. package/profiles/client/packages/client/runtime/dom.ts +0 -2
  46. package/profiles/client/packages/client/runtime/jsx-dev-runtime.ts +0 -1
  47. package/profiles/client/packages/client/runtime/jsx-runtime.ts +0 -1
  48. package/profiles/client/packages/client/runtime/jsx-types.d.ts +0 -66
  49. package/profiles/client/packages/client/runtime/jsx.ts +0 -101
  50. package/profiles/client/packages/client/scripts/build.ts +0 -14
  51. package/profiles/client/packages/client/scripts/preview.ts +0 -14
  52. package/profiles/client/packages/client/scripts/start-dev.ts +0 -49
  53. package/profiles/client/packages/core/LICENSE +0 -97
  54. package/profiles/client/packages/core/dom.ts +0 -43
  55. package/profiles/client/packages/core/for.ts +0 -42
  56. package/profiles/client/packages/core/index.ts +0 -5
  57. package/profiles/client/packages/core/lifecycle.ts +0 -6
  58. package/profiles/client/packages/core/package.json +0 -16
  59. package/profiles/client/packages/core/show-switch.ts +0 -56
  60. package/profiles/client/packages/core/state.ts +0 -56
  61. package/profiles/client/packages/router/LICENSE +0 -97
  62. package/profiles/client/packages/router/index.ts +0 -20
  63. package/profiles/client/packages/router/matcher.ts +0 -105
  64. package/profiles/client/packages/router/package.json +0 -15
  65. package/profiles/client/packages/router/router.ts +0 -185
  66. package/profiles/client/packages/router/types.ts +0 -34
  67. package/profiles/client/packages/router/utils.ts +0 -45
  68. package/profiles/client/packages/style/LICENSE +0 -97
  69. package/profiles/client/packages/style/breakpoints.ts +0 -20
  70. package/profiles/client/packages/style/extension/.vscodeignore +0 -5
  71. package/profiles/client/packages/style/extension/flow-style-colors-0.0.1.vsix +0 -0
  72. package/profiles/client/packages/style/extension/out/extension.js +0 -130
  73. package/profiles/client/packages/style/extension/package.json +0 -24
  74. package/profiles/client/packages/style/extension/src/extension.ts +0 -146
  75. package/profiles/client/packages/style/extension/tsconfig.json +0 -12
  76. package/profiles/client/packages/style/index.ts +0 -30
  77. package/profiles/client/packages/style/package.json +0 -20
  78. package/profiles/client/packages/style/react.ts +0 -68
  79. package/profiles/client/packages/style/resolve.ts +0 -127
  80. package/profiles/client/packages/style/server.ts +0 -299
  81. package/profiles/client/packages/style/shorthand.ts +0 -96
  82. package/profiles/client/packages/style/style-builder/button.ts +0 -41
  83. package/profiles/client/packages/style/style-builder/constants.ts +0 -16
  84. package/profiles/client/packages/style/style-builder/dom.ts +0 -18
  85. package/profiles/client/packages/style/style-builder/index.ts +0 -48
  86. package/profiles/client/packages/style/style-builder/panel.ts +0 -69
  87. package/profiles/client/packages/style/style-builder/position.ts +0 -25
  88. package/profiles/client/packages/style/visual-builder.ts +0 -822
  89. package/profiles/client/packages/style/vite-plugin.ts +0 -86
  90. package/profiles/client/tsconfig.json +0 -30
  91. package/profiles/full/.dockerignore +0 -12
  92. package/profiles/full/.oxfmtrc.json +0 -7
  93. package/profiles/full/.oxlintrc.json +0 -13
  94. package/profiles/full/.vscode/settings.json +0 -12
  95. package/profiles/full/Dockerfile +0 -26
  96. package/profiles/full/README.md +0 -34
  97. package/profiles/full/bun.lock +0 -352
  98. package/profiles/full/client/root.css +0 -9
  99. package/profiles/full/client/root.tsx +0 -6
  100. package/profiles/full/client/routes/404.tsx +0 -24
  101. package/profiles/full/client/routes/about.tsx +0 -7
  102. package/profiles/full/client/routes/index.tsx +0 -48
  103. package/profiles/full/flow.config.ts +0 -6
  104. package/profiles/full/index.html +0 -5
  105. package/profiles/full/package.json +0 -33
  106. package/profiles/full/packages/client/LICENSE +0 -97
  107. package/profiles/full/packages/client/build/config.ts +0 -211
  108. package/profiles/full/packages/client/build/vite.ts +0 -98
  109. package/profiles/full/packages/client/features/attrs.ts +0 -32
  110. package/profiles/full/packages/client/features/class-flow.ts +0 -116
  111. package/profiles/full/packages/client/features/index.ts +0 -8
  112. package/profiles/full/packages/client/features/pseudo-injector.ts +0 -40
  113. package/profiles/full/packages/client/features/style-flow.ts +0 -106
  114. package/profiles/full/packages/client/features/style.ts +0 -27
  115. package/profiles/full/packages/client/features/utils.ts +0 -4
  116. package/profiles/full/packages/client/features/viewport.ts +0 -20
  117. package/profiles/full/packages/client/index.ts +0 -7
  118. package/profiles/full/packages/client/package.json +0 -48
  119. package/profiles/full/packages/client/runtime/dom.ts +0 -2
  120. package/profiles/full/packages/client/runtime/jsx-dev-runtime.ts +0 -1
  121. package/profiles/full/packages/client/runtime/jsx-runtime.ts +0 -1
  122. package/profiles/full/packages/client/runtime/jsx-types.d.ts +0 -66
  123. package/profiles/full/packages/client/runtime/jsx.ts +0 -101
  124. package/profiles/full/packages/client/scripts/build.ts +0 -14
  125. package/profiles/full/packages/client/scripts/preview.ts +0 -14
  126. package/profiles/full/packages/client/scripts/start-dev.ts +0 -49
  127. package/profiles/full/packages/core/LICENSE +0 -97
  128. package/profiles/full/packages/core/dom.ts +0 -43
  129. package/profiles/full/packages/core/for.ts +0 -42
  130. package/profiles/full/packages/core/index.ts +0 -5
  131. package/profiles/full/packages/core/lifecycle.ts +0 -6
  132. package/profiles/full/packages/core/package.json +0 -16
  133. package/profiles/full/packages/core/show-switch.ts +0 -56
  134. package/profiles/full/packages/core/state.ts +0 -56
  135. package/profiles/full/packages/router/LICENSE +0 -97
  136. package/profiles/full/packages/router/index.ts +0 -20
  137. package/profiles/full/packages/router/matcher.ts +0 -105
  138. package/profiles/full/packages/router/package.json +0 -15
  139. package/profiles/full/packages/router/router.ts +0 -185
  140. package/profiles/full/packages/router/types.ts +0 -34
  141. package/profiles/full/packages/router/utils.ts +0 -45
  142. package/profiles/full/packages/server/LICENSE +0 -97
  143. package/profiles/full/packages/server/core.ts +0 -140
  144. package/profiles/full/packages/server/index.ts +0 -24
  145. package/profiles/full/packages/server/package.json +0 -32
  146. package/profiles/full/packages/server/plugin.ts +0 -79
  147. package/profiles/full/packages/server/production.ts +0 -75
  148. package/profiles/full/packages/server/scripts/start.ts +0 -11
  149. package/profiles/full/packages/style/LICENSE +0 -97
  150. package/profiles/full/packages/style/breakpoints.ts +0 -20
  151. package/profiles/full/packages/style/extension/.vscodeignore +0 -5
  152. package/profiles/full/packages/style/extension/flow-style-colors-0.0.1.vsix +0 -0
  153. package/profiles/full/packages/style/extension/out/extension.js +0 -130
  154. package/profiles/full/packages/style/extension/package.json +0 -24
  155. package/profiles/full/packages/style/extension/src/extension.ts +0 -146
  156. package/profiles/full/packages/style/extension/tsconfig.json +0 -12
  157. package/profiles/full/packages/style/index.ts +0 -30
  158. package/profiles/full/packages/style/package.json +0 -20
  159. package/profiles/full/packages/style/react.ts +0 -68
  160. package/profiles/full/packages/style/resolve.ts +0 -127
  161. package/profiles/full/packages/style/server.ts +0 -299
  162. package/profiles/full/packages/style/shorthand.ts +0 -96
  163. package/profiles/full/packages/style/style-builder/button.ts +0 -41
  164. package/profiles/full/packages/style/style-builder/constants.ts +0 -16
  165. package/profiles/full/packages/style/style-builder/dom.ts +0 -18
  166. package/profiles/full/packages/style/style-builder/index.ts +0 -48
  167. package/profiles/full/packages/style/style-builder/panel.ts +0 -69
  168. package/profiles/full/packages/style/style-builder/position.ts +0 -25
  169. package/profiles/full/packages/style/visual-builder.ts +0 -822
  170. package/profiles/full/packages/style/vite-plugin.ts +0 -86
  171. package/profiles/full/server/routes/hello.get.ts +0 -3
  172. package/profiles/full/tsconfig.json +0 -30
  173. package/profiles/server/.dockerignore +0 -12
  174. package/profiles/server/.oxfmtrc.json +0 -7
  175. package/profiles/server/.oxlintrc.json +0 -13
  176. package/profiles/server/.vscode/settings.json +0 -12
  177. package/profiles/server/Dockerfile +0 -26
  178. package/profiles/server/README.md +0 -34
  179. package/profiles/server/bun.lock +0 -352
  180. package/profiles/server/flow.config.ts +0 -7
  181. package/profiles/server/index.html +0 -5
  182. package/profiles/server/package.json +0 -30
  183. package/profiles/server/packages/core/LICENSE +0 -97
  184. package/profiles/server/packages/core/dom.ts +0 -43
  185. package/profiles/server/packages/core/for.ts +0 -42
  186. package/profiles/server/packages/core/index.ts +0 -5
  187. package/profiles/server/packages/core/lifecycle.ts +0 -6
  188. package/profiles/server/packages/core/package.json +0 -16
  189. package/profiles/server/packages/core/show-switch.ts +0 -56
  190. package/profiles/server/packages/core/state.ts +0 -56
  191. package/profiles/server/packages/router/LICENSE +0 -97
  192. package/profiles/server/packages/router/index.ts +0 -20
  193. package/profiles/server/packages/router/matcher.ts +0 -105
  194. package/profiles/server/packages/router/package.json +0 -15
  195. package/profiles/server/packages/router/router.ts +0 -185
  196. package/profiles/server/packages/router/types.ts +0 -34
  197. package/profiles/server/packages/router/utils.ts +0 -45
  198. package/profiles/server/packages/server/LICENSE +0 -97
  199. package/profiles/server/packages/server/core.ts +0 -140
  200. package/profiles/server/packages/server/index.ts +0 -24
  201. package/profiles/server/packages/server/package.json +0 -32
  202. package/profiles/server/packages/server/plugin.ts +0 -79
  203. package/profiles/server/packages/server/production.ts +0 -75
  204. package/profiles/server/packages/server/scripts/start.ts +0 -11
  205. package/profiles/server/packages/style/LICENSE +0 -97
  206. package/profiles/server/packages/style/breakpoints.ts +0 -20
  207. package/profiles/server/packages/style/extension/.vscodeignore +0 -5
  208. package/profiles/server/packages/style/extension/flow-style-colors-0.0.1.vsix +0 -0
  209. package/profiles/server/packages/style/extension/out/extension.js +0 -130
  210. package/profiles/server/packages/style/extension/package.json +0 -24
  211. package/profiles/server/packages/style/extension/src/extension.ts +0 -146
  212. package/profiles/server/packages/style/extension/tsconfig.json +0 -12
  213. package/profiles/server/packages/style/package.json +0 -20
  214. package/profiles/server/packages/style/react.ts +0 -68
  215. package/profiles/server/packages/style/resolve.ts +0 -127
  216. package/profiles/server/packages/style/server.ts +0 -299
  217. package/profiles/server/packages/style/shorthand.ts +0 -96
  218. package/profiles/server/packages/style/style-builder/button.ts +0 -41
  219. package/profiles/server/packages/style/style-builder/constants.ts +0 -16
  220. package/profiles/server/packages/style/style-builder/dom.ts +0 -18
  221. package/profiles/server/packages/style/style-builder/index.ts +0 -48
  222. package/profiles/server/packages/style/style-builder/panel.ts +0 -69
  223. package/profiles/server/packages/style/style-builder/position.ts +0 -25
  224. package/profiles/server/packages/style/visual-builder.ts +0 -822
  225. package/profiles/server/packages/style/vite-plugin.ts +0 -86
  226. package/profiles/server/server/routes/hello.get.ts +0 -3
  227. package/profiles/server/tsconfig.json +0 -30
  228. package/templates/flow.config.client.ts +0 -6
  229. package/templates/flow.config.full.ts +0 -6
  230. package/templates/flow.config.server.ts +0 -7
@@ -1,127 +0,0 @@
1
- import { isStyleKey, getStyleProp, toStyleValue } from './shorthand.js';
2
- import { VIEWPORT_KEYS, PSEUDO_KEYS, type ViewportKey } from './breakpoints.js';
3
-
4
- const DEFAULT_TOKENS = new Set(['primary', 'muted', 'primary-foreground']);
5
-
6
- /** Layer già "plain" (getter chiamati dal runtime). base + flat style/class. */
7
- export type PlainLayer = {
8
- base?: string;
9
- [key: string]: string | number | boolean | PlainLayer | undefined;
10
- };
11
-
12
- export type ResolvedLayer = { class: string; style: Record<string, string> };
13
-
14
- const RESERVED = new Set([
15
- ...VIEWPORT_KEYS,
16
- ...PSEUDO_KEYS,
17
- ]);
18
-
19
- function isReserved(key: string): boolean {
20
- return RESERVED.has(key as 'mob');
21
- }
22
-
23
- /** Risolve un layer plain in class + style. Non considera mob/tab/des/hover/active. */
24
- export function resolveLayer(plain: PlainLayer, tokens?: Set<string>): ResolvedLayer {
25
- const t = tokens ?? DEFAULT_TOKENS;
26
- const classes: string[] = [];
27
- const style: Record<string, string> = {};
28
-
29
- if (plain.base) classes.push(plain.base.trim());
30
-
31
- for (const [k, v] of Object.entries(plain)) {
32
- if (k === 'base' || isReserved(k)) continue;
33
- if (v === undefined || v === null) continue;
34
-
35
- if (isStyleKey(k)) {
36
- const prop = getStyleProp(k);
37
- if (prop) {
38
- let val = toStyleValue(v, t);
39
- if (k === 'scale' && typeof v === 'number') val = `scale(${v})`;
40
- style[prop] = val;
41
- }
42
- } else {
43
- if (v === true) classes.push(k);
44
- if (typeof v === 'string' && v) classes.push(v);
45
- }
46
- }
47
-
48
- return {
49
- class: classes.filter(Boolean).join(' '),
50
- style,
51
- };
52
- }
53
-
54
- /** Merge due resolved: second sovrascrive style, class è concatenata. */
55
- export function mergeResolved(a: ResolvedLayer, b: ResolvedLayer): ResolvedLayer {
56
- return {
57
- class: [a.class, b.class].filter(Boolean).join(' '),
58
- style: { ...a.style, ...b.style },
59
- };
60
- }
61
-
62
- /** Solo stile da un layer (per pseudo). Ignora base e classList. */
63
- export function resolvePseudoStyle(plain: PlainLayer, tokens?: Set<string>): Record<string, string> {
64
- const t = tokens ?? DEFAULT_TOKENS;
65
- const style: Record<string, string> = {};
66
- for (const [k, v] of Object.entries(plain)) {
67
- if (k === 'base' || isReserved(k)) continue;
68
- if (!isStyleKey(k)) continue;
69
- const prop = getStyleProp(k);
70
- if (prop && v !== undefined && v !== null) {
71
- let val = toStyleValue(v, t);
72
- if (k === 'scale' && typeof v === 'number') val = `scale(${v})`;
73
- style[prop] = val;
74
- }
75
- }
76
- return style;
77
- }
78
-
79
- /** Da oggetto stile a stringa CSS (per iniettare regola :hover). */
80
- export function styleToCssText(style: Record<string, string>): string {
81
- return Object.entries(style)
82
- .map(([k, v]) => `${k}: ${v}`)
83
- .join('; ');
84
- }
85
-
86
- /** Stesso formato di styleFlow (stringa | [base, layer] | layer), ma solo valori plain (no getter). */
87
- type FlowStyleValue =
88
- | string
89
- | [string, PlainLayer]
90
- | (PlainLayer & { base?: string; mob?: PlainLayer; tab?: PlainLayer; des?: PlainLayer });
91
-
92
- /** Normalizza value in base + layer per un viewport. Usabile da React/altro: flowStyle(value, viewport) → { class, style }. */
93
- export function flowStyle(
94
- value: FlowStyleValue | null | undefined,
95
- viewport?: ViewportKey,
96
- tokens?: Set<string>
97
- ): ResolvedLayer {
98
- if (value == null) return { class: '', style: {} };
99
- let base = '';
100
- let layer: PlainLayer = {};
101
- if (typeof value === 'string') {
102
- base = value;
103
- } else if (Array.isArray(value)) {
104
- base = typeof value[0] === 'string' ? value[0] : '';
105
- layer = (value[1] && typeof value[1] === 'object' && !Array.isArray(value[1])) ? (value[1] as PlainLayer) : {};
106
- } else if (typeof value === 'object' && !Array.isArray(value)) {
107
- layer = { ...value };
108
- base = typeof layer.base === 'string' ? layer.base : '';
109
- }
110
- const merged: PlainLayer = { base };
111
- for (const [k, v] of Object.entries(layer)) {
112
- if (k === 'base' || isReserved(k)) continue;
113
- (merged as Record<string, unknown>)[k] = v;
114
- }
115
- if (viewport) {
116
- const vp = layer[viewport];
117
- if (vp && typeof vp === 'object' && !Array.isArray(vp)) {
118
- const vpPlain = vp as PlainLayer;
119
- if (vpPlain.base) merged.base = (merged.base ? `${merged.base} ` : '') + (vpPlain.base ?? '');
120
- for (const [k, v] of Object.entries(vpPlain)) {
121
- if (k === 'base' || isReserved(k)) continue;
122
- (merged as Record<string, unknown>)[k] = v;
123
- }
124
- }
125
- }
126
- return resolveLayer(merged, tokens);
127
- }
@@ -1,299 +0,0 @@
1
- /**
2
- * Server per il Visual Style Builder: espone POST /__flow-style-patch per modificare
3
- * i file sorgente (s= / styleFlow=). Avviabile da CLI o dal plugin Vite.
4
- */
5
- import fs from 'node:fs';
6
- import path from 'node:path';
7
- import http from 'node:http';
8
-
9
- const DEFAULT_PORT = 3757;
10
-
11
- export type StyleFlowServerOptions = {
12
- port?: number;
13
- root?: string;
14
- };
15
-
16
- /** Trova la posizione della } che chiude la { aperta a openIdx (con nesting). */
17
- function findMatchingClose(content: string, openIdx: number): number {
18
- let depth = 0;
19
- for (let i = openIdx; i < content.length; i++) {
20
- const c = content[i];
21
- if (c === '{') depth++;
22
- else if (c === '}') {
23
- depth--;
24
- if (depth === 0) return i;
25
- }
26
- }
27
- return -1;
28
- }
29
-
30
- /** Trova l’oggetto s= o styleFlow= che contiene la riga (1-based); ritorna [start, end] degli indici. */
31
- /** Trova tutti i blocchi s= o styleFlow= nel file; ritorna [{ line }] riga 1-based. */
32
- function findAllStyleBlocks(content: string): { line: number }[] {
33
- const blocks: { line: number }[] = [];
34
- const re = /\s(s|styleFlow)\s*=\s*\{/g;
35
- let m: RegExpExecArray | null;
36
- while ((m = re.exec(content)) !== null) {
37
- const line = content.slice(0, m.index).split(/\r?\n/).length;
38
- const openIdx = content.indexOf('{', m.index);
39
- if (findMatchingClose(content, openIdx) >= 0) blocks.push({ line });
40
- }
41
- return blocks;
42
- }
43
-
44
- const SHORTHAND_KEYS = [
45
- 'p', 'pt', 'pr', 'pb', 'pl', 'm', 'mt', 'mr', 'mb', 'ml',
46
- 'w', 'h', 'minW', 'minH', 'maxW', 'maxH', 'gap', 'rounded', 'text', 'color', 'bg',
47
- 'display', 'flex', 'opacity', 'top', 'left', 'right', 'bottom',
48
- ];
49
-
50
- /** Estrae valori semplici dall inner per le chiavi note. */
51
- function parseStyleInner(inner: string): Record<string, number | string> {
52
- const out: Record<string, number | string> = {};
53
- for (const key of SHORTHAND_KEYS) {
54
- const re = new RegExp(`(?:^|[,\\n])\\s*(?:${key}|"${key}")\\s*:\\s*((-?\\d+(?:\\.\\d+)?)|"([^"]*)"|'([^']*)')`, 'g');
55
- const m = re.exec(inner);
56
- if (!m) continue;
57
- if (m[2] !== undefined) out[key] = parseFloat(m[2]);
58
- else if (m[3] !== undefined) out[key] = m[3];
59
- else if (m[4] !== undefined) out[key] = m[4];
60
- }
61
- return out;
62
- }
63
-
64
- function findStyleObjectRange(content: string, line: number): [number, number] | null {
65
- const lines = content.split(/\r?\n/);
66
- const lineIdx = Math.max(0, line - 1);
67
- const propNames = ['s=', 'styleFlow='];
68
- let searchLineIdx = lineIdx;
69
- while (searchLineIdx >= 0) {
70
- const row = lines[searchLineIdx] ?? '';
71
- for (const name of propNames) {
72
- const idx = row.indexOf(name);
73
- if (idx !== -1) {
74
- const openBrace = row.indexOf('{', idx);
75
- if (openBrace !== -1) {
76
- const globalOpen = lines.slice(0, searchLineIdx).join('\n').length + openBrace;
77
- const closeIdx = findMatchingClose(content, globalOpen);
78
- if (closeIdx !== -1) return [globalOpen, closeIdx];
79
- }
80
- }
81
- }
82
- searchLineIdx--;
83
- }
84
- return null;
85
- }
86
-
87
- function findValueRange(inner: string, key: string): [number, number] | null {
88
- const reKey = new RegExp(`(?:^|[,\\n])\\s*(?:${key}|"${key}")\\s*:\\s*`, 'g');
89
- const m = reKey.exec(inner);
90
- if (!m) return null;
91
- const valueStart = m.index + m[0].length;
92
- let i = valueStart;
93
- const ch = inner[i];
94
- if (ch === '"' || ch === "'") {
95
- const q = ch;
96
- i++;
97
- while (i < inner.length) {
98
- if (inner[i] === '\\') i += 2;
99
- else if (inner[i] === q) return [valueStart, i + 1];
100
- else i++;
101
- }
102
- return null;
103
- }
104
- if (ch === '{' || ch === '[') {
105
- const close = findMatchingClose(inner, i);
106
- return close >= 0 ? [valueStart, close + 1] : null;
107
- }
108
- while (i < inner.length && /[0-9.eE+-]/.test(inner[i] ?? '')) i++;
109
- while (i < inner.length && /[\s)]/.test(inner[i] ?? '')) i++;
110
- if (i < inner.length && inner[i] === ')') i++;
111
- return [valueStart, i];
112
- }
113
-
114
- /** Merge nel file: aggiorna solo le chiavi in style nell’oggetto esistente (s= o styleFlow=). */
115
- function getStyleObjectFromInner(fullInner: string): { inner: string; patchStart: number; patchEnd: number } {
116
- const trimmed = fullInner.trim();
117
- if (!trimmed.startsWith('[')) {
118
- return { inner: fullInner, patchStart: 0, patchEnd: fullInner.length };
119
- }
120
- const firstBrace = fullInner.indexOf('{');
121
- if (firstBrace === -1) return { inner: fullInner, patchStart: 0, patchEnd: fullInner.length };
122
- const closeBrace = findMatchingClose(fullInner, firstBrace);
123
- if (closeBrace === -1) return { inner: fullInner, patchStart: 0, patchEnd: fullInner.length };
124
- return {
125
- inner: fullInner.slice(firstBrace + 1, closeBrace),
126
- patchStart: firstBrace + 1,
127
- patchEnd: closeBrace,
128
- };
129
- }
130
-
131
- function patchStyleInFile(
132
- content: string,
133
- line: number,
134
- style: Record<string, number | string>
135
- ): string {
136
- const range = findStyleObjectRange(content, line);
137
- if (!range) return content;
138
- const [openIdx, closeIdx] = range;
139
- const fullInner = content.slice(openIdx + 1, closeIdx);
140
- const { inner: innerSlice, patchStart, patchEnd } = getStyleObjectFromInner(fullInner);
141
- let inner = innerSlice;
142
- for (const [key, value] of Object.entries(style)) {
143
- const serialized = typeof value === 'number' ? String(value) : JSON.stringify(value);
144
- const valRange = findValueRange(inner, key);
145
- if (valRange) {
146
- const [vs, ve] = valRange;
147
- inner = inner.slice(0, vs) + serialized + inner.slice(ve);
148
- } else {
149
- const trim = inner.trimEnd();
150
- inner = trim + (trim.endsWith(',') ? '' : ',') + `\n ${key}: ${serialized}`;
151
- }
152
- }
153
- return (
154
- content.slice(0, openIdx + 1 + patchStart) +
155
- inner +
156
- content.slice(openIdx + 1 + patchEnd)
157
- );
158
- }
159
-
160
- function createServer(options: StyleFlowServerOptions = {}) {
161
- const port = options.port ?? DEFAULT_PORT;
162
- const root = path.resolve(options.root ?? process.cwd());
163
-
164
- const server = http.createServer((req, res) => {
165
- res.setHeader('Access-Control-Allow-Origin', '*');
166
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
167
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
168
-
169
- if (req.method === 'OPTIONS') {
170
- res.writeHead(204);
171
- res.end();
172
- return;
173
- }
174
-
175
- const url = req.url ?? '';
176
- const urlObj = url.startsWith('/') ? new URL(url, 'http://localhost') : null;
177
- const pathname = urlObj?.pathname ?? url.split('?')[0];
178
- const fileParam = urlObj?.searchParams.get('file');
179
- const lineParam = urlObj?.searchParams.get('line');
180
-
181
- if (req.method === 'GET' && pathname === '/__flow-style-blocks' && fileParam) {
182
- try {
183
- const file = fileParam.trim();
184
- const safePath = path.normalize(file).replace(/^(\.\.(\/|\\|$))+/, '');
185
- const absPath = path.join(root, safePath);
186
- if (!absPath.startsWith(root)) {
187
- res.writeHead(403, { 'Content-Type': 'application/json' });
188
- res.end(JSON.stringify({ error: 'Invalid path' }));
189
- return;
190
- }
191
- const content = fs.readFileSync(absPath, 'utf8');
192
- const blocks = findAllStyleBlocks(content);
193
- res.writeHead(200, { 'Content-Type': 'application/json' });
194
- res.end(JSON.stringify({ blocks }));
195
- } catch (err) {
196
- res.writeHead(500, { 'Content-Type': 'application/json' });
197
- res.end(JSON.stringify({ error: err instanceof Error ? err.message : 'Unknown error' }));
198
- }
199
- return;
200
- }
201
-
202
- if (req.method === 'GET' && pathname === '/__flow-style-read' && fileParam && lineParam) {
203
- try {
204
- const file = fileParam.trim();
205
- const line = parseInt(lineParam, 10);
206
- const safePath = path.normalize(file).replace(/^(\.\.(\/|\\|$))+/, '');
207
- const absPath = path.join(root, safePath);
208
- if (!absPath.startsWith(root)) {
209
- res.writeHead(403, { 'Content-Type': 'application/json' });
210
- res.end(JSON.stringify({ error: 'Invalid path' }));
211
- return;
212
- }
213
- const content = fs.readFileSync(absPath, 'utf8');
214
- const range = findStyleObjectRange(content, line);
215
- if (!range) {
216
- res.writeHead(404, { 'Content-Type': 'application/json' });
217
- res.end(JSON.stringify({ error: 'Block not found' }));
218
- return;
219
- }
220
- const fullInner = content.slice(range[0] + 1, range[1]);
221
- const { inner } = getStyleObjectFromInner(fullInner);
222
- const style = parseStyleInner(inner);
223
- res.writeHead(200, { 'Content-Type': 'application/json' });
224
- res.end(JSON.stringify({ style }));
225
- } catch (err) {
226
- res.writeHead(500, { 'Content-Type': 'application/json' });
227
- res.end(JSON.stringify({ error: err instanceof Error ? err.message : 'Unknown error' }));
228
- }
229
- return;
230
- }
231
-
232
- if (req.method !== 'POST' || pathname !== '/__flow-style-patch') {
233
- res.writeHead(404, { 'Content-Type': 'application/json' });
234
- res.end(JSON.stringify({ error: 'Not found' }));
235
- return;
236
- }
237
-
238
- let body = '';
239
- req.on('data', (chunk) => (body += chunk));
240
- req.on('end', () => {
241
- try {
242
- const { file, line, style } = JSON.parse(body) as {
243
- file?: string;
244
- line?: number;
245
- style?: Record<string, number | string>;
246
- };
247
- if (!file || typeof line !== 'number' || !style || typeof style !== 'object') {
248
- res.writeHead(400, { 'Content-Type': 'application/json' });
249
- res.end(JSON.stringify({ error: 'file, line, style required' }));
250
- return;
251
- }
252
- const safePath = path.normalize(file).replace(/^(\.\.(\/|\\|$))+/, '');
253
- const absPath = path.join(root, safePath);
254
- if (!absPath.startsWith(root)) {
255
- res.writeHead(403, { 'Content-Type': 'application/json' });
256
- res.end(JSON.stringify({ error: 'Invalid path' }));
257
- return;
258
- }
259
- const content = fs.readFileSync(absPath, 'utf8');
260
- const next = patchStyleInFile(content, line, style);
261
- fs.writeFileSync(absPath, next, 'utf8');
262
- res.writeHead(200, { 'Content-Type': 'application/json' });
263
- res.end(JSON.stringify({ ok: true }));
264
- } catch (err) {
265
- res.writeHead(500, { 'Content-Type': 'application/json' });
266
- res.end(
267
- JSON.stringify({
268
- error: err instanceof Error ? err.message : 'Unknown error',
269
- })
270
- );
271
- }
272
- });
273
- });
274
-
275
- return { server, port };
276
- }
277
-
278
- /**
279
- * Avvia il server di patch per il Style Builder.
280
- * Chiamabile da script o dal plugin Vite.
281
- */
282
- export function styleFlowServer(options: StyleFlowServerOptions = {}): void {
283
- const port = options.port ?? DEFAULT_PORT;
284
- const root = options.root ?? process.cwd();
285
- const { server } = createServer({ port, root });
286
- server.listen(port, '127.0.0.1', () => {
287
- console.log(`[flow-style] Patch server http://127.0.0.1:${port} (root: ${root})`);
288
- });
289
- }
290
-
291
- /** Per uso interno del plugin Vite: ritorna l'istanza e la porta. */
292
- export function createStyleFlowServer(options: StyleFlowServerOptions = {}): {
293
- server: http.Server;
294
- port: number;
295
- } {
296
- const port = options.port ?? DEFAULT_PORT;
297
- const { server } = createServer({ ...options, port });
298
- return { server, port };
299
- }
@@ -1,96 +0,0 @@
1
- /**
2
- * Shorthand → CSS property. Solo chiavi "pure" (no suffisso tipo mb-10).
3
- * Usato per decidere se una chiave è stile (valore number/string/getter) o classList (bool/getter).
4
- */
5
- export const SHORTHAND_MAP = {
6
- text: 'fontSize',
7
- mb: 'marginBottom',
8
- mt: 'marginTop',
9
- ml: 'marginLeft',
10
- mr: 'marginRight',
11
- mx: 'marginLeft',
12
- my: 'marginTop',
13
- m: 'margin',
14
- pb: 'paddingBottom',
15
- pt: 'paddingTop',
16
- pl: 'paddingLeft',
17
- pr: 'paddingRight',
18
- px: 'paddingLeft',
19
- py: 'paddingTop',
20
- p: 'padding',
21
- w: 'width',
22
- h: 'height',
23
- minW: 'minWidth',
24
- minH: 'minHeight',
25
- maxW: 'maxWidth',
26
- maxH: 'maxHeight',
27
- gap: 'gap',
28
- rounded: 'borderRadius',
29
- top: 'top',
30
- left: 'left',
31
- right: 'right',
32
- bottom: 'bottom',
33
- color: 'color',
34
- bg: 'background',
35
- scale: 'transform',
36
- outline: 'outline',
37
- opacity: 'opacity',
38
- flex: 'flex',
39
- display: 'display',
40
- } as const satisfies Record<string, string>;
41
-
42
- export type StyleShorthandKey = keyof typeof SHORTHAND_MAP;
43
-
44
- const SHORTHAND_SET = new Set<string>(Object.keys(SHORTHAND_MAP));
45
-
46
- export function isStyleKey(key: string): boolean {
47
- return key.startsWith('--') || SHORTHAND_SET.has(key);
48
- }
49
-
50
- export function getStyleProp(key: string): string | undefined {
51
- if (key.startsWith('--')) return key;
52
- return key in SHORTHAND_MAP ? SHORTHAND_MAP[key as StyleShorthandKey] : undefined;
53
- }
54
-
55
- /** CSS property → shorthand (per visual builder: leggere stile da DOM e copiare come styleFlow). */
56
- export const CSS_TO_SHORTHAND: Record<string, string> = {
57
- fontSize: 'text',
58
- marginBottom: 'mb',
59
- marginTop: 'mt',
60
- marginLeft: 'ml',
61
- marginRight: 'mr',
62
- margin: 'm',
63
- paddingBottom: 'pb',
64
- paddingTop: 'pt',
65
- paddingLeft: 'pl',
66
- paddingRight: 'pr',
67
- padding: 'p',
68
- width: 'w',
69
- height: 'h',
70
- minWidth: 'minW',
71
- minHeight: 'minH',
72
- maxWidth: 'maxW',
73
- maxHeight: 'maxH',
74
- gap: 'gap',
75
- borderRadius: 'rounded',
76
- top: 'top',
77
- left: 'left',
78
- right: 'right',
79
- bottom: 'bottom',
80
- color: 'color',
81
- background: 'bg',
82
- transform: 'scale',
83
- outline: 'outline',
84
- opacity: 'opacity',
85
- flex: 'flex',
86
- display: 'display',
87
- };
88
-
89
- /** Numero → "Npx", altrimenti stringa. Token "primary" → var(--color-primary) se in tokens. (scale gestito in resolve.) */
90
- export function toStyleValue(v: unknown, tokens?: Set<string>): string {
91
- if (v == null) return '';
92
- if (typeof v === 'number') return `${v}px`;
93
- const s = String(v);
94
- if (tokens && tokens.has(s)) return `var(--color-${s})`;
95
- return s;
96
- }
@@ -1,41 +0,0 @@
1
- /** Pulsante tondo del Flow Style Builder. */
2
-
3
- import { createEl } from './dom.js';
4
- import { BUTTON_ID, BUTTON_SIZE, THEME } from './constants.js';
5
- import { cornerToStyles } from './position.js';
6
- import type { FlowStyleBuilderPosition } from './position.js';
7
-
8
- export function createButton(
9
- corner: FlowStyleBuilderPosition,
10
- onClick: () => void
11
- ): HTMLButtonElement {
12
- const size = `${BUTTON_SIZE}px`;
13
- const btn = createEl('button', {
14
- position: 'fixed',
15
- width: size,
16
- height: size,
17
- minWidth: size,
18
- minHeight: size,
19
- maxWidth: size,
20
- maxHeight: size,
21
- boxSizing: 'border-box',
22
- borderRadius: '50%',
23
- border: `2px solid ${THEME.border}`,
24
- background: THEME.surface,
25
- color: THEME.accent,
26
- cursor: 'pointer',
27
- display: 'flex',
28
- alignItems: 'center',
29
- justifyContent: 'center',
30
- flexShrink: '0',
31
- zIndex: '2147483647',
32
- boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
33
- }) as HTMLButtonElement;
34
- btn.id = BUTTON_ID;
35
- btn.innerHTML = '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2"/></svg>';
36
- btn.title = 'Flow Style Builder';
37
-
38
- Object.assign(btn.style, cornerToStyles(corner));
39
- btn.addEventListener('click', onClick);
40
- return btn;
41
- }
@@ -1,16 +0,0 @@
1
- /** Costanti UI del Flow Style Builder. */
2
-
3
- export const BUTTON_ID = 'flowStyleBuilder';
4
- export const PANEL_ID = 'flowStyleBuilderPanel';
5
- export const MARGIN = 16;
6
- export const BUTTON_SIZE = 48;
7
- export const PANEL_WIDTH = 300;
8
-
9
- export const THEME = {
10
- bg: '#0f1419',
11
- surface: '#1a1f26',
12
- border: '#2d3748',
13
- accent: '#14b8a6',
14
- text: '#e2e8f0',
15
- muted: '#94a3b8',
16
- } as const;
@@ -1,18 +0,0 @@
1
- /** Helper DOM per il Flow Style Builder. */
2
-
3
- export function setStyles(el: HTMLElement, s: Partial<CSSStyleDeclaration>): void {
4
- for (const [k, v] of Object.entries(s)) {
5
- if (v != null && typeof v === 'string') (el.style as unknown as Record<string, string>)[k] = v;
6
- }
7
- }
8
-
9
- export function createEl<K extends keyof HTMLElementTagNameMap>(
10
- tag: K,
11
- style?: Partial<CSSStyleDeclaration>,
12
- attrs?: Record<string, string>
13
- ): HTMLElementTagNameMap[K] {
14
- const el = document.createElement(tag);
15
- if (style) setStyles(el as unknown as HTMLElement, style);
16
- if (attrs) for (const [k, v] of Object.entries(attrs)) el.setAttribute(k, v);
17
- return el;
18
- }
@@ -1,48 +0,0 @@
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
- }