@llmnative/react 1.1.0 → 1.2.1

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 (40) hide show
  1. package/README.md +1 -1
  2. package/dist/index.css +3 -1
  3. package/dist/index.js +20 -23
  4. package/dist/index.mjs +18040 -17552
  5. package/dist/types/src/I18n.d.ts +3 -0
  6. package/dist/types/src/components/ErrorBoundary.d.ts +1 -1
  7. package/dist/types/src/components/blocks/Dropdown.d.ts +27 -2
  8. package/dist/types/src/components/ui/Alert.d.ts +1 -1
  9. package/dist/types/src/components/ui/Gallery.d.ts +6 -0
  10. package/dist/types/src/components/ui/Loader.d.ts +1 -1
  11. package/dist/types/src/components/ui/Modal.d.ts +18 -0
  12. package/dist/types/src/components/ui/Tab.d.ts +1 -1
  13. package/dist/types/src/components/ui/fields/CodeEditor.d.ts +6 -1
  14. package/dist/types/src/components/ui/fields/ContextMenu.d.ts +24 -0
  15. package/dist/types/src/components/ui/fields/Upload.d.ts +1 -1
  16. package/dist/types/src/components/widgets/Form.d.ts +14 -3
  17. package/dist/types/src/components/widgets/grid-core/GridCore.d.ts +1 -1
  18. package/dist/types/src/components/widgets/grid-core/GridGalleryView.d.ts +1 -1
  19. package/dist/types/src/components/widgets/grid-core/types.d.ts +79 -3
  20. package/dist/types/src/components/widgets/grid-core/useGridActions.d.ts +1 -1
  21. package/dist/types/src/index.d.ts +2 -2
  22. package/dist/types/src/libs/editorHeight.d.ts +11 -1
  23. package/dist/types/src/libs/fetch.d.ts +2 -0
  24. package/dist/types/src/providers/ai/AIProvider.d.ts +54 -1
  25. package/dist/types/src/providers/ai/index.d.ts +1 -1
  26. package/dist/types/src/providers/ai/openaiCompatible.d.ts +22 -0
  27. package/dist/types/src/providers/ai/shared.d.ts +3 -3
  28. package/dist/types/src/providers/auth/google/auth.d.ts +1 -1
  29. package/dist/types/src/providers/data/DataProvider.d.ts +8 -0
  30. package/dist/types/src/providers/data/firestore.d.ts +11 -0
  31. package/dist/vite.js +1 -1
  32. package/dist/vite.mjs +62 -53
  33. package/package.json +51 -53
  34. package/scripts/cli/setup-devtools.js +8 -7
  35. package/scripts/cli/setup-project.js +23 -19
  36. package/themes/cyber.ts +8 -7
  37. package/themes/default.ts +22 -7
  38. package/themes/flat.ts +8 -7
  39. package/dist/style.css +0 -1
  40. package/dist/types/src/providers/email/google/apis/email.d.ts +0 -7
@@ -80,5 +80,13 @@ export interface DataProviderAdapter extends ProviderConfigurable {
80
80
  readShallow?(path: string, exception?: boolean): Promise<string[]>;
81
81
  /** Write `data` to `path` in batches (useful for large imports). */
82
82
  setChunks?(path: string, data: object, options?: SetChunksOptions): Promise<void>;
83
+ /**
84
+ * Releases this adapter's underlying connection/resources. Not all providers need one
85
+ * (e.g. a stateless REST-backed adapter has nothing to release) — implement it when the
86
+ * provider holds a long-lived client/channel that should stop retrying once a caller has
87
+ * given up on it (see FirestoreDataProvider, where a nonexistent named database otherwise
88
+ * keeps reconnecting with backoff forever at the SDK level).
89
+ */
90
+ dispose?(): Promise<void>;
83
91
  }
84
92
  export {};
@@ -10,6 +10,17 @@ export declare class FirestoreDataProvider implements DataProviderAdapter {
10
10
  constructor(config?: FirestoreDataProviderConfig);
11
11
  /** Same "(default)" database as before when no databaseId was configured. */
12
12
  private getDb;
13
+ /**
14
+ * Stops this instance's underlying network channel — call this once a caller has given up
15
+ * on this specific databaseId (e.g. after a timeout on a database that doesn't exist).
16
+ * `getFirestore(app, databaseId)` is a cached singleton per (app, databaseId); left alone,
17
+ * a client that can't connect keeps retrying with backoff FOREVER at the SDK level, fully
18
+ * independent of any one `read()`/`subscribe()` call already having given up on its own
19
+ * promise — this is what actually silences that. Safe to call even if never connected
20
+ * (Firestore no-ops); the cache entry is removed afterwards, so a later `new
21
+ * FirestoreDataProvider({databaseId})` for the same id gets a fresh client, not a dead one.
22
+ */
23
+ dispose: () => Promise<void>;
13
24
  getConfigurationState(): ProviderConfigurationState;
14
25
  isConfigured(): boolean;
15
26
  read: (path: string, { where, order, toArray, exception }?: ReadOptions) => Promise<any>;
package/dist/vite.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u="x-llmnative-proxy",p="/api/proxy",h=async t=>{const e=[];for await(const r of t)e.push(Buffer.isBuffer(r)?r:Buffer.from(r));return e.length===0?void 0:Buffer.concat(e)},l=async(t,e,r)=>{const a=new URL(t.url||"/","http://localhost").searchParams.get("url");if(t.headers[u]!=="1"){e.statusCode=403,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify({error:"Proxy access denied."}));return}if(!a){e.statusCode=400,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify({error:'Missing "url" query parameter.'}));return}try{const o=new URL(a);if(o.pathname.startsWith(r)&&["localhost","127.0.0.1"].includes(o.hostname)){e.statusCode=508,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify({error:"Recursive proxy target detected.",target:a}));return}const d=await h(t),f=new Headers,y=new Set([u,"host","origin","referer","content-length","transfer-encoding","connection"]);Object.entries(t.headers).forEach(([i,n])=>{!n||y.has(i.toLowerCase())||f.set(i,Array.isArray(n)?n.join(", "):n)});const c=await fetch(a,{method:t.method||"GET",headers:f,body:d&&!["GET","HEAD"].includes((t.method||"GET").toUpperCase())?d:void 0,redirect:"follow"});e.statusCode=c.status,c.headers.forEach((i,n)=>{n.toLowerCase()!=="content-encoding"&&e.setHeader(n,i)}),e.end(Buffer.from(await c.arrayBuffer()))}catch(o){e.statusCode=502,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify({error:o instanceof Error?o.message:"Proxy request failed."}))}},g=(t=p)=>({name:"llmnative-dev-proxy",configureServer(e){e.middlewares.use(t,(r,s)=>{l(r,s,t)})},configurePreviewServer(e){e.middlewares.use(t,(r,s)=>{l(r,s,t)})}});exports.PROXY_PATH=p;exports.createProxyPlugin=g;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=`x-llmnative-proxy`,t=`/api/proxy`,n=async e=>{let t=[];for await(let n of e)t.push(Buffer.isBuffer(n)?n:Buffer.from(n));return t.length===0?void 0:Buffer.concat(t)},r=async(t,r,i)=>{let a=new URL(t.url||`/`,`http://localhost`).searchParams.get(`url`);if(t.headers[e]!==`1`){r.statusCode=403,r.setHeader(`Content-Type`,`application/json`),r.end(JSON.stringify({error:`Proxy access denied.`}));return}if(!a){r.statusCode=400,r.setHeader(`Content-Type`,`application/json`),r.end(JSON.stringify({error:`Missing "url" query parameter.`}));return}try{let o=new URL(a);if(o.pathname.startsWith(i)&&[`localhost`,`127.0.0.1`].includes(o.hostname)){r.statusCode=508,r.setHeader(`Content-Type`,`application/json`),r.end(JSON.stringify({error:`Recursive proxy target detected.`,target:a}));return}let s=await n(t),c=new Headers,l=new Set([e,`host`,`origin`,`referer`,`content-length`,`transfer-encoding`,`connection`]);Object.entries(t.headers).forEach(([e,t])=>{!t||l.has(e.toLowerCase())||c.set(e,Array.isArray(t)?t.join(`, `):t)});let u=await fetch(a,{method:t.method||`GET`,headers:c,body:s&&![`GET`,`HEAD`].includes((t.method||`GET`).toUpperCase())?Uint8Array.from(s):void 0,redirect:`follow`});r.statusCode=u.status,u.headers.forEach((e,t)=>{t.toLowerCase()!==`content-encoding`&&r.setHeader(t,e)}),r.end(Buffer.from(await u.arrayBuffer()))}catch(e){r.statusCode=502,r.setHeader(`Content-Type`,`application/json`),r.end(JSON.stringify({error:e instanceof Error?e.message:`Proxy request failed.`}))}},i=(e=t)=>({name:`llmnative-dev-proxy`,configureServer(t){t.middlewares.use(e,(t,n)=>{r(t,n,e)})},configurePreviewServer(t){t.middlewares.use(e,(t,n)=>{r(t,n,e)})}});exports.PROXY_PATH=t,exports.createProxyPlugin=i;
package/dist/vite.mjs CHANGED
@@ -1,54 +1,63 @@
1
- const u = "x-llmnative-proxy", l = "/api/proxy", y = async (t) => {
2
- const e = [];
3
- for await (const r of t)
4
- e.push(Buffer.isBuffer(r) ? r : Buffer.from(r));
5
- return e.length === 0 ? void 0 : Buffer.concat(e);
6
- }, p = async (t, e, r) => {
7
- const a = new URL(t.url || "/", "http://localhost").searchParams.get("url");
8
- if (t.headers[u] !== "1") {
9
- e.statusCode = 403, e.setHeader("Content-Type", "application/json"), e.end(JSON.stringify({ error: "Proxy access denied." }));
10
- return;
11
- }
12
- if (!a) {
13
- e.statusCode = 400, e.setHeader("Content-Type", "application/json"), e.end(JSON.stringify({ error: 'Missing "url" query parameter.' }));
14
- return;
15
- }
16
- try {
17
- const o = new URL(a);
18
- if (o.pathname.startsWith(r) && ["localhost", "127.0.0.1"].includes(o.hostname)) {
19
- e.statusCode = 508, e.setHeader("Content-Type", "application/json"), e.end(JSON.stringify({ error: "Recursive proxy target detected.", target: a }));
20
- return;
21
- }
22
- const d = await y(t), f = new Headers(), h = /* @__PURE__ */ new Set([u, "host", "origin", "referer", "content-length", "transfer-encoding", "connection"]);
23
- Object.entries(t.headers).forEach(([i, n]) => {
24
- !n || h.has(i.toLowerCase()) || f.set(i, Array.isArray(n) ? n.join(", ") : n);
25
- });
26
- const c = await fetch(a, {
27
- method: t.method || "GET",
28
- headers: f,
29
- body: d && !["GET", "HEAD"].includes((t.method || "GET").toUpperCase()) ? d : void 0,
30
- redirect: "follow"
31
- });
32
- e.statusCode = c.status, c.headers.forEach((i, n) => {
33
- n.toLowerCase() !== "content-encoding" && e.setHeader(n, i);
34
- }), e.end(Buffer.from(await c.arrayBuffer()));
35
- } catch (o) {
36
- e.statusCode = 502, e.setHeader("Content-Type", "application/json"), e.end(JSON.stringify({ error: o instanceof Error ? o.message : "Proxy request failed." }));
37
- }
38
- }, g = (t = l) => ({
39
- name: "llmnative-dev-proxy",
40
- configureServer(e) {
41
- e.middlewares.use(t, (r, s) => {
42
- p(r, s, t);
43
- });
44
- },
45
- configurePreviewServer(e) {
46
- e.middlewares.use(t, (r, s) => {
47
- p(r, s, t);
48
- });
49
- }
1
+ //#region src/providers/proxy/vite.ts
2
+ var e = "x-llmnative-proxy", t = "/api/proxy", n = async (e) => {
3
+ let t = [];
4
+ for await (let n of e) t.push(Buffer.isBuffer(n) ? n : Buffer.from(n));
5
+ return t.length === 0 ? void 0 : Buffer.concat(t);
6
+ }, r = async (t, r, i) => {
7
+ let a = new URL(t.url || "/", "http://localhost").searchParams.get("url");
8
+ if (t.headers[e] !== "1") {
9
+ r.statusCode = 403, r.setHeader("Content-Type", "application/json"), r.end(JSON.stringify({ error: "Proxy access denied." }));
10
+ return;
11
+ }
12
+ if (!a) {
13
+ r.statusCode = 400, r.setHeader("Content-Type", "application/json"), r.end(JSON.stringify({ error: "Missing \"url\" query parameter." }));
14
+ return;
15
+ }
16
+ try {
17
+ let o = new URL(a);
18
+ if (o.pathname.startsWith(i) && ["localhost", "127.0.0.1"].includes(o.hostname)) {
19
+ r.statusCode = 508, r.setHeader("Content-Type", "application/json"), r.end(JSON.stringify({
20
+ error: "Recursive proxy target detected.",
21
+ target: a
22
+ }));
23
+ return;
24
+ }
25
+ let s = await n(t), c = new Headers(), l = /* @__PURE__ */ new Set([
26
+ e,
27
+ "host",
28
+ "origin",
29
+ "referer",
30
+ "content-length",
31
+ "transfer-encoding",
32
+ "connection"
33
+ ]);
34
+ Object.entries(t.headers).forEach(([e, t]) => {
35
+ !t || l.has(e.toLowerCase()) || c.set(e, Array.isArray(t) ? t.join(", ") : t);
36
+ });
37
+ let u = await fetch(a, {
38
+ method: t.method || "GET",
39
+ headers: c,
40
+ body: s && !["GET", "HEAD"].includes((t.method || "GET").toUpperCase()) ? Uint8Array.from(s) : void 0,
41
+ redirect: "follow"
42
+ });
43
+ r.statusCode = u.status, u.headers.forEach((e, t) => {
44
+ t.toLowerCase() !== "content-encoding" && r.setHeader(t, e);
45
+ }), r.end(Buffer.from(await u.arrayBuffer()));
46
+ } catch (e) {
47
+ r.statusCode = 502, r.setHeader("Content-Type", "application/json"), r.end(JSON.stringify({ error: e instanceof Error ? e.message : "Proxy request failed." }));
48
+ }
49
+ }, i = (e = t) => ({
50
+ name: "llmnative-dev-proxy",
51
+ configureServer(t) {
52
+ t.middlewares.use(e, (t, n) => {
53
+ r(t, n, e);
54
+ });
55
+ },
56
+ configurePreviewServer(t) {
57
+ t.middlewares.use(e, (t, n) => {
58
+ r(t, n, e);
59
+ });
60
+ }
50
61
  });
51
- export {
52
- l as PROXY_PATH,
53
- g as createProxyPlugin
54
- };
62
+ //#endregion
63
+ export { t as PROXY_PATH, i as createProxyPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llmnative/react",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "LLM-native React framework for deterministic UI generation. Data-driven by default, schema-driven optional. Ultra-low token consumption — built for AI agents, not just humans.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -30,7 +30,8 @@
30
30
  "test:e2e:proxy-runtime": "vitest run tests/e2e/proxy-runtime.test.ts --environment node",
31
31
  "test:integration": "npx firebase emulators:exec --only database,firestore,storage --project demo-test \"npx vitest run --config vitest.integration.config.mts\"",
32
32
  "test:watch": "vitest",
33
- "test:coverage": "vitest run --coverage"
33
+ "test:coverage": "vitest run --coverage",
34
+ "release:check": "node scripts/release/check-release.mjs"
34
35
  },
35
36
  "bin": {
36
37
  "llmnative": "bin/cli.js"
@@ -65,18 +66,22 @@
65
66
  ],
66
67
  "author": "wolfgan",
67
68
  "license": "Apache-2.0",
69
+ "engines": {
70
+ "node": ">=24.18.0 <25"
71
+ },
72
+ "packageManager": "npm@11.11.0",
68
73
  "bugs": {
69
74
  "url": "https://github.com/sherpadvisorylab/llmnative-react/issues"
70
75
  },
71
76
  "homepage": "https://github.com/sherpadvisorylab/llmnative-react#readme",
72
77
  "peerDependencies": {
73
- "@phosphor-icons/react": "^2.0.0",
74
- "@supabase/supabase-js": "^2.107.0",
75
- "firebase": "^10.14.0",
76
- "lucide-react": "^0.400.0",
77
- "react": "^19.0.0",
78
- "react-dom": "^19.0.0",
79
- "react-router-dom": "^6.30.0"
78
+ "@phosphor-icons/react": "^2.1.0",
79
+ "@supabase/supabase-js": "^2.110.0",
80
+ "firebase": "^12.16.0",
81
+ "lucide-react": "^1.26.0",
82
+ "react": "^19.2.0",
83
+ "react-dom": "^19.2.0",
84
+ "react-router-dom": "^7.18.1"
80
85
  },
81
86
  "peerDependenciesMeta": {
82
87
  "@phosphor-icons/react": {
@@ -87,75 +92,68 @@
87
92
  }
88
93
  },
89
94
  "devDependencies": {
90
- "@babel/core": "^7.25.7",
91
- "@babel/plugin-proposal-class-properties": "^7.18.6",
92
- "@babel/plugin-proposal-object-rest-spread": "^7.20.7",
93
- "@babel/preset-env": "^7.25.7",
94
- "@babel/preset-react": "^7.25.7",
95
- "@babel/preset-typescript": "^7.25.7",
96
95
  "@firebase/rules-unit-testing": "^5.0.1",
97
96
  "@phosphor-icons/react": "^2.1.10",
98
- "@playwright/test": "^1.61.1",
99
- "@supabase/supabase-js": "^2.107.0",
100
- "@tailwindcss/postcss": "^4.2.4",
97
+ "@playwright/test": "^1.62.0",
98
+ "@supabase/supabase-js": "^2.110.8",
99
+ "@tailwindcss/postcss": "^4.3.3",
101
100
  "@testing-library/dom": "^10.4.1",
102
- "@testing-library/jest-dom": "^6.9.1",
101
+ "@testing-library/jest-dom": "^7.0.0",
103
102
  "@testing-library/react": "^16.3.2",
104
103
  "@testing-library/user-event": "^14.6.1",
105
- "@types/papaparse": "^5.3.16",
106
- "@types/prismjs": "^1.26.5",
107
- "@types/react": "^18.2.0",
108
- "@types/react-dom": "^18.2.0",
109
- "@vitest/coverage-v8": "2.1",
110
- "autoprefixer": "^10.5.0",
111
- "firebase": "^12.0.0",
112
- "googleapis": "^171.4.0",
113
- "happy-dom": "^20.9.0",
104
+ "@types/papaparse": "^5.5.2",
105
+ "@types/prismjs": "^1.26.6",
106
+ "@types/react": "^19.2.17",
107
+ "@types/react-dom": "^19.2.3",
108
+ "@vitest/coverage-v8": "4.1",
109
+ "autoprefixer": "^10.5.4",
110
+ "firebase": "^12.16.0",
111
+ "happy-dom": "^20.11.1",
114
112
  "jsdom": "^29.1.1",
115
- "lucide-react": "^1.14.0",
116
- "postcss": "^8.5.14",
117
- "react": "^19.2.5",
118
- "react-dom": "^19.2.5",
119
- "react-router-dom": "^6.30.3",
120
- "tailwindcss": "^4.2.4",
121
- "typescript": "^5.6.2",
122
- "vite": "^5.4.21",
123
- "vitest": "2.1",
124
- "ws": "^8.21.0"
113
+ "lucide-react": "^1.26.0",
114
+ "postcss": "^8.5.23",
115
+ "react": "^19.2.8",
116
+ "react-dom": "^19.2.8",
117
+ "react-router-dom": "^7.18.1",
118
+ "tailwindcss": "^4.3.3",
119
+ "typescript": "6.0.3",
120
+ "vite": "^8.1.5",
121
+ "vitest": "4.1",
122
+ "ws": "^8.21.1"
125
123
  },
126
124
  "dependencies": {
127
125
  "@codemirror/autocomplete": "^6.20.3",
128
- "@codemirror/commands": "^6.10.3",
126
+ "@codemirror/commands": "^6.10.4",
129
127
  "@codemirror/lang-css": "^6.3.1",
130
128
  "@codemirror/lang-html": "^6.4.11",
131
129
  "@codemirror/lang-javascript": "^6.2.5",
132
130
  "@codemirror/lang-json": "^6.0.2",
133
131
  "@codemirror/lang-liquid": "^6.3.2",
134
- "@codemirror/language": "^6.12.3",
132
+ "@codemirror/language": "^6.12.4",
135
133
  "@codemirror/lint": "^6.9.7",
136
134
  "@codemirror/search": "^6.7.1",
137
- "@codemirror/state": "^6.6.0",
138
- "@codemirror/view": "^6.43.1",
139
- "@tiptap/extension-character-count": "^3.26.1",
140
- "@tiptap/extension-image": "^3.26.1",
141
- "@tiptap/extension-link": "^3.26.1",
142
- "@tiptap/extension-placeholder": "^3.26.1",
143
- "@tiptap/extension-table": "^3.26.1",
144
- "@tiptap/extension-underline": "^3.26.1",
145
- "@tiptap/react": "^3.26.1",
146
- "@tiptap/starter-kit": "^3.26.1",
135
+ "@codemirror/state": "^6.7.1",
136
+ "@codemirror/view": "^6.43.6",
137
+ "@tiptap/extension-character-count": "^3.29.0",
138
+ "@tiptap/extension-image": "^3.29.0",
139
+ "@tiptap/extension-link": "^3.29.0",
140
+ "@tiptap/extension-placeholder": "^3.29.0",
141
+ "@tiptap/extension-table": "^3.29.0",
142
+ "@tiptap/extension-underline": "^3.29.0",
143
+ "@tiptap/react": "^3.29.0",
144
+ "@tiptap/starter-kit": "^3.29.0",
147
145
  "buffer": "^6.0.3",
148
146
  "clsx": "^2.1.1",
149
147
  "codemirror": "^6.0.2",
150
- "liquidjs": "^10.27.0",
151
- "papaparse": "^5.5.3",
148
+ "liquidjs": "^10.27.2",
149
+ "papaparse": "^5.5.4",
152
150
  "prismjs": "^1.30.0",
153
151
  "react-markdown": "^10.1.0",
154
152
  "rehype-autolink-headings": "^7.1.0",
155
153
  "rehype-sanitize": "^6.0.0",
156
154
  "rehype-slug": "^6.0.0",
157
155
  "remark-gfm": "^4.0.1",
158
- "tailwind-merge": "^3.5.0",
156
+ "tailwind-merge": "^3.6.0",
159
157
  "tui-image-editor": "^3.15.3"
160
158
  },
161
159
  "publishConfig": {
@@ -61,18 +61,19 @@ function createViteConfig(proxyProvider) {
61
61
  import { defineConfig, loadEnv } from 'vite';
62
62
  import react from '@vitejs/plugin-react';
63
63
  ${importBlock}
64
- export default defineConfig(({ mode }) => {
64
+ export default defineConfig(({ mode }) => {
65
65
  const env = loadEnv(mode, process.cwd(), '');
66
66
 
67
- return {
68
- plugins: [
67
+ return {
68
+ plugins: [
69
69
  react(),
70
70
  ${pluginBlock} ].filter(Boolean),
71
71
  resolve: {
72
72
  dedupe: ['react', 'react-dom', 'react-router-dom'],
73
73
  },
74
- build: {
75
- cssMinify: false,
74
+ build: {
75
+ target: 'baseline-widely-available',
76
+ cssMinify: false,
76
77
  chunkSizeWarningLimit: 10000,
77
78
  },
78
79
  define: {
@@ -91,9 +92,9 @@ function setupDevTools(options = {}) {
91
92
  ensureFile(path.join(root, 'tsconfig.json'), `
92
93
  {
93
94
  "compilerOptions": {
94
- "target": "ES2021",
95
+ "target": "ES2022",
95
96
  "useDefineForClassFields": true,
96
- "lib": ["DOM", "DOM.Iterable", "ES2021"],
97
+ "lib": ["DOM", "DOM.Iterable", "ES2022"],
97
98
  "allowJs": false,
98
99
  "skipLibCheck": true,
99
100
  "esModuleInterop": true,
@@ -172,8 +172,12 @@ function createPackageJson(params) {
172
172
  ensureFile(path.join(root, 'package.json'), JSON.stringify({
173
173
  name: normalizeFirebaseProjectId(params.projectname) || 'llmnative-app',
174
174
  version: '0.1.0',
175
- private: true,
176
- type: 'module',
175
+ private: true,
176
+ type: 'module',
177
+ engines: {
178
+ node: '>=24.18.0 <25',
179
+ },
180
+ packageManager: 'npm@11.11.0',
177
181
  scripts: {
178
182
  dev: 'vite',
179
183
  build: 'vite build',
@@ -181,23 +185,23 @@ function createPackageJson(params) {
181
185
  typecheck: 'tsc --noEmit',
182
186
  },
183
187
  dependencies: {
184
- '@phosphor-icons/react': '^2.0.0',
185
- '@vitejs/plugin-react': '^4.3.4',
186
- firebase: '^10.14.0',
187
- 'lucide-react': '^0.400.0',
188
- react: '^18.2.0',
189
- 'react-dom': '^18.2.0',
190
- '@llmnative/react': `^${version}`,
191
- 'react-router-dom': '^6.22.0',
192
- },
193
- devDependencies: {
194
- '@tailwindcss/postcss': '^4.2.4',
195
- '@types/react': '^18.2.0',
196
- '@types/react-dom': '^18.2.0',
197
- autoprefixer: '^10.5.0',
198
- postcss: '^8.5.14',
199
- typescript: '^5.6.2',
200
- vite: '^5.4.21',
188
+ '@phosphor-icons/react': '^2.1.10',
189
+ firebase: '^12.16.0',
190
+ 'lucide-react': '^1.26.0',
191
+ react: '^19.2.8',
192
+ 'react-dom': '^19.2.8',
193
+ '@llmnative/react': `^${version}`,
194
+ 'react-router-dom': '^7.18.1',
195
+ },
196
+ devDependencies: {
197
+ '@tailwindcss/postcss': '^4.3.3',
198
+ '@types/react': '^19.2.17',
199
+ '@types/react-dom': '^19.2.3',
200
+ '@vitejs/plugin-react': '^6.0.4',
201
+ autoprefixer: '^10.5.4',
202
+ postcss: '^8.5.23',
203
+ typescript: '6.0.3',
204
+ vite: '^8.1.5',
201
205
  },
202
206
  }, null, 2));
203
207
  }
package/themes/cyber.ts CHANGED
@@ -125,16 +125,17 @@ export const motion: MotionRegistry = {
125
125
 
126
126
  export const components: Theme = {
127
127
  Grid: {
128
+ // REVERT NOTE (2026-07-15): see themes/default.ts for the full rationale/before-state.
128
129
  Card: {
129
130
  wrapperClassName: '',
130
- className: '',
131
- headerClassName: 'flex justify-between',
132
- bodyClassName: 'p-0',
133
- footerClassName: '',
131
+ className: 'rounded-none border-0 bg-transparent shadow-none',
132
+ headerClassName: 'flex justify-between border-b-0 bg-transparent px-0 py-2',
133
+ bodyClassName: 'p-0 mt-2',
134
+ footerClassName: 'border-t-0 bg-transparent px-0 py-2',
134
135
  loading: false,
135
136
  },
136
137
  Table: {
137
- wrapperClassName: '',
138
+ wrapperClassName: 'rounded-lg border border-border bg-card shadow-sm',
138
139
  className: '',
139
140
  headerClassName: '',
140
141
  bodyClassName: '',
@@ -143,7 +144,7 @@ export const components: Theme = {
143
144
  selectedClassName: 'bg-primary/10',
144
145
  },
145
146
  Gallery: {
146
- wrapperClassName: '',
147
+ wrapperClassName: 'rounded-lg border border-border bg-card shadow-sm p-3',
147
148
  className: '',
148
149
  scrollClassName: '',
149
150
  headerClassName: '',
@@ -224,7 +225,7 @@ export const components: Theme = {
224
225
  Loader: {
225
226
  wrapperClassName: '',
226
227
  className: '',
227
- icon: 'custom-loader',
228
+ icon: 'loader-2',
228
229
  title: 'Loading..',
229
230
  description: '',
230
231
  },
package/themes/default.ts CHANGED
@@ -125,16 +125,30 @@ export const motion: MotionRegistry = {
125
125
 
126
126
  export const components: Theme = {
127
127
  Grid: {
128
+ // REVERT NOTE (2026-07-15): before this change, `Card.className` was 'border-0' only
129
+ // (outer border removed, but bg-card/rounded/shadow kept — header+footer still sat in
130
+ // a white rounded box), `Table.wrapperClassName`/`Gallery.wrapperClassName` were both
131
+ // ''. The change moves the "raised card" surface (border+bg+shadow+radius) from the
132
+ // Card wrapper (which held header+body+footer together) down into Table/Gallery's own
133
+ // wrapper — so the toolbar row (view toggle, column picker, New component…) sits
134
+ // directly on the page's floor background with no box of its own, and only the actual
135
+ // data surface reads as a raised panel. To revert: restore the four blocks below to
136
+ // the values in this note.
128
137
  Card: {
129
138
  wrapperClassName: '',
130
- className: '',
131
- headerClassName: 'flex justify-between',
132
- bodyClassName: 'p-0',
133
- footerClassName: '',
139
+ // Fully transparent/borderless/shapeless now — header and footer (when used) are
140
+ // meant to float on the page's own background, not sit inside a card of their own;
141
+ // the "raised surface" look lives in Table/Gallery's wrapperClassName instead.
142
+ className: 'rounded-none border-0 bg-transparent shadow-none',
143
+ headerClassName: 'flex justify-between border-b-0 bg-transparent px-0 py-2',
144
+ bodyClassName: 'p-0 mt-2',
145
+ footerClassName: 'border-t-0 bg-transparent px-0 py-2',
134
146
  loading: false,
135
147
  },
136
148
  Table: {
137
- wrapperClassName: '',
149
+ // The table's own raised surface — previously this border+bg lived on the
150
+ // shared Card wrapper (see revert note above).
151
+ wrapperClassName: 'rounded-lg border border-border bg-card shadow-sm',
138
152
  className: '',
139
153
  headerClassName: '',
140
154
  bodyClassName: '',
@@ -143,7 +157,8 @@ export const components: Theme = {
143
157
  selectedClassName: 'bg-primary/10',
144
158
  },
145
159
  Gallery: {
146
- wrapperClassName: '',
160
+ // Same rationale as Table above; `p-3` so cards don't sit flush against the border.
161
+ wrapperClassName: 'rounded-lg border border-border bg-card shadow-sm p-3',
147
162
  className: '',
148
163
  scrollClassName: '',
149
164
  headerClassName: '',
@@ -224,7 +239,7 @@ export const components: Theme = {
224
239
  Loader: {
225
240
  wrapperClassName: '',
226
241
  className: '',
227
- icon: 'custom-loader',
242
+ icon: 'loader-2',
228
243
  title: 'Loading..',
229
244
  description: '',
230
245
  },
package/themes/flat.ts CHANGED
@@ -125,16 +125,17 @@ export const motion: MotionRegistry = {
125
125
 
126
126
  export const components: Theme = {
127
127
  Grid: {
128
+ // REVERT NOTE (2026-07-15): see themes/default.ts for the full rationale/before-state.
128
129
  Card: {
129
130
  wrapperClassName: '',
130
- className: '',
131
- headerClassName: 'flex justify-between',
132
- bodyClassName: 'p-0',
133
- footerClassName: '',
131
+ className: 'rounded-none border-0 bg-transparent shadow-none',
132
+ headerClassName: 'flex justify-between border-b-0 bg-transparent px-0 py-2',
133
+ bodyClassName: 'p-0 mt-2',
134
+ footerClassName: 'border-t-0 bg-transparent px-0 py-2',
134
135
  loading: false,
135
136
  },
136
137
  Table: {
137
- wrapperClassName: '',
138
+ wrapperClassName: 'rounded-lg border border-border bg-card shadow-sm',
138
139
  className: '',
139
140
  headerClassName: '',
140
141
  bodyClassName: '',
@@ -143,7 +144,7 @@ export const components: Theme = {
143
144
  selectedClassName: 'bg-primary/10',
144
145
  },
145
146
  Gallery: {
146
- wrapperClassName: '',
147
+ wrapperClassName: 'rounded-lg border border-border bg-card shadow-sm p-3',
147
148
  className: '',
148
149
  scrollClassName: '',
149
150
  headerClassName: '',
@@ -224,7 +225,7 @@ export const components: Theme = {
224
225
  Loader: {
225
226
  wrapperClassName: '',
226
227
  className: '',
227
- icon: 'custom-loader',
228
+ icon: 'loader-2',
228
229
  title: 'Loading..',
229
230
  description: '',
230
231
  },