@micro-cms/admin-ui 0.0.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.
- package/dist/AutoForm.d.ts +9 -0
- package/dist/AutoForm.js +28 -0
- package/dist/AutoTable.d.ts +10 -0
- package/dist/AutoTable.js +21 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +26 -0
- package/dist/registry.d.ts +19 -0
- package/dist/registry.js +27 -0
- package/package.json +29 -0
package/dist/AutoForm.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { ComponentRegistry, DefaultTextInput } from './registry';
|
|
3
|
+
export const AutoForm = ({ entity, initialData = {}, onSubmit }) => {
|
|
4
|
+
const [formData, setFormData] = useState(initialData);
|
|
5
|
+
// Update form data if initialData changes
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
setFormData(initialData || {});
|
|
8
|
+
}, [initialData]);
|
|
9
|
+
const handleChange = (fieldName, value) => {
|
|
10
|
+
setFormData((prev) => ({ ...prev, [fieldName]: value }));
|
|
11
|
+
};
|
|
12
|
+
const handleSubmit = (e) => {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
onSubmit(formData);
|
|
15
|
+
};
|
|
16
|
+
return (React.createElement("form", { onSubmit: handleSubmit, className: "space-y-4 p-4 border rounded shadow-sm bg-white" },
|
|
17
|
+
React.createElement("h3", { className: "text-lg font-semibold mb-4" },
|
|
18
|
+
"Create ",
|
|
19
|
+
entity.name),
|
|
20
|
+
entity.fields.map((field) => {
|
|
21
|
+
const Component = ComponentRegistry.get(field.type) || DefaultTextInput;
|
|
22
|
+
return (React.createElement("div", { key: field.name, className: "mb-2" },
|
|
23
|
+
React.createElement(Component, { field: field, value: formData[field.name], onChange: (val) => handleChange(field.name, val) })));
|
|
24
|
+
}),
|
|
25
|
+
React.createElement("button", { type: "submit", className: "px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors" },
|
|
26
|
+
"Save ",
|
|
27
|
+
entity.name)));
|
|
28
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Entity } from '@micro-cms/types';
|
|
3
|
+
interface AutoTableProps {
|
|
4
|
+
entity: Entity;
|
|
5
|
+
data: any[];
|
|
6
|
+
onEdit?: (item: any) => void;
|
|
7
|
+
onDelete?: (item: any) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare const AutoTable: React.FC<AutoTableProps>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export const AutoTable = ({ entity, data, onEdit, onDelete }) => {
|
|
3
|
+
if (!data || data.length === 0) {
|
|
4
|
+
return React.createElement("div", { className: "p-4 text-gray-500" },
|
|
5
|
+
"No records found for ",
|
|
6
|
+
entity.name);
|
|
7
|
+
}
|
|
8
|
+
return (React.createElement("div", { className: "overflow-x-auto border rounded" },
|
|
9
|
+
React.createElement("table", { className: "min-w-full divide-y divide-gray-200" },
|
|
10
|
+
React.createElement("thead", { className: "bg-gray-50" },
|
|
11
|
+
React.createElement("tr", null,
|
|
12
|
+
entity.fields.map((field) => (React.createElement("th", { key: field.name, className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider" }, field.label || field.name))),
|
|
13
|
+
(onEdit || onDelete) && React.createElement("th", { className: "px-6 py-3 text-right" }, "Actions"))),
|
|
14
|
+
React.createElement("tbody", { className: "bg-white divide-y divide-gray-200" }, data.map((item, idx) => (React.createElement("tr", { key: item.id || idx },
|
|
15
|
+
entity.fields.map((field) => (React.createElement("td", { key: field.name, className: "px-6 py-4 whitespace-nowrap text-sm text-gray-900" }, typeof item[field.name] === 'boolean'
|
|
16
|
+
? item[field.name] ? 'Yes' : 'No'
|
|
17
|
+
: String(item[field.name])))),
|
|
18
|
+
(onEdit || onDelete) && (React.createElement("td", { className: "px-6 py-4 whitespace-nowrap text-right text-sm font-medium" },
|
|
19
|
+
onEdit && (React.createElement("button", { onClick: () => onEdit(item), className: "text-indigo-600 hover:text-indigo-900 mr-4" }, "Edit")),
|
|
20
|
+
onDelete && (React.createElement("button", { onClick: () => onDelete(item), className: "text-red-600 hover:text-red-900" }, "Delete")))))))))));
|
|
21
|
+
};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ComponentRegistry, DefaultTextInput, DefaultNumberInput, DefaultBooleanInput } from './registry';
|
|
2
|
+
export * from './registry';
|
|
3
|
+
export * from './AutoForm';
|
|
4
|
+
export * from './AutoTable';
|
|
5
|
+
const adminUiModule = {
|
|
6
|
+
manifest: {
|
|
7
|
+
name: '@micro-cms/admin-ui',
|
|
8
|
+
version: '0.0.1',
|
|
9
|
+
provides: ['admin-interface'],
|
|
10
|
+
requires: ['introspection'],
|
|
11
|
+
pairsWith: {
|
|
12
|
+
'@micro-cms/mock-db': { reason: 'Admin needs data to display', strength: 'recommended' }
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
async load({ context }) {
|
|
16
|
+
// Register default components
|
|
17
|
+
ComponentRegistry.register('text', DefaultTextInput);
|
|
18
|
+
ComponentRegistry.register('number', DefaultNumberInput);
|
|
19
|
+
ComponentRegistry.register('boolean', DefaultBooleanInput);
|
|
20
|
+
// Listen to schema changes to potentially re-render or update internal UI state
|
|
21
|
+
context.subscribe('database.schema', (schema) => {
|
|
22
|
+
console.log('Admin UI detected schema update', schema);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
export default adminUiModule;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Field, FieldType } from '@micro-cms/types';
|
|
3
|
+
export interface FieldComponentProps {
|
|
4
|
+
field: Field;
|
|
5
|
+
value: any;
|
|
6
|
+
onChange: (value: any) => void;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
export type FieldComponent = React.ComponentType<FieldComponentProps>;
|
|
10
|
+
declare class Registry {
|
|
11
|
+
private components;
|
|
12
|
+
register(type: FieldType | string, component: FieldComponent): void;
|
|
13
|
+
get(type: string): FieldComponent | undefined;
|
|
14
|
+
}
|
|
15
|
+
export declare const ComponentRegistry: Registry;
|
|
16
|
+
export declare const DefaultTextInput: FieldComponent;
|
|
17
|
+
export declare const DefaultNumberInput: FieldComponent;
|
|
18
|
+
export declare const DefaultBooleanInput: FieldComponent;
|
|
19
|
+
export {};
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
class Registry {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.components = new Map();
|
|
5
|
+
}
|
|
6
|
+
register(type, component) {
|
|
7
|
+
this.components.set(type, component);
|
|
8
|
+
}
|
|
9
|
+
get(type) {
|
|
10
|
+
return this.components.get(type);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const ComponentRegistry = new Registry();
|
|
14
|
+
// Default Components (Fallbacks)
|
|
15
|
+
export const DefaultTextInput = ({ field, value, onChange }) => (React.createElement("div", { className: "flex flex-col gap-1" },
|
|
16
|
+
React.createElement("label", { className: "text-sm font-medium" }, field.label || field.name),
|
|
17
|
+
React.createElement("input", { className: "border rounded px-2 py-1", type: "text", value: value || '', onChange: (e) => onChange(e.target.value), required: field.constraints?.required })));
|
|
18
|
+
export const DefaultNumberInput = ({ field, value, onChange }) => (React.createElement("div", { className: "flex flex-col gap-1" },
|
|
19
|
+
React.createElement("label", { className: "text-sm font-medium" }, field.label || field.name),
|
|
20
|
+
React.createElement("input", { className: "border rounded px-2 py-1", type: "number", value: value || '', onChange: (e) => onChange(Number(e.target.value)) })));
|
|
21
|
+
export const DefaultBooleanInput = ({ field, value, onChange }) => (React.createElement("div", { className: "flex items-center gap-2" },
|
|
22
|
+
React.createElement("input", { type: "checkbox", checked: !!value, onChange: (e) => onChange(e.target.checked) }),
|
|
23
|
+
React.createElement("label", { className: "text-sm font-medium" }, field.label || field.name)));
|
|
24
|
+
// Register defaults
|
|
25
|
+
ComponentRegistry.register('text', DefaultTextInput);
|
|
26
|
+
ComponentRegistry.register('number', DefaultNumberInput);
|
|
27
|
+
ComponentRegistry.register('boolean', DefaultBooleanInput);
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@micro-cms/admin-ui",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": ["dist"],
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"react": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@micro-cms/types": "workspace:*"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"devDependencies": {},
|
|
24
|
+
"typescript": "^5.0.0",
|
|
25
|
+
|
|
26
|
+
"build": "tsc",
|
|
27
|
+
"prepare": "pnpm build"
|
|
28
|
+
}
|
|
29
|
+
}
|