Skip to content

Commit 3c28102

Browse files
authored
Merge pull request #76 from objectstack-ai/copilot/redesign-object-form-designer-again
2 parents a3666df + 8cdcda8 commit 3c28102

27 files changed

+2467
-111
lines changed

examples/designer-modes/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Designer Modes Example
2+
3+
This example demonstrates the three specialized designer modes in Object UI:
4+
5+
## 🎯 Designer Modes
6+
7+
### 1. Form Designer
8+
Optimized for building forms with validation and field management.
9+
- **Components**: Form fields, buttons, basic layout
10+
- **Branding**: Emerald/Teal
11+
- **Use Case**: Creating contact forms, registration forms, data entry forms
12+
13+
### 2. Layout Designer
14+
Optimized for designing page layouts and structures.
15+
- **Components**: Containers, grids, navigation, content
16+
- **Branding**: Blue/Indigo
17+
- **Use Case**: Creating page structures, dashboards, landing pages
18+
19+
### 3. General Designer
20+
Full-featured designer with all available components.
21+
- **Components**: All 30+ components
22+
- **Branding**: Purple/Pink
23+
- **Use Case**: Any UI design task requiring maximum flexibility
24+
25+
## 🚀 Running the Example
26+
27+
```bash
28+
# Install dependencies (from root)
29+
pnpm install
30+
31+
# Run the example
32+
cd examples/designer-modes
33+
pnpm dev
34+
```
35+
36+
The application will start at `http://localhost:5173`
37+
38+
## 🎨 Features
39+
40+
- **Mode Switching**: Toggle between the three designer modes using the top navigation
41+
- **Live Preview**: See your changes in real-time as you design
42+
- **Schema Export**: Check the console to see the generated schema JSON
43+
- **Persistence**: Switch modes while maintaining your design (uses the same schema)
44+
45+
## 📝 Usage
46+
47+
1. **Start with a Mode**: Choose Form Designer for forms, Layout Designer for page structures, or General Designer for everything
48+
2. **Drag Components**: Drag components from the left panel to the canvas
49+
3. **Configure Properties**: Select a component and edit its properties in the right panel
50+
4. **Switch Modes**: Try switching between modes to see different component sets
51+
5. **Export Schema**: The schema is logged to the console on every change
52+
53+
## 🔄 How It Works
54+
55+
```tsx
56+
import { Designer } from '@object-ui/designer';
57+
58+
function App() {
59+
const [mode, setMode] = useState('general');
60+
61+
return (
62+
<Designer
63+
mode={mode}
64+
onSchemaChange={(schema) => console.log(schema)}
65+
/>
66+
);
67+
}
68+
```
69+
70+
## 📚 Related Documentation
71+
72+
- [Specialized Designers Guide](../../packages/designer/SPECIALIZED_DESIGNERS.md)
73+
- [Main Designer Documentation](../../packages/designer/README.md)

examples/designer-modes/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Designer Modes Demo - Object UI</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "@examples/designer-modes",
3+
"private": true,
4+
"license": "MIT",
5+
"version": "0.0.0",
6+
"type": "module",
7+
"scripts": {
8+
"dev": "vite",
9+
"build": "tsc -b && vite build",
10+
"lint": "eslint .",
11+
"preview": "vite preview"
12+
},
13+
"dependencies": {
14+
"@object-ui/core": "workspace:*",
15+
"@object-ui/react": "workspace:*",
16+
"@object-ui/components": "workspace:*",
17+
"@object-ui/designer": "workspace:*",
18+
"react": "^18.3.1",
19+
"react-dom": "^18.3.1"
20+
},
21+
"devDependencies": {
22+
"@eslint/js": "^9.39.1",
23+
"@types/node": "^24.10.1",
24+
"@types/react": "^18.3.12",
25+
"@types/react-dom": "^18.3.1",
26+
"@vitejs/plugin-react": "^5.1.2",
27+
"autoprefixer": "^10.4.23",
28+
"eslint": "^9.39.1",
29+
"eslint-plugin-react-hooks": "^7.0.1",
30+
"eslint-plugin-react-refresh": "^0.4.24",
31+
"globals": "^16.5.0",
32+
"postcss": "^8.5.6",
33+
"tailwindcss": "^3.4.19",
34+
"typescript": "~5.9.3",
35+
"typescript-eslint": "^8.46.4",
36+
"vite": "^5.0.0"
37+
}
38+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {},
5+
},
6+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { useState } from 'react';
2+
import { Designer, type DesignerMode } from '@object-ui/designer';
3+
import type { SchemaNode } from '@object-ui/core';
4+
5+
function App() {
6+
const [mode, setMode] = useState<DesignerMode>('general');
7+
const [schema, setSchema] = useState<SchemaNode>({
8+
type: 'div',
9+
className: 'p-8',
10+
body: []
11+
});
12+
13+
return (
14+
<div className="h-screen flex flex-col">
15+
{/* Mode Selector */}
16+
<div className="h-16 bg-gray-900 text-white flex items-center px-6 gap-4 shadow-lg z-50">
17+
<h1 className="text-xl font-bold">Object UI Designer Modes</h1>
18+
<div className="flex-1" />
19+
<div className="flex gap-2">
20+
<button
21+
onClick={() => setMode('form')}
22+
className={`px-4 py-2 rounded-lg font-medium transition-all ${
23+
mode === 'form'
24+
? 'bg-emerald-500 text-white shadow-lg'
25+
: 'bg-gray-800 text-gray-300 hover:bg-gray-700'
26+
}`}
27+
>
28+
Form
29+
</button>
30+
<button
31+
onClick={() => setMode('layout')}
32+
className={`px-4 py-2 rounded-lg font-medium transition-all ${
33+
mode === 'layout'
34+
? 'bg-blue-500 text-white shadow-lg'
35+
: 'bg-gray-800 text-gray-300 hover:bg-gray-700'
36+
}`}
37+
>
38+
Layout
39+
</button>
40+
<button
41+
onClick={() => setMode('canvas')}
42+
className={`px-4 py-2 rounded-lg font-medium transition-all ${
43+
mode === 'canvas'
44+
? 'bg-amber-500 text-white shadow-lg'
45+
: 'bg-gray-800 text-gray-300 hover:bg-gray-700'
46+
}`}
47+
>
48+
Canvas
49+
</button>
50+
<button
51+
onClick={() => setMode('general')}
52+
className={`px-4 py-2 rounded-lg font-medium transition-all ${
53+
mode === 'general'
54+
? 'bg-purple-500 text-white shadow-lg'
55+
: 'bg-gray-800 text-gray-300 hover:bg-gray-700'
56+
}`}
57+
>
58+
General
59+
</button>
60+
</div>
61+
</div>
62+
63+
{/* Designer */}
64+
<div className="flex-1 overflow-hidden">
65+
<Designer
66+
key={mode} // Re-mount when mode changes
67+
mode={mode}
68+
initialSchema={schema}
69+
onSchemaChange={(newSchema) => {
70+
setSchema(newSchema);
71+
console.log('Schema updated:', newSchema);
72+
}}
73+
/>
74+
</div>
75+
</div>
76+
);
77+
}
78+
79+
export default App;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
@tailwind base;
2+
@tailwind components;
3+
@tailwind utilities;
4+
5+
:root {
6+
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
7+
line-height: 1.5;
8+
font-weight: 400;
9+
}
10+
11+
* {
12+
margin: 0;
13+
padding: 0;
14+
box-sizing: border-box;
15+
}
16+
17+
body {
18+
margin: 0;
19+
display: flex;
20+
min-width: 320px;
21+
min-height: 100vh;
22+
}
23+
24+
#root {
25+
width: 100%;
26+
height: 100vh;
27+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { StrictMode } from 'react';
2+
import { createRoot } from 'react-dom/client';
3+
import App from './App';
4+
import './index.css';
5+
6+
createRoot(document.getElementById('root')!).render(
7+
<StrictMode>
8+
<App />
9+
</StrictMode>,
10+
);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/** @type {import('tailwindcss').Config} */
2+
export default {
3+
content: [
4+
"./index.html",
5+
"./src/**/*.{js,ts,jsx,tsx}",
6+
"../../packages/designer/src/**/*.{js,ts,jsx,tsx}",
7+
"../../packages/components/src/**/*.{js,ts,jsx,tsx}",
8+
],
9+
theme: {
10+
extend: {},
11+
},
12+
plugins: [],
13+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"useDefineForClassFields": true,
5+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
6+
"module": "ESNext",
7+
"types": ["vite/client"],
8+
"skipLibCheck": true,
9+
10+
/* Bundler mode */
11+
"moduleResolution": "bundler",
12+
"allowImportingTsExtensions": true,
13+
"isolatedModules": true,
14+
"moduleDetection": "force",
15+
"noEmit": true,
16+
"jsx": "react-jsx",
17+
18+
/* Linting */
19+
"strict": true,
20+
"noUnusedLocals": true,
21+
"noUnusedParameters": true,
22+
"noFallthroughCasesInSwitch": true,
23+
"noUncheckedSideEffectImports": true
24+
},
25+
"include": ["src"]
26+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { defineConfig } from 'vite';
2+
import react from '@vitejs/plugin-react';
3+
4+
// https://vitejs.dev/config/
5+
export default defineConfig({
6+
plugins: [react()],
7+
resolve: {
8+
alias: {
9+
'@': '/src',
10+
},
11+
},
12+
});

0 commit comments

Comments
 (0)