create-flow-os 0.0.1-dev.1771785969 → 0.0.1-dev.1771979233

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 (186) hide show
  1. package/package.json +8 -23
  2. package/src/create/index.ts +31 -0
  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 -13
  14. package/packages/client/client/routes/404.tsx +0 -24
  15. package/packages/client/client/routes/index.tsx +0 -47
  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 -335
  24. package/profiles/client/client/root.css +0 -9
  25. package/profiles/client/client/root.tsx +0 -13
  26. package/profiles/client/client/routes/404.tsx +0 -24
  27. package/profiles/client/client/routes/index.tsx +0 -47
  28. package/profiles/client/flow.config.ts +0 -3
  29. package/profiles/client/index.html +0 -5
  30. package/profiles/client/package.json +0 -29
  31. package/profiles/client/packages/client/LICENSE +0 -97
  32. package/profiles/client/packages/client/build/config.ts +0 -166
  33. package/profiles/client/packages/client/build/vite.ts +0 -54
  34. package/profiles/client/packages/client/features/attrs.ts +0 -32
  35. package/profiles/client/packages/client/features/class-flow.ts +0 -116
  36. package/profiles/client/packages/client/features/index.ts +0 -8
  37. package/profiles/client/packages/client/features/pseudo-injector.ts +0 -40
  38. package/profiles/client/packages/client/features/style-flow.ts +0 -106
  39. package/profiles/client/packages/client/features/style.ts +0 -27
  40. package/profiles/client/packages/client/features/utils.ts +0 -4
  41. package/profiles/client/packages/client/features/viewport.ts +0 -20
  42. package/profiles/client/packages/client/index.ts +0 -6
  43. package/profiles/client/packages/client/package.json +0 -48
  44. package/profiles/client/packages/client/runtime/dom.ts +0 -2
  45. package/profiles/client/packages/client/runtime/jsx-dev-runtime.ts +0 -1
  46. package/profiles/client/packages/client/runtime/jsx-runtime.ts +0 -1
  47. package/profiles/client/packages/client/runtime/jsx-types.d.ts +0 -64
  48. package/profiles/client/packages/client/runtime/jsx.ts +0 -99
  49. package/profiles/client/packages/client/scripts/build.ts +0 -14
  50. package/profiles/client/packages/client/scripts/preview.ts +0 -14
  51. package/profiles/client/packages/client/scripts/start-dev.ts +0 -49
  52. package/profiles/client/packages/core/LICENSE +0 -97
  53. package/profiles/client/packages/core/dom.ts +0 -43
  54. package/profiles/client/packages/core/for.ts +0 -42
  55. package/profiles/client/packages/core/index.ts +0 -5
  56. package/profiles/client/packages/core/lifecycle.ts +0 -6
  57. package/profiles/client/packages/core/package.json +0 -16
  58. package/profiles/client/packages/core/show-switch.ts +0 -56
  59. package/profiles/client/packages/core/state.ts +0 -56
  60. package/profiles/client/packages/router/LICENSE +0 -97
  61. package/profiles/client/packages/router/index.ts +0 -174
  62. package/profiles/client/packages/router/package.json +0 -15
  63. package/profiles/client/packages/style/LICENSE +0 -97
  64. package/profiles/client/packages/style/breakpoints.ts +0 -20
  65. package/profiles/client/packages/style/extension/.vscodeignore +0 -5
  66. package/profiles/client/packages/style/extension/flow-style-colors-0.0.1.vsix +0 -0
  67. package/profiles/client/packages/style/extension/out/extension.js +0 -130
  68. package/profiles/client/packages/style/extension/package.json +0 -24
  69. package/profiles/client/packages/style/extension/src/extension.ts +0 -146
  70. package/profiles/client/packages/style/extension/tsconfig.json +0 -12
  71. package/profiles/client/packages/style/index.ts +0 -16
  72. package/profiles/client/packages/style/package.json +0 -15
  73. package/profiles/client/packages/style/resolve.ts +0 -84
  74. package/profiles/client/packages/style/shorthand.ts +0 -62
  75. package/profiles/client/tsconfig.json +0 -30
  76. package/profiles/full/.dockerignore +0 -12
  77. package/profiles/full/.oxfmtrc.json +0 -7
  78. package/profiles/full/.oxlintrc.json +0 -13
  79. package/profiles/full/.vscode/settings.json +0 -12
  80. package/profiles/full/Dockerfile +0 -26
  81. package/profiles/full/README.md +0 -34
  82. package/profiles/full/bun.lock +0 -335
  83. package/profiles/full/client/root.css +0 -9
  84. package/profiles/full/client/root.tsx +0 -13
  85. package/profiles/full/client/routes/404.tsx +0 -24
  86. package/profiles/full/client/routes/index.tsx +0 -47
  87. package/profiles/full/flow.config.ts +0 -8
  88. package/profiles/full/index.html +0 -5
  89. package/profiles/full/package.json +0 -30
  90. package/profiles/full/packages/client/LICENSE +0 -97
  91. package/profiles/full/packages/client/build/config.ts +0 -166
  92. package/profiles/full/packages/client/build/vite.ts +0 -54
  93. package/profiles/full/packages/client/features/attrs.ts +0 -32
  94. package/profiles/full/packages/client/features/class-flow.ts +0 -116
  95. package/profiles/full/packages/client/features/index.ts +0 -8
  96. package/profiles/full/packages/client/features/pseudo-injector.ts +0 -40
  97. package/profiles/full/packages/client/features/style-flow.ts +0 -106
  98. package/profiles/full/packages/client/features/style.ts +0 -27
  99. package/profiles/full/packages/client/features/utils.ts +0 -4
  100. package/profiles/full/packages/client/features/viewport.ts +0 -20
  101. package/profiles/full/packages/client/index.ts +0 -6
  102. package/profiles/full/packages/client/package.json +0 -48
  103. package/profiles/full/packages/client/runtime/dom.ts +0 -2
  104. package/profiles/full/packages/client/runtime/jsx-dev-runtime.ts +0 -1
  105. package/profiles/full/packages/client/runtime/jsx-runtime.ts +0 -1
  106. package/profiles/full/packages/client/runtime/jsx-types.d.ts +0 -64
  107. package/profiles/full/packages/client/runtime/jsx.ts +0 -99
  108. package/profiles/full/packages/client/scripts/build.ts +0 -14
  109. package/profiles/full/packages/client/scripts/preview.ts +0 -14
  110. package/profiles/full/packages/client/scripts/start-dev.ts +0 -49
  111. package/profiles/full/packages/core/LICENSE +0 -97
  112. package/profiles/full/packages/core/dom.ts +0 -43
  113. package/profiles/full/packages/core/for.ts +0 -42
  114. package/profiles/full/packages/core/index.ts +0 -5
  115. package/profiles/full/packages/core/lifecycle.ts +0 -6
  116. package/profiles/full/packages/core/package.json +0 -16
  117. package/profiles/full/packages/core/show-switch.ts +0 -56
  118. package/profiles/full/packages/core/state.ts +0 -56
  119. package/profiles/full/packages/router/LICENSE +0 -97
  120. package/profiles/full/packages/router/index.ts +0 -174
  121. package/profiles/full/packages/router/package.json +0 -15
  122. package/profiles/full/packages/server/LICENSE +0 -97
  123. package/profiles/full/packages/server/core.ts +0 -140
  124. package/profiles/full/packages/server/index.ts +0 -24
  125. package/profiles/full/packages/server/package.json +0 -32
  126. package/profiles/full/packages/server/plugin.ts +0 -79
  127. package/profiles/full/packages/server/production.ts +0 -75
  128. package/profiles/full/packages/server/scripts/start.ts +0 -11
  129. package/profiles/full/packages/style/LICENSE +0 -97
  130. package/profiles/full/packages/style/breakpoints.ts +0 -20
  131. package/profiles/full/packages/style/extension/.vscodeignore +0 -5
  132. package/profiles/full/packages/style/extension/flow-style-colors-0.0.1.vsix +0 -0
  133. package/profiles/full/packages/style/extension/out/extension.js +0 -130
  134. package/profiles/full/packages/style/extension/package.json +0 -24
  135. package/profiles/full/packages/style/extension/src/extension.ts +0 -146
  136. package/profiles/full/packages/style/extension/tsconfig.json +0 -12
  137. package/profiles/full/packages/style/index.ts +0 -16
  138. package/profiles/full/packages/style/package.json +0 -15
  139. package/profiles/full/packages/style/resolve.ts +0 -84
  140. package/profiles/full/packages/style/shorthand.ts +0 -62
  141. package/profiles/full/server/routes/hello.get.ts +0 -3
  142. package/profiles/full/tsconfig.json +0 -30
  143. package/profiles/server/.dockerignore +0 -12
  144. package/profiles/server/.oxfmtrc.json +0 -7
  145. package/profiles/server/.oxlintrc.json +0 -13
  146. package/profiles/server/.vscode/settings.json +0 -12
  147. package/profiles/server/Dockerfile +0 -26
  148. package/profiles/server/README.md +0 -34
  149. package/profiles/server/bun.lock +0 -335
  150. package/profiles/server/flow.config.ts +0 -6
  151. package/profiles/server/index.html +0 -5
  152. package/profiles/server/package.json +0 -27
  153. package/profiles/server/packages/core/LICENSE +0 -97
  154. package/profiles/server/packages/core/dom.ts +0 -43
  155. package/profiles/server/packages/core/for.ts +0 -42
  156. package/profiles/server/packages/core/index.ts +0 -5
  157. package/profiles/server/packages/core/lifecycle.ts +0 -6
  158. package/profiles/server/packages/core/package.json +0 -16
  159. package/profiles/server/packages/core/show-switch.ts +0 -56
  160. package/profiles/server/packages/core/state.ts +0 -56
  161. package/profiles/server/packages/router/LICENSE +0 -97
  162. package/profiles/server/packages/router/index.ts +0 -174
  163. package/profiles/server/packages/router/package.json +0 -15
  164. package/profiles/server/packages/server/LICENSE +0 -97
  165. package/profiles/server/packages/server/core.ts +0 -140
  166. package/profiles/server/packages/server/index.ts +0 -24
  167. package/profiles/server/packages/server/package.json +0 -32
  168. package/profiles/server/packages/server/plugin.ts +0 -79
  169. package/profiles/server/packages/server/production.ts +0 -75
  170. package/profiles/server/packages/server/scripts/start.ts +0 -11
  171. package/profiles/server/packages/style/LICENSE +0 -97
  172. package/profiles/server/packages/style/breakpoints.ts +0 -20
  173. package/profiles/server/packages/style/extension/.vscodeignore +0 -5
  174. package/profiles/server/packages/style/extension/flow-style-colors-0.0.1.vsix +0 -0
  175. package/profiles/server/packages/style/extension/out/extension.js +0 -130
  176. package/profiles/server/packages/style/extension/package.json +0 -24
  177. package/profiles/server/packages/style/extension/src/extension.ts +0 -146
  178. package/profiles/server/packages/style/extension/tsconfig.json +0 -12
  179. package/profiles/server/packages/style/index.ts +0 -16
  180. package/profiles/server/packages/style/package.json +0 -15
  181. package/profiles/server/packages/style/resolve.ts +0 -84
  182. package/profiles/server/packages/style/shorthand.ts +0 -62
  183. package/profiles/server/server/routes/hello.get.ts +0 -3
  184. package/profiles/server/tsconfig.json +0 -30
  185. package/templates/flow.config.client.ts +0 -3
  186. package/templates/flow.config.server.ts +0 -6
@@ -1,166 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import os from 'node:os';
4
- import net from 'node:net';
5
- import type { Plugin } from 'vite';
6
- import { createLogger } from 'vite';
7
-
8
- function isPortFree(port: number): Promise<boolean> {
9
- return new Promise((resolve) => {
10
- const s = net.createServer();
11
- s.once('error', () => resolve(false));
12
- s.once('listening', () => {
13
- s.close(() => resolve(true));
14
- });
15
- s.listen(port, '127.0.0.1');
16
- });
17
- }
18
-
19
- async function findFreePort(from: number, to: number): Promise<number> {
20
- for (let p = from; p <= to; p++) {
21
- if (await isPortFree(p)) return p;
22
- }
23
- throw new Error(`Nessuna porta libera tra ${from} e ${to}`);
24
- }
25
-
26
- const cyan = (s: string) => `\x1b[36m${s}\x1b[0m`;
27
- const bold = (s: string) => `\x1b[1m${s}\x1b[0m`;
28
- const dim = (s: string) => `\x1b[2m${s}\x1b[0m`;
29
- const stripAnsi = (s: string) => s.replace(/\x1b\[[0-9;]*m/g, '');
30
- const CONTENT_W = 48;
31
- const BORDER_W = 52;
32
-
33
- function getNetworkUrl(port: number): string | null {
34
- const ifaces = os.networkInterfaces();
35
- for (const list of Object.values(ifaces ?? {})) {
36
- if (!list) continue;
37
- for (const i of list) {
38
- if (i.family === 'IPv4' && !i.internal) return `http://${i.address}:${port}/`;
39
- }
40
- }
41
- return null;
42
- }
43
-
44
- /** Monorepo: alias a path assoluti (Rollup in Docker non segue symlink). Fuori monorepo ritorna {}. */
45
- function resolveAlias(): Record<string, string> {
46
- const root = path.resolve(process.cwd());
47
- const packagesDir = path.join(root, 'packages');
48
- if (!fs.existsSync(packagesDir)) return {};
49
- const alias: Record<string, string> = {};
50
- const clientRuntime = path.join(root, 'packages', 'client', 'runtime');
51
- const jrx = path.join(clientRuntime, 'jsx-runtime.ts');
52
- if (fs.existsSync(jrx)) {
53
- alias['@flow.os/client/jsx-runtime'] = jrx;
54
- alias['@flow.os/client/jsx-dev-runtime'] = path.join(clientRuntime, 'jsx-dev-runtime.ts');
55
- }
56
- for (const name of fs.readdirSync(packagesDir)) {
57
- const dir = path.join(packagesDir, name);
58
- if (!fs.statSync(dir).isDirectory()) continue;
59
- const pkgPath = path.join(dir, 'package.json');
60
- if (!fs.existsSync(pkgPath)) continue;
61
- const abs = path.resolve(dir);
62
- try {
63
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as { name?: string };
64
- if (pkg.name?.startsWith('@flow.os/') || pkg.name === '@flow.os') alias[pkg.name] = abs;
65
- } catch {}
66
- alias[`@flow.os/${name}`] = abs;
67
- }
68
- return alias;
69
- }
70
-
71
- export type FlowConfigOptions = {
72
- /** Porta del dev server. Default: 3000 */
73
- port?: number;
74
- /** Esporre su rete. Default: true */
75
- host?: boolean;
76
- /**
77
- * Backend in dev: passa flowServer() per usare il server Flow (API da server/routes).
78
- * Per Go, Rust, Nitro o altro: non passare server e avvia il backend separatamente;
79
- * opzionalmente aggiungi in plugins un proxy verso la porta del tuo backend.
80
- */
81
- server?: Plugin;
82
- /** Plugin Vite aggiuntivi. Default: [] */
83
- plugins?: Plugin[];
84
- };
85
-
86
- const DEFAULTS = {
87
- port: 3000,
88
- host: true,
89
- server: undefined as Plugin | undefined,
90
- plugins: [] as Plugin[],
91
- };
92
-
93
- function flowServerUrlPlugin(hostEnabled: boolean): Plugin {
94
- return {
95
- name: 'flow:server-url',
96
- configureServer(server) {
97
- (server as { printUrls?: () => void }).printUrls = () => {};
98
- server.httpServer?.once('listening', () => {
99
- const addr = server.httpServer?.address();
100
- if (!addr || typeof addr !== 'object' || !('port' in addr)) return;
101
- const port = (addr as { port: number }).port;
102
- const host = (addr as { address: string }).address;
103
- const localHost = host === '::' || host === '0.0.0.0' ? 'localhost' : host;
104
- const localUrl = `http://${localHost}:${port}/`;
105
- const networkUrl = hostEnabled ? getNetworkUrl(port) : null;
106
-
107
- const line = (content: string) => {
108
- const pad = Math.max(0, CONTENT_W - stripAnsi(content).length);
109
- return dim(' │ ') + content + ' '.repeat(pad) + dim(' │');
110
- };
111
- const border = (c: string) => dim(' ' + c + '─'.repeat(BORDER_W) + (c === '╭' ? '╮' : '╯'));
112
- const out: string[] = [
113
- '',
114
- border('╭'),
115
- line(bold('Flow OS') + dim(' is running')),
116
- line(cyan('◆') + ' ' + dim('Local: ') + cyan(localUrl)),
117
- ...(networkUrl ? [line(dim('Network: ') + cyan(networkUrl))] : []),
118
- border('╰'),
119
- '',
120
- ];
121
- console.log(out.join('\n'));
122
- });
123
- },
124
- };
125
- }
126
-
127
- /** Config per flow.config.ts. Client + Vite; server opzionale con server: flowServer(). */
128
- export default function config(
129
- options: FlowConfigOptions = {}
130
- ): () => Promise<ReturnType<typeof import('vite').defineConfig>> {
131
- const { port: optPort = DEFAULTS.port, host = DEFAULTS.host, server = DEFAULTS.server, plugins = DEFAULTS.plugins } = options;
132
- return async () => {
133
- let port: number;
134
- if (process.env.FLOW_DEV_PORT) {
135
- port = parseInt(process.env.FLOW_DEV_PORT, 10);
136
- } else {
137
- port = await findFreePort(3000, 3020);
138
- }
139
- const { flow } = await import('./vite.js');
140
- const allPlugins = [
141
- flowServerUrlPlugin(host === true),
142
- ...(server ? [server, flow(), ...plugins] : [flow(), ...plugins]),
143
- ];
144
- const alias = resolveAlias();
145
- const baseLogger = createLogger('info');
146
- const customLogger = {
147
- ...baseLogger,
148
- info: (msg: string, opts?: { clear?: boolean }) => {
149
- const t = msg.replace(/\s+/g, ' ');
150
- if (/VITE\s+v?\d|ready\s+in|Local:\s*http|Network:\s*http|press\s+h\s+enter|Port\s+\d+\s+is\s+in\s+use/i.test(t)) return;
151
- baseLogger.info(msg, opts);
152
- },
153
- };
154
- return {
155
- resolve: Object.keys(alias).length ? { alias } : {},
156
- server: { port, host, strictPort: true },
157
- customLogger,
158
- build: {
159
- rollupOptions: {
160
- external: ['@flow.os/server', /^@flow.os\/server\/.+/],
161
- },
162
- },
163
- plugins: allPlugins,
164
- };
165
- };
166
- }
@@ -1,54 +0,0 @@
1
- /// <reference types="node" />
2
- import { writeFileSync } from 'fs';
3
- import { resolve } from 'path';
4
- import type { Plugin } from 'vite';
5
-
6
- const FLOW_ENTRY_ID = '\0flow-entry';
7
- const ENTRY_CODE = `import * as root from '/client/root.tsx';
8
- import { run } from '@flow.os/router';
9
- const opts = {};
10
- if (root.fallback != null) opts.fallback = root.fallback;
11
- if (root.notFound != null) opts.notFound = root.notFound;
12
- run(root.default, import.meta.glob('/client/routes/**/*.tsx'), Object.keys(opts).length ? opts : undefined);
13
- `;
14
-
15
- /** Reset stili browser: niente margin/padding di default, layout full viewport. */
16
- const FLOW_BASE_STYLE = `<style>html,body{margin:0;padding:0;min-height:100vh}#app{min-height:100vh;box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}</style>`;
17
-
18
- const HTML = `<!DOCTYPE html>
19
- <html lang="it">
20
- <head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Flow</title>${FLOW_BASE_STYLE}</head>
21
- <body><div id="app"></div><script type="module" src="/entry.tsx"></script></body>
22
- </html>`;
23
-
24
- export function flow(): Plugin {
25
- const cwd = process.cwd();
26
- return {
27
- name: 'flow',
28
- config() {
29
- return {
30
- root: resolve(cwd),
31
- base: '/',
32
- esbuild: { jsx: 'automatic', jsxImportSource: '@flow.os/client' },
33
- resolve: { alias: { '~': resolve(cwd, 'client') } },
34
- build: { target: 'esnext', minify: 'esbuild', sourcemap: true },
35
- };
36
- },
37
- configResolved(_config) {
38
- writeFileSync(resolve(cwd, 'index.html'), HTML);
39
- },
40
- resolveId(id) {
41
- return id === '/entry.tsx' ? FLOW_ENTRY_ID : null;
42
- },
43
- load(id) {
44
- return id === FLOW_ENTRY_ID ? ENTRY_CODE : null;
45
- },
46
- buildEnd(err) {
47
- if (err) {
48
- const msg = err.message ?? String(err);
49
- const stack = err.stack ?? (err as Error).cause?.toString?.();
50
- console.error('[flow] build error:', msg, stack ?? '');
51
- }
52
- },
53
- };
54
- }
@@ -1,32 +0,0 @@
1
- import { effect } from '@flow.os/core';
2
- import { isGetter } from './utils.js';
3
-
4
- /** Props gestite altrove (non passare qui). */
5
- const SKIP = new Set(['children', 'class', 'className', 'classList', 'classFlow', 'style', 'styleFlow']);
6
-
7
- export function applyAttrs(el: HTMLElement, rest: Record<string, unknown>): void {
8
- for (const [k, v] of Object.entries(rest)) {
9
- if (v == null || SKIP.has(k)) continue;
10
- if (k.startsWith('on') && typeof v === 'function') {
11
- el.addEventListener(k.slice(2).toLowerCase(), v as EventListener);
12
- continue;
13
- }
14
- if (isGetter(v)) {
15
- effect(() => {
16
- const x = (v as () => unknown)();
17
- if (typeof x === 'boolean') {
18
- if (x) el.setAttribute(k, '');
19
- else el.removeAttribute(k);
20
- } else {
21
- el.setAttribute(k, String(x));
22
- }
23
- });
24
- continue;
25
- }
26
- if (typeof v === 'boolean') {
27
- if (v) el.setAttribute(k, '');
28
- continue;
29
- }
30
- if (typeof v === 'string' || typeof v === 'number') el.setAttribute(k, String(v));
31
- }
32
- }
@@ -1,116 +0,0 @@
1
- import { effect } from '@flow.os/core';
2
- import { isGetter } from './utils.js';
3
-
4
- export function toStyleValue(v: unknown): string {
5
- return typeof v === 'number' ? `${v}px` : String(v ?? '');
6
- }
7
-
8
- export function setStyleProp(el: HTMLElement, key: string, value: string): void {
9
- if (key.startsWith('--')) el.style.setProperty(key, value);
10
- else (el.style as unknown as Record<string, string>)[key] = value;
11
- }
12
-
13
- const CLASS_FLOW_MAP: Record<string, string> = {
14
- text: 'fontSize',
15
- mb: 'marginBottom',
16
- mt: 'marginTop',
17
- ml: 'marginLeft',
18
- mr: 'marginRight',
19
- mx: 'marginLeft',
20
- my: 'marginTop',
21
- m: 'margin',
22
- pb: 'paddingBottom',
23
- pt: 'paddingTop',
24
- pl: 'paddingLeft',
25
- pr: 'paddingRight',
26
- px: 'paddingLeft',
27
- py: 'paddingTop',
28
- p: 'padding',
29
- w: 'width',
30
- h: 'height',
31
- minW: 'minWidth',
32
- minH: 'minHeight',
33
- maxW: 'maxWidth',
34
- maxH: 'maxHeight',
35
- gap: 'gap',
36
- rounded: 'borderRadius',
37
- top: 'top',
38
- left: 'left',
39
- right: 'right',
40
- bottom: 'bottom',
41
- };
42
-
43
- function resolveClassFlowKey(k: string): string {
44
- if (k.startsWith('--')) return k;
45
- return CLASS_FLOW_MAP[k] ?? k;
46
- }
47
-
48
- function isClassFlowReactive(val: unknown): boolean {
49
- return isGetter(val) || (Array.isArray(val) && val.length === 2 && isGetter(val[0]));
50
- }
51
-
52
- function resolveClassFlowValue(val: unknown): string {
53
- if (isGetter(val)) return toStyleValue((val as () => unknown)());
54
- if (Array.isArray(val) && val.length === 2 && isGetter(val[0]))
55
- return String((val[0] as () => unknown)()) + String(val[1]);
56
- return toStyleValue(val);
57
- }
58
-
59
- function applyClassFlowObj(el: HTMLElement, obj: Record<string, unknown>): void {
60
- for (const [k, val] of Object.entries(obj))
61
- setStyleProp(el, resolveClassFlowKey(k), resolveClassFlowValue(val));
62
- }
63
-
64
- export function applyClassFlow(el: HTMLElement, classFlowVal: unknown): void {
65
- if (classFlowVal == null) return;
66
- if (isGetter(classFlowVal)) {
67
- effect(() => applyClassFlowObj(el, (classFlowVal as () => Record<string, unknown>)()));
68
- return;
69
- }
70
- if (typeof classFlowVal !== 'object' || Array.isArray(classFlowVal) || classFlowVal instanceof Node) return;
71
- const obj = classFlowVal as Record<string, unknown>;
72
- const hasReactive = Object.values(obj).some(isClassFlowReactive);
73
- if (hasReactive) {
74
- effect(() => {
75
- for (const [k, val] of Object.entries(obj))
76
- setStyleProp(el, resolveClassFlowKey(k), resolveClassFlowValue(val));
77
- });
78
- } else {
79
- applyClassFlowObj(el, obj);
80
- }
81
- }
82
-
83
- export function applyClassAndClassList(
84
- el: HTMLElement,
85
- classVal: unknown,
86
- classNameVal: unknown,
87
- classListVal: unknown
88
- ): void {
89
- const base = classVal ?? classNameVal;
90
- if (base == null && (classListVal == null || typeof classListVal !== 'object')) return;
91
- effect(() => {
92
- let baseStr = '';
93
- if (base != null) {
94
- if (Array.isArray(base)) {
95
- baseStr = base
96
- .map((item) => (isGetter(item) ? String((item as () => unknown)()) : String(item)))
97
- .filter(Boolean)
98
- .join(' ');
99
- } else if (isGetter(base)) {
100
- baseStr = String((base as () => unknown)());
101
- } else {
102
- baseStr = String(base);
103
- }
104
- }
105
- const list = classListVal as Record<string, boolean | (() => boolean)> | undefined;
106
- const truthy: string[] = [];
107
- if (list && typeof list === 'object' && !(list instanceof Node)) {
108
- for (const [cls, val] of Object.entries(list)) {
109
- const v = isGetter(val) ? (val as () => boolean)() : val;
110
- if (v) truthy.push(cls);
111
- }
112
- }
113
- const full = [baseStr, ...truthy].filter(Boolean).join(' ');
114
- el.setAttribute('class', full);
115
- });
116
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * Feature applicate a div, p, button, ecc.
3
- * Un file per feature; qui si raggruppano e si espongono a jsx.
4
- */
5
- export { applyClassFlow, applyClassAndClassList } from './class-flow.js';
6
- export { applyStyle } from './style.js';
7
- export { applyStyleFlow } from './style-flow.js';
8
- export { applyAttrs } from './attrs.js';
@@ -1,40 +0,0 @@
1
- import { styleToCssText } from '@flow.os/style';
2
- import type { PseudoKey } from '@flow.os/style';
3
-
4
- const PSEUDO_SELECTOR: Record<PseudoKey, string> = {
5
- hover: ':hover',
6
- active: ':active',
7
- focus: ':focus',
8
- focusVisible: ':focus-visible',
9
- };
10
-
11
- let styleEl: HTMLStyleElement | null = null;
12
- const cache = new Map<string, string>();
13
- let id = 0;
14
-
15
- function ensureStyleEl(): HTMLStyleElement {
16
- if (styleEl) return styleEl;
17
- styleEl = document.createElement('style');
18
- styleEl.setAttribute('data-flow-style', '');
19
- document.head.appendChild(styleEl);
20
- return styleEl;
21
- }
22
-
23
- /** Restituisce className da aggiungere all'elemento. La regola .sf-{pseudo}-{id}:{pseudo} { ... } è iniettata una sola volta. */
24
- export function getPseudoClass(
25
- pseudo: PseudoKey,
26
- style: Record<string, string>
27
- ): string {
28
- const cssText = styleToCssText(style);
29
- if (!cssText) return '';
30
- const key = `${pseudo}:${cssText}`;
31
- let className = cache.get(key);
32
- if (className) return className;
33
- className = `sf-${pseudo}-${++id}`;
34
- cache.set(key, className);
35
- const selector = `.${className}${PSEUDO_SELECTOR[pseudo]}`;
36
- const rule = `${selector} { ${cssText} }`;
37
- const el = ensureStyleEl();
38
- el.appendChild(document.createTextNode(rule));
39
- return className;
40
- }
@@ -1,106 +0,0 @@
1
- import { effect } from '@flow.os/core';
2
- import { isGetter } from './utils.js';
3
- import {
4
- VIEWPORT_KEYS,
5
- PSEUDO_KEYS,
6
- resolveLayer,
7
- resolvePseudoStyle,
8
- type PlainLayer,
9
- type ViewportKey,
10
- type PseudoKey,
11
- } from '@flow.os/style';
12
- import { getViewportBreakpoint } from './viewport.js';
13
- import { getPseudoClass } from './pseudo-injector.js';
14
-
15
- const RESERVED = new Set<string>([...VIEWPORT_KEYS, ...PSEUDO_KEYS]);
16
-
17
- /** Chiama getter e restituisce oggetto plain (una livello, escluse chiavi reserved). */
18
- function gatherPlain(obj: Record<string, unknown> | null | undefined): PlainLayer {
19
- const out: PlainLayer = {};
20
- if (!obj || typeof obj !== 'object' || Array.isArray(obj)) return out;
21
- for (const [k, v] of Object.entries(obj)) {
22
- if (RESERVED.has(k)) continue;
23
- if (v === undefined || v === null) continue;
24
- if (isGetter(v)) {
25
- const x = (v as () => unknown)();
26
- if (typeof x === 'boolean') out[k] = x;
27
- else if (typeof x === 'number' || typeof x === 'string') out[k] = x;
28
- else if (Array.isArray(x) && x.length === 2 && isGetter(x[0]))
29
- out[k] = String((x[0] as () => unknown)()) + String(x[1]);
30
- else out[k] = String(x);
31
- } else if (typeof v === 'object' && v !== null && !(v instanceof Node)) {
32
- if (k === 'base') out['base'] = (v as Record<string, string>)['base'] ?? String(v);
33
- // nested layer (mob/tab/des/hover/...) già esclusi da RESERVED
34
- } else {
35
- out[k] = v as string | number | boolean;
36
- }
37
- }
38
- return out;
39
- }
40
-
41
- /** Normalizza value in base string + flat object. */
42
- function normalize(
43
- value: unknown
44
- ): { base: string; flat: Record<string, unknown> } {
45
- if (value == null) return { base: '', flat: {} };
46
- if (typeof value === 'string') return { base: value, flat: {} };
47
- if (Array.isArray(value)) {
48
- const base = typeof value[0] === 'string' ? value[0] : '';
49
- const flat = (value[1] && typeof value[1] === 'object' && !Array.isArray(value[1]))
50
- ? (value[1] as Record<string, unknown>)
51
- : {};
52
- return { base, flat };
53
- }
54
- if (typeof value === 'object' && !Array.isArray(value) && !(value instanceof Node)) {
55
- const flat = value as Record<string, unknown>;
56
- const base = typeof flat['base'] === 'string' ? flat['base'] : '';
57
- return { base, flat };
58
- }
59
- return { base: '', flat: {} };
60
- }
61
-
62
- export function applyStyleFlow(el: HTMLElement, value: unknown): void {
63
- if (value == null) return;
64
- const { base, flat } = normalize(value);
65
- let prevStyleKeys: string[] = [];
66
-
67
- effect(() => {
68
- const viewport: ViewportKey = getViewportBreakpoint();
69
- const plainBase = gatherPlain(flat);
70
- if (base) plainBase.base = (plainBase.base ? `${plainBase.base} ` : '') + base;
71
- const viewportLayer = flat[viewport];
72
- const plainViewport = gatherPlain(
73
- viewportLayer && typeof viewportLayer === 'object' && !Array.isArray(viewportLayer)
74
- ? (viewportLayer as Record<string, unknown>)
75
- : {}
76
- );
77
- const merged: PlainLayer = { ...plainBase };
78
- if (plainViewport.base) merged.base = (merged.base ? `${merged.base} ` : '') + plainViewport.base;
79
- for (const [k, v] of Object.entries(plainViewport)) {
80
- if (k === 'base') continue;
81
- (merged as Record<string, unknown>)[k] = v;
82
- }
83
- const resolved = resolveLayer(merged);
84
-
85
- const pseudoClasses: string[] = [];
86
- for (const pseudo of PSEUDO_KEYS) {
87
- const rawPseudo = flat[pseudo];
88
- const plainPseudo = gatherPlain(
89
- rawPseudo && typeof rawPseudo === 'object' && !Array.isArray(rawPseudo)
90
- ? (rawPseudo as Record<string, unknown>)
91
- : {}
92
- );
93
- const stylePseudo = resolvePseudoStyle(plainPseudo);
94
- const cls = getPseudoClass(pseudo as PseudoKey, stylePseudo);
95
- if (cls) pseudoClasses.push(cls);
96
- }
97
-
98
- el.className = [resolved.class, ...pseudoClasses].filter(Boolean).join(' ');
99
- for (const k of prevStyleKeys) el.style.removeProperty(k);
100
- prevStyleKeys = Object.keys(resolved.style);
101
- for (const [k, v] of Object.entries(resolved.style)) {
102
- if (k.startsWith('--')) el.style.setProperty(k, v);
103
- else (el.style as unknown as Record<string, string>)[k] = v;
104
- }
105
- });
106
- }
@@ -1,27 +0,0 @@
1
- import { effect } from '@flow.os/core';
2
- import { isGetter } from './utils.js';
3
- import { setStyleProp, toStyleValue } from './class-flow.js';
4
-
5
- export function applyStyle(el: HTMLElement, styleVal: unknown): void {
6
- if (styleVal == null) return;
7
- if (isGetter(styleVal)) {
8
- effect(() => {
9
- const style = (styleVal as () => Record<string, string> | string)();
10
- if (typeof style === 'string') {
11
- el.setAttribute('style', style);
12
- } else if (style && typeof style === 'object') {
13
- for (const [sk, sv] of Object.entries(style)) setStyleProp(el, sk, toStyleValue(sv));
14
- }
15
- });
16
- return;
17
- }
18
- if (typeof styleVal !== 'object' || styleVal === null || styleVal instanceof Node) return;
19
- const style = styleVal as Record<string, string | number | (() => string | number)>;
20
- for (const [sk, sv] of Object.entries(style)) {
21
- if (isGetter(sv)) {
22
- effect(() => setStyleProp(el, sk, toStyleValue((sv as () => unknown)())));
23
- } else {
24
- setStyleProp(el, sk, toStyleValue(sv));
25
- }
26
- }
27
- }
@@ -1,4 +0,0 @@
1
- /** Getter reattivo (funzione senza argomenti). */
2
- export function isGetter(fn: unknown): fn is () => unknown {
3
- return typeof fn === 'function' && fn.length === 0;
4
- }
@@ -1,20 +0,0 @@
1
- import { state } from '@flow.os/core';
2
- import type { ViewportKey } from '@flow.os/style';
3
- import { getViewportKeyFromWidth } from '@flow.os/style';
4
-
5
- const [getViewport, setViewport] = state<ViewportKey>('mob');
6
- let subscribed = false;
7
-
8
- function subscribe(): void {
9
- if (subscribed) return;
10
- subscribed = true;
11
- const update = () => setViewport(getViewportKeyFromWidth(window.innerWidth));
12
- update();
13
- window.addEventListener('resize', update);
14
- }
15
-
16
- /** Breakpoint viewport reattivo (mob/tab/des). Una sola subscription condivisa. */
17
- export function getViewportBreakpoint(): ViewportKey {
18
- subscribe();
19
- return getViewport();
20
- }
@@ -1,6 +0,0 @@
1
- /// <reference path="./runtime/jsx-types.d.ts" />
2
- // API pubblica: tutto da qui o da subpath (./config, ./vite, ./jsx-runtime, ./jsx-dev-runtime)
3
- export { Fragment, jsx, jsxs, jsxDEV } from './runtime/jsx.js';
4
- export { normalizeChild, setContent } from './runtime/dom.js';
5
- export { default as config } from './build/config.js';
6
- export { applyClassFlow, applyClassAndClassList, applyStyle, applyStyleFlow, applyAttrs } from './features/index.js';
@@ -1,48 +0,0 @@
1
- {
2
- "name": "@flow.os/client",
3
- "version": "0.0.5",
4
- "license": "PolyForm-Shield-1.0.0",
5
- "type": "module",
6
- "main": "./index.ts",
7
- "types": "./index.ts",
8
- "bin": {
9
- "flow-os-dev": "./scripts/start-dev.ts",
10
- "flow-os-build": "./scripts/build.ts",
11
- "flow-os-preview": "./scripts/preview.ts"
12
- },
13
- "dependencies": {
14
- "@flow.os/core": "workspace:*",
15
- "@flow.os/router": "workspace:*",
16
- "@flow.os/style": "workspace:*"
17
- },
18
- "peerDependencies": {
19
- "vite": ">=5.0.0"
20
- },
21
- "exports": {
22
- ".": {
23
- "types": "./index.ts",
24
- "import": "./index.ts",
25
- "default": "./index.ts"
26
- },
27
- "./config": {
28
- "types": "./build/config.ts",
29
- "import": "./build/config.ts",
30
- "default": "./build/config.ts"
31
- },
32
- "./vite": {
33
- "types": "./build/vite.ts",
34
- "import": "./build/vite.ts",
35
- "default": "./build/vite.ts"
36
- },
37
- "./jsx-runtime": {
38
- "types": "./runtime/jsx.ts",
39
- "import": "./runtime/jsx.ts",
40
- "default": "./runtime/jsx.ts"
41
- },
42
- "./jsx-dev-runtime": {
43
- "types": "./runtime/jsx.ts",
44
- "import": "./runtime/jsx.ts",
45
- "default": "./runtime/jsx.ts"
46
- }
47
- }
48
- }
@@ -1,2 +0,0 @@
1
- /** Re-export DOM helpers da @flow.os/core. */
2
- export { normalizeChild, setContent } from '@flow.os/core';
@@ -1 +0,0 @@
1
- export * from './jsx.js';
@@ -1 +0,0 @@
1
- export * from './jsx.js';