@treenity/react 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AclEditor.d.ts +11 -0
- package/dist/AclEditor.d.ts.map +1 -0
- package/dist/AclEditor.js +152 -0
- package/dist/AclEditor.js.map +1 -0
- package/dist/App.d.ts +2 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +521 -0
- package/dist/App.js.map +1 -0
- package/dist/Inspector.d.ts +12 -0
- package/dist/Inspector.d.ts.map +1 -0
- package/dist/Inspector.js +360 -0
- package/dist/Inspector.js.map +1 -0
- package/dist/Tree.d.ts +16 -0
- package/dist/Tree.d.ts.map +1 -0
- package/dist/Tree.js +100 -0
- package/dist/Tree.js.map +1 -0
- package/dist/ViewPage.d.ts +5 -0
- package/dist/ViewPage.d.ts.map +1 -0
- package/dist/ViewPage.js +13 -0
- package/dist/ViewPage.js.map +1 -0
- package/dist/bind/computed.d.ts +9 -0
- package/dist/bind/computed.d.ts.map +1 -0
- package/dist/bind/computed.js +61 -0
- package/dist/bind/computed.js.map +1 -0
- package/dist/bind/engine.d.ts +3 -0
- package/dist/bind/engine.d.ts.map +1 -0
- package/dist/bind/engine.js +184 -0
- package/dist/bind/engine.js.map +1 -0
- package/dist/bind/eval.d.ts +13 -0
- package/dist/bind/eval.d.ts.map +1 -0
- package/dist/bind/eval.js +97 -0
- package/dist/bind/eval.js.map +1 -0
- package/dist/bind/hook.d.ts +8 -0
- package/dist/bind/hook.d.ts.map +1 -0
- package/dist/bind/hook.js +99 -0
- package/dist/bind/hook.js.map +1 -0
- package/dist/bind/parse.d.ts +19 -0
- package/dist/bind/parse.d.ts.map +1 -0
- package/dist/bind/parse.js +86 -0
- package/dist/bind/parse.js.map +1 -0
- package/dist/bind/pipes.d.ts +4 -0
- package/dist/bind/pipes.d.ts.map +1 -0
- package/dist/bind/pipes.js +43 -0
- package/dist/bind/pipes.js.map +1 -0
- package/dist/cache.d.ts +27 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +236 -0
- package/dist/cache.js.map +1 -0
- package/dist/client-tree.d.ts +9 -0
- package/dist/client-tree.d.ts.map +1 -0
- package/dist/client-tree.js +14 -0
- package/dist/client-tree.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +10 -0
- package/dist/client.js.map +1 -0
- package/dist/components/ui/accordion.d.ts +8 -0
- package/dist/components/ui/accordion.d.ts.map +1 -0
- package/dist/components/ui/accordion.js +18 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/components/ui/badge.d.ts +10 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/badge.js +19 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/button.d.ts +11 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +31 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/checkbox.d.ts +4 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -0
- package/dist/components/ui/checkbox.js +7 -0
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +18 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/dialog.js +37 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +14 -0
- package/dist/components/ui/drawer.d.ts.map +1 -0
- package/dist/components/ui/drawer.js +35 -0
- package/dist/components/ui/drawer.js.map +1 -0
- package/dist/components/ui/input.d.ts +4 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/input.js +7 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/label.d.ts +5 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/label.js +8 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/popover.d.ts +11 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/popover.js +26 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/progress.d.ts +5 -0
- package/dist/components/ui/progress.d.ts.map +1 -0
- package/dist/components/ui/progress.js +9 -0
- package/dist/components/ui/progress.js.map +1 -0
- package/dist/components/ui/select.d.ts +16 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/select.js +39 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/slider.d.ts +5 -0
- package/dist/components/ui/slider.d.ts.map +1 -0
- package/dist/components/ui/slider.js +15 -0
- package/dist/components/ui/slider.js.map +1 -0
- package/dist/components/ui/sonner.d.ts +4 -0
- package/dist/components/ui/sonner.d.ts.map +1 -0
- package/dist/components/ui/sonner.js +21 -0
- package/dist/components/ui/sonner.js.map +1 -0
- package/dist/components/ui/switch.d.ts +7 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/components/ui/switch.js +9 -0
- package/dist/components/ui/switch.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +4 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/textarea.js +7 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +8 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +18 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/context/index.d.ts +31 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +98 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +2 -0
- package/dist/context.js.map +1 -0
- package/dist/hooks.d.ts +21 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +156 -0
- package/dist/hooks.js.map +1 -0
- package/dist/idb.d.ts +13 -0
- package/dist/idb.d.ts.map +1 -0
- package/dist/idb.js +67 -0
- package/dist/idb.js.map +1 -0
- package/dist/lib/minimd.d.ts +3 -0
- package/dist/lib/minimd.d.ts.map +1 -0
- package/dist/lib/minimd.js +97 -0
- package/dist/lib/minimd.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/load-client.d.ts +2 -0
- package/dist/load-client.d.ts.map +1 -0
- package/dist/load-client.js +6 -0
- package/dist/load-client.js.map +1 -0
- package/dist/main.d.ts +4 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +16 -0
- package/dist/main.js.map +1 -0
- package/dist/mods/editor-ui/client.d.ts +6 -0
- package/dist/mods/editor-ui/client.d.ts.map +1 -0
- package/dist/mods/editor-ui/client.js +8 -0
- package/dist/mods/editor-ui/client.js.map +1 -0
- package/dist/mods/editor-ui/default-view.d.ts +2 -0
- package/dist/mods/editor-ui/default-view.d.ts.map +1 -0
- package/dist/mods/editor-ui/default-view.js +71 -0
- package/dist/mods/editor-ui/default-view.js.map +1 -0
- package/dist/mods/editor-ui/dir-view.d.ts +2 -0
- package/dist/mods/editor-ui/dir-view.d.ts.map +1 -0
- package/dist/mods/editor-ui/dir-view.js +42 -0
- package/dist/mods/editor-ui/dir-view.js.map +1 -0
- package/dist/mods/editor-ui/form-fields.d.ts +6 -0
- package/dist/mods/editor-ui/form-fields.d.ts.map +1 -0
- package/dist/mods/editor-ui/form-fields.js +401 -0
- package/dist/mods/editor-ui/form-fields.js.map +1 -0
- package/dist/mods/editor-ui/layout-view.d.ts +2 -0
- package/dist/mods/editor-ui/layout-view.d.ts.map +1 -0
- package/dist/mods/editor-ui/layout-view.js +22 -0
- package/dist/mods/editor-ui/layout-view.js.map +1 -0
- package/dist/mods/editor-ui/list-items.d.ts +2 -0
- package/dist/mods/editor-ui/list-items.d.ts.map +1 -0
- package/dist/mods/editor-ui/list-items.js +38 -0
- package/dist/mods/editor-ui/list-items.js.map +1 -0
- package/dist/mods/editor-ui/node-utils.d.ts +10 -0
- package/dist/mods/editor-ui/node-utils.d.ts.map +1 -0
- package/dist/mods/editor-ui/node-utils.js +76 -0
- package/dist/mods/editor-ui/node-utils.js.map +1 -0
- package/dist/mods/editor-ui/user-view.d.ts +2 -0
- package/dist/mods/editor-ui/user-view.d.ts.map +1 -0
- package/dist/mods/editor-ui/user-view.js +47 -0
- package/dist/mods/editor-ui/user-view.js.map +1 -0
- package/dist/mods/treenity/client.d.ts +4 -0
- package/dist/mods/treenity/client.d.ts.map +1 -0
- package/dist/mods/treenity/client.js +6 -0
- package/dist/mods/treenity/client.js.map +1 -0
- package/dist/mods/treenity/groups/index.d.ts +2 -0
- package/dist/mods/treenity/groups/index.d.ts.map +1 -0
- package/dist/mods/treenity/groups/index.js +27 -0
- package/dist/mods/treenity/groups/index.js.map +1 -0
- package/dist/mods/treenity/preview.d.ts +6 -0
- package/dist/mods/treenity/preview.d.ts.map +1 -0
- package/dist/mods/treenity/preview.js +95 -0
- package/dist/mods/treenity/preview.js.map +1 -0
- package/dist/mods/treenity/ref-view.d.ts +2 -0
- package/dist/mods/treenity/ref-view.d.ts.map +1 -0
- package/dist/mods/treenity/ref-view.js +29 -0
- package/dist/mods/treenity/ref-view.js.map +1 -0
- package/dist/mods/treenity/schema-form.d.ts +2 -0
- package/dist/mods/treenity/schema-form.d.ts.map +1 -0
- package/dist/mods/treenity/schema-form.js +38 -0
- package/dist/mods/treenity/schema-form.js.map +1 -0
- package/dist/mods/treenity/seed.d.ts +2 -0
- package/dist/mods/treenity/seed.d.ts.map +1 -0
- package/dist/mods/treenity/seed.js +53 -0
- package/dist/mods/treenity/seed.js.map +1 -0
- package/dist/mods/treenity/server.d.ts +2 -0
- package/dist/mods/treenity/server.d.ts.map +1 -0
- package/dist/mods/treenity/server.js +2 -0
- package/dist/mods/treenity/server.js.map +1 -0
- package/dist/mods/treenity/type-view.d.ts +2 -0
- package/dist/mods/treenity/type-view.d.ts.map +1 -0
- package/dist/mods/treenity/type-view.js +36 -0
- package/dist/mods/treenity/type-view.js.map +1 -0
- package/dist/remote-tree.d.ts +6 -0
- package/dist/remote-tree.d.ts.map +1 -0
- package/dist/remote-tree.js +18 -0
- package/dist/remote-tree.js.map +1 -0
- package/dist/schema-loader.d.ts +19 -0
- package/dist/schema-loader.d.ts.map +1 -0
- package/dist/schema-loader.js +63 -0
- package/dist/schema-loader.js.map +1 -0
- package/dist/trpc.d.ts +187 -0
- package/dist/trpc.d.ts.map +1 -0
- package/dist/trpc.js +21 -0
- package/dist/trpc.js.map +1 -0
- package/package.json +88 -0
- package/src/AclEditor.tsx +330 -0
- package/src/App.tsx +775 -0
- package/src/CLAUDE.md +16 -0
- package/src/Inspector.tsx +857 -0
- package/src/Tree.tsx +237 -0
- package/src/ViewPage.tsx +45 -0
- package/src/bind/bind.test.ts +316 -0
- package/src/bind/computed.ts +64 -0
- package/src/bind/engine.ts +198 -0
- package/src/bind/eval.ts +108 -0
- package/src/bind/hook.ts +112 -0
- package/src/bind/parse.ts +104 -0
- package/src/bind/pipes.ts +71 -0
- package/src/cache.test.ts +139 -0
- package/src/cache.ts +244 -0
- package/src/client-tree.test.ts +116 -0
- package/src/client-tree.ts +24 -0
- package/src/client.ts +11 -0
- package/src/components/ui/accordion.tsx +63 -0
- package/src/components/ui/badge.tsx +27 -0
- package/src/components/ui/button.tsx +44 -0
- package/src/components/ui/checkbox.tsx +19 -0
- package/src/components/ui/dialog.tsx +156 -0
- package/src/components/ui/drawer.tsx +132 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/label.tsx +21 -0
- package/src/components/ui/popover.tsx +86 -0
- package/src/components/ui/progress.tsx +30 -0
- package/src/components/ui/select.tsx +189 -0
- package/src/components/ui/slider.tsx +62 -0
- package/src/components/ui/sonner.tsx +32 -0
- package/src/components/ui/switch.tsx +34 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/components/ui/tooltip.tsx +56 -0
- package/src/context/index.tsx +131 -0
- package/src/context.ts +1 -0
- package/src/hooks.ts +208 -0
- package/src/idb.ts +80 -0
- package/src/index.html +14 -0
- package/src/lib/minimd.css +28 -0
- package/src/lib/minimd.ts +95 -0
- package/src/lib/utils.ts +6 -0
- package/src/load-client.ts +5 -0
- package/src/main.tsx +22 -0
- package/src/mods/editor-ui/CLAUDE.md +3 -0
- package/src/mods/editor-ui/client.ts +8 -0
- package/src/mods/editor-ui/default-view.tsx +148 -0
- package/src/mods/editor-ui/dir-view.tsx +91 -0
- package/src/mods/editor-ui/form-fields.tsx +861 -0
- package/src/mods/editor-ui/layout-view.tsx +62 -0
- package/src/mods/editor-ui/list-items.tsx +63 -0
- package/src/mods/editor-ui/node-utils.ts +84 -0
- package/src/mods/editor-ui/user-view.tsx +101 -0
- package/src/mods/treenity/CLAUDE.md +7 -0
- package/src/mods/treenity/client.ts +6 -0
- package/src/mods/treenity/groups/index.tsx +65 -0
- package/src/mods/treenity/preview.tsx +133 -0
- package/src/mods/treenity/ref-view.tsx +87 -0
- package/src/mods/treenity/schema-form.tsx +65 -0
- package/src/mods/treenity/seed.ts +56 -0
- package/src/mods/treenity/server.ts +1 -0
- package/src/mods/treenity/type-view.tsx +116 -0
- package/src/remote-tree.test.ts +142 -0
- package/src/remote-tree.ts +25 -0
- package/src/schema-loader.ts +84 -0
- package/src/style.css +1269 -0
- package/src/trpc.ts +27 -0
- package/src/vite-env.d.ts +3 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Minimal markdown → HTML for chat bubbles (~50 lines)
|
|
2
|
+
// Covers: headers, bold, italic, inline code, code blocks, links, lists, blockquotes, hr
|
|
3
|
+
import './minimd.css';
|
|
4
|
+
|
|
5
|
+
const esc = (s: string) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
6
|
+
|
|
7
|
+
function inline(s: string): string {
|
|
8
|
+
return esc(s)
|
|
9
|
+
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
10
|
+
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
|
|
11
|
+
.replace(/__(.+?)__/g, '<strong>$1</strong>')
|
|
12
|
+
.replace(/\*(.+?)\*/g, '<em>$1</em>')
|
|
13
|
+
.replace(/_(.+?)_/g, '<em>$1</em>')
|
|
14
|
+
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener">$1</a>');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function minimd(src: string): string {
|
|
18
|
+
const lines = src.split('\n');
|
|
19
|
+
const out: string[] = [];
|
|
20
|
+
let i = 0;
|
|
21
|
+
|
|
22
|
+
while (i < lines.length) {
|
|
23
|
+
const line = lines[i];
|
|
24
|
+
|
|
25
|
+
// Fenced code block
|
|
26
|
+
if (line.startsWith('```')) {
|
|
27
|
+
const lang = line.slice(3).trim();
|
|
28
|
+
const code: string[] = [];
|
|
29
|
+
i++;
|
|
30
|
+
while (i < lines.length && !lines[i].startsWith('```')) {
|
|
31
|
+
code.push(lines[i]);
|
|
32
|
+
i++;
|
|
33
|
+
}
|
|
34
|
+
i++; // skip closing ```
|
|
35
|
+
out.push(`<pre${lang ? ` data-lang="${esc(lang)}"` : ''}><code>${esc(code.join('\n'))}</code></pre>`);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Header
|
|
40
|
+
const hm = line.match(/^(#{1,4})\s+(.+)/);
|
|
41
|
+
if (hm) { out.push(`<h${hm[1].length}>${inline(hm[2])}</h${hm[1].length}>`); i++; continue; }
|
|
42
|
+
|
|
43
|
+
// HR
|
|
44
|
+
if (/^[-*_]{3,}\s*$/.test(line)) { out.push('<hr>'); i++; continue; }
|
|
45
|
+
|
|
46
|
+
// Blockquote
|
|
47
|
+
if (line.startsWith('> ')) { out.push(`<blockquote>${inline(line.slice(2))}</blockquote>`); i++; continue; }
|
|
48
|
+
|
|
49
|
+
// Unordered list
|
|
50
|
+
if (/^[-*+]\s/.test(line)) {
|
|
51
|
+
out.push('<ul>');
|
|
52
|
+
while (i < lines.length && /^[-*+]\s/.test(lines[i])) {
|
|
53
|
+
out.push(`<li>${inline(lines[i].replace(/^[-*+]\s/, ''))}</li>`);
|
|
54
|
+
i++;
|
|
55
|
+
}
|
|
56
|
+
out.push('</ul>');
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Ordered list
|
|
61
|
+
if (/^\d+\.\s/.test(line)) {
|
|
62
|
+
out.push('<ol>');
|
|
63
|
+
while (i < lines.length && /^\d+\.\s/.test(lines[i])) {
|
|
64
|
+
out.push(`<li>${inline(lines[i].replace(/^\d+\.\s/, ''))}</li>`);
|
|
65
|
+
i++;
|
|
66
|
+
}
|
|
67
|
+
out.push('</ol>');
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Table
|
|
72
|
+
if (line.startsWith('|') && i + 1 < lines.length && /^\|[-\s:|]+\|/.test(lines[i + 1])) {
|
|
73
|
+
const parseRow = (r: string) => r.split('|').slice(1, -1).map(c => c.trim());
|
|
74
|
+
const headers = parseRow(line);
|
|
75
|
+
i += 2; // skip header + separator
|
|
76
|
+
out.push('<table><thead><tr>' + headers.map(h => `<th>${inline(h)}</th>`).join('') + '</tr></thead><tbody>');
|
|
77
|
+
while (i < lines.length && lines[i].startsWith('|')) {
|
|
78
|
+
const cells = parseRow(lines[i]);
|
|
79
|
+
out.push('<tr>' + cells.map(c => `<td>${inline(c)}</td>`).join('') + '</tr>');
|
|
80
|
+
i++;
|
|
81
|
+
}
|
|
82
|
+
out.push('</tbody></table>');
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Empty line
|
|
87
|
+
if (!line.trim()) { i++; continue; }
|
|
88
|
+
|
|
89
|
+
// Paragraph
|
|
90
|
+
out.push(`<p>${inline(line)}</p>`);
|
|
91
|
+
i++;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return out.join('\n');
|
|
95
|
+
}
|
package/src/lib/utils.ts
ADDED
package/src/main.tsx
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
3
|
+
import { enablePatches } from 'immer';
|
|
4
|
+
import { StrictMode } from 'react';
|
|
5
|
+
import { createRoot } from 'react-dom/client';
|
|
6
|
+
import { App } from './App';
|
|
7
|
+
import './load-client';
|
|
8
|
+
import './style.css';
|
|
9
|
+
|
|
10
|
+
enablePatches();
|
|
11
|
+
|
|
12
|
+
const queryClient = new QueryClient();
|
|
13
|
+
|
|
14
|
+
const root = document.getElementById('root');
|
|
15
|
+
if (!root) throw new Error('No #root element');
|
|
16
|
+
createRoot(root).render(
|
|
17
|
+
<StrictMode>
|
|
18
|
+
<QueryClientProvider client={queryClient}>
|
|
19
|
+
<App />
|
|
20
|
+
</QueryClientProvider>
|
|
21
|
+
</StrictMode>,
|
|
22
|
+
);
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Render, RenderContext } from '#context';
|
|
2
|
+
import { useChildren } from '#hooks';
|
|
3
|
+
import { trpc } from '#trpc';
|
|
4
|
+
import { type ComponentData, type NodeData, register } from '@treenity/core/core';
|
|
5
|
+
import { useCallback, useState } from 'react';
|
|
6
|
+
import { getComponents, getPlainFields, getSchema } from './node-utils';
|
|
7
|
+
|
|
8
|
+
/** Fallback for components without their own react handler */
|
|
9
|
+
function ComponentFieldsView({ value }: { value: ComponentData }) {
|
|
10
|
+
const s = getSchema(value.$type);
|
|
11
|
+
const fields = s ? Object.entries(s.properties) : [];
|
|
12
|
+
|
|
13
|
+
if (fields.length > 0) {
|
|
14
|
+
return (
|
|
15
|
+
<>
|
|
16
|
+
{fields.map(([k, prop]) => {
|
|
17
|
+
const val = (value as any)[k];
|
|
18
|
+
return (
|
|
19
|
+
<div key={k} className="comp-view-row">
|
|
20
|
+
<span className="comp-view-label">{(prop as any).title || k}</span>
|
|
21
|
+
<span className="comp-view-value">
|
|
22
|
+
{val === undefined || val === '' ? '—' : typeof val === 'object' ? JSON.stringify(val) : String(val)}
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
})}
|
|
27
|
+
</>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const entries = Object.entries(value).filter(([k]) => !k.startsWith('$'));
|
|
32
|
+
if (entries.length === 0) return null;
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
{entries.map(([k, v]) => (
|
|
37
|
+
<div key={k} className="comp-view-row">
|
|
38
|
+
<span className="comp-view-label">{k}</span>
|
|
39
|
+
<span className="comp-view-value">
|
|
40
|
+
{typeof v === 'string' ? v || '—' : typeof v === 'object' ? JSON.stringify(v) : String(v)}
|
|
41
|
+
</span>
|
|
42
|
+
</div>
|
|
43
|
+
))}
|
|
44
|
+
</>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function GenerateViewButton({ type, sample }: { type: string; sample: NodeData }) {
|
|
49
|
+
const [status, setStatus] = useState<'idle' | 'generating' | 'done' | 'error'>('idle');
|
|
50
|
+
const [error, setError] = useState('');
|
|
51
|
+
|
|
52
|
+
const generate = useCallback(async () => {
|
|
53
|
+
setStatus('generating');
|
|
54
|
+
try {
|
|
55
|
+
const clean = Object.fromEntries(
|
|
56
|
+
Object.entries(sample).filter(([k]) => !['$rev', '$acl', '$owner'].includes(k)),
|
|
57
|
+
);
|
|
58
|
+
await trpc.execute.mutate({
|
|
59
|
+
path: '/metatron',
|
|
60
|
+
action: 'task',
|
|
61
|
+
data: { prompt: `Generate a React view for type "${type}". Sample data:\n${JSON.stringify(clean, null, 2)}` },
|
|
62
|
+
});
|
|
63
|
+
setStatus('done');
|
|
64
|
+
} catch (err: any) {
|
|
65
|
+
setError(err.message);
|
|
66
|
+
setStatus('error');
|
|
67
|
+
}
|
|
68
|
+
}, [type, sample]);
|
|
69
|
+
|
|
70
|
+
if (status === 'generating') {
|
|
71
|
+
return <div className="text-sm text-blue-400 animate-pulse py-2">Creating task...</div>;
|
|
72
|
+
}
|
|
73
|
+
if (status === 'error') {
|
|
74
|
+
return <div className="text-sm text-red-400 py-2">{error}</div>;
|
|
75
|
+
}
|
|
76
|
+
if (status === 'done') {
|
|
77
|
+
return <div className="text-sm text-green-400 py-2">Task created in /metatron — waiting for AI</div>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<button
|
|
82
|
+
onClick={generate}
|
|
83
|
+
className="text-sm text-blue-400 hover:text-blue-300 border border-blue-400/30 rounded px-3 py-1.5 my-2"
|
|
84
|
+
>
|
|
85
|
+
Generate AI View
|
|
86
|
+
</button>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function DefaultNodeView({ value }: { value: NodeData }) {
|
|
91
|
+
const children = useChildren(value.$path);
|
|
92
|
+
const plain = getPlainFields(value);
|
|
93
|
+
const components = getComponents(value);
|
|
94
|
+
const hasInfo = Object.keys(plain).length > 0 || components.length > 0;
|
|
95
|
+
const canGenerate = value.$type.includes('.');
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<div className="node-default-view">
|
|
99
|
+
{canGenerate && <GenerateViewButton type={value.$type} sample={value} />}
|
|
100
|
+
|
|
101
|
+
{components.map(([name, comp]) => {
|
|
102
|
+
const ctype = (comp as any).$type;
|
|
103
|
+
return (
|
|
104
|
+
<div key={name} className="comp-view-card">
|
|
105
|
+
<div className="comp-view-header">
|
|
106
|
+
{name}
|
|
107
|
+
{name !== ctype && <span className="comp-type">{ctype}</span>}
|
|
108
|
+
</div>
|
|
109
|
+
<Render value={comp as ComponentData} />
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
})}
|
|
113
|
+
|
|
114
|
+
{Object.keys(plain).length > 0 && (
|
|
115
|
+
<div className="node-info-bar">
|
|
116
|
+
{Object.entries(plain).map(([k, v]) => (
|
|
117
|
+
<span key={k} className="node-info-chip data">
|
|
118
|
+
<span className="node-info-chip-label">{k}</span>
|
|
119
|
+
<span className="node-info-chip-val">
|
|
120
|
+
{typeof v === 'string' ? v : JSON.stringify(v)}
|
|
121
|
+
</span>
|
|
122
|
+
</span>
|
|
123
|
+
))}
|
|
124
|
+
</div>
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
{children.length > 0 && (
|
|
128
|
+
<RenderContext name="react:list">
|
|
129
|
+
<div className="children-grid">
|
|
130
|
+
{children.map((child) => (
|
|
131
|
+
<Render key={child.$path} value={child} />
|
|
132
|
+
))}
|
|
133
|
+
</div>
|
|
134
|
+
</RenderContext>
|
|
135
|
+
)}
|
|
136
|
+
|
|
137
|
+
{children.length === 0 && !hasInfo && <div className="node-empty">Empty node</div>}
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Dispatch: node → DefaultNodeView, component → ComponentFieldsView */
|
|
143
|
+
function DefaultView({ value }: { value: ComponentData }) {
|
|
144
|
+
if ('$path' in value) return <DefaultNodeView value={value as NodeData} />;
|
|
145
|
+
return <ComponentFieldsView value={value} />;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
register('default', 'react', DefaultView as any);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Render, RenderContext } from '#context';
|
|
2
|
+
import { useChildren } from '#hooks';
|
|
3
|
+
import { type NodeData, register } from '@treenity/core/core';
|
|
4
|
+
|
|
5
|
+
const STATUS_COLORS: Record<string, [string, string]> = {
|
|
6
|
+
draft: ['var(--accent-subtle, #1a2a3a)', 'var(--accent)'],
|
|
7
|
+
published: ['#1a2e1a', '#4c8'],
|
|
8
|
+
archived: ['#2e2a1a', '#ca4'],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function FolderView({ value }: { value: NodeData }) {
|
|
12
|
+
const children = useChildren(value.$path);
|
|
13
|
+
const meta = value.metadata as
|
|
14
|
+
| { $type: string; title?: string; description?: string }
|
|
15
|
+
| undefined;
|
|
16
|
+
const status = value.status as { $type: string; value?: string } | undefined;
|
|
17
|
+
const counter = value.counter as { $type: string; count?: number } | undefined;
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div className="node-default-view">
|
|
21
|
+
{(meta || status || counter) && (
|
|
22
|
+
<div
|
|
23
|
+
style={{
|
|
24
|
+
padding: 16,
|
|
25
|
+
background: 'var(--surface)',
|
|
26
|
+
borderRadius: 'var(--radius)',
|
|
27
|
+
marginBottom: 12,
|
|
28
|
+
}}
|
|
29
|
+
>
|
|
30
|
+
{meta?.title && <div style={{ fontSize: 18, fontWeight: 600 }}>{meta.title}</div>}
|
|
31
|
+
{meta?.description && (
|
|
32
|
+
<div style={{ fontSize: 13, color: 'var(--text-2)', marginTop: 4 }}>
|
|
33
|
+
{meta.description}
|
|
34
|
+
</div>
|
|
35
|
+
)}
|
|
36
|
+
{(status || counter) && (
|
|
37
|
+
<div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
|
|
38
|
+
{status?.value &&
|
|
39
|
+
(() => {
|
|
40
|
+
const [bg, fg] = STATUS_COLORS[status.value] ?? STATUS_COLORS.draft;
|
|
41
|
+
return (
|
|
42
|
+
<span
|
|
43
|
+
style={{
|
|
44
|
+
padding: '2px 10px',
|
|
45
|
+
borderRadius: 12,
|
|
46
|
+
fontSize: 11,
|
|
47
|
+
fontWeight: 600,
|
|
48
|
+
background: bg,
|
|
49
|
+
color: fg,
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
{status.value}
|
|
53
|
+
</span>
|
|
54
|
+
);
|
|
55
|
+
})()}
|
|
56
|
+
{counter != null && (
|
|
57
|
+
<span
|
|
58
|
+
style={{
|
|
59
|
+
padding: '2px 10px',
|
|
60
|
+
borderRadius: 12,
|
|
61
|
+
fontSize: 11,
|
|
62
|
+
fontWeight: 600,
|
|
63
|
+
background: 'var(--surface)',
|
|
64
|
+
border: '1px solid var(--border)',
|
|
65
|
+
color: 'var(--text-2)',
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
count: {counter.count ?? 0}
|
|
69
|
+
</span>
|
|
70
|
+
)}
|
|
71
|
+
</div>
|
|
72
|
+
)}
|
|
73
|
+
</div>
|
|
74
|
+
)}
|
|
75
|
+
{children.length > 0 && (
|
|
76
|
+
<RenderContext name="react:list">
|
|
77
|
+
<div className="children-grid">
|
|
78
|
+
{children.map((child) => (
|
|
79
|
+
<Render key={child.$path} value={child} />
|
|
80
|
+
))}
|
|
81
|
+
</div>
|
|
82
|
+
</RenderContext>
|
|
83
|
+
)}
|
|
84
|
+
{children.length === 0 && !meta && !status && !counter && (
|
|
85
|
+
<div className="node-empty">Empty folder</div>
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
register('dir', 'react', FolderView as any);
|