add prompt library dialog.
This commit is contained in:
parent
199ddb6848
commit
5c3c8a0beb
11
package.json
11
package.json
@ -8,6 +8,7 @@
|
||||
"@material-ui/core": "^4.12.4",
|
||||
"@mui/icons-material": "^5.15.10",
|
||||
"@mui/material": "^5.15.10",
|
||||
"@reduxjs/toolkit": "^2.2.1",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
@ -17,22 +18,20 @@
|
||||
"@types/react-dom": "^18.2.19",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-redux": "^9.1.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"browser": {
|
||||
"crypto": false
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
|
11382
pnpm-lock.yaml
Normal file
11382
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,8 +4,10 @@ import './App.css';
|
||||
import PromptArea from './components/PromptArea';
|
||||
import { Op, Operation } from './components/Operation';
|
||||
import Nugget from './components/Nugget';
|
||||
import { Ast } from './lib/ast';
|
||||
|
||||
function App() {
|
||||
const ast = new Ast();
|
||||
const c = (
|
||||
<div className="App">
|
||||
<PromptArea>
|
||||
|
@ -1,25 +1,19 @@
|
||||
import { Badge, Chip, Menu, MenuItem } from "@material-ui/core";
|
||||
import Nugget from "./Nugget";
|
||||
import React, { Children, Component, ReactNode, ReactPropTypes } from 'react';
|
||||
import { Composable } from "./IComposable";
|
||||
import { Menu, MenuItem } from "@material-ui/core";
|
||||
import React, { Children, ReactNode } from 'react';
|
||||
import "./Operation.css";
|
||||
import { Op } from "../lib/operator";
|
||||
import { randomUUID } from "crypto";
|
||||
|
||||
enum Op {
|
||||
JOINED = "joined",
|
||||
AND = "and",
|
||||
SWAPPED = "swaped",
|
||||
SWAP = "swap",
|
||||
BLENDED = "blended",
|
||||
BLEND = "blend",
|
||||
}
|
||||
|
||||
function Operation({ children, initialOp }: { children: ReactNode[], initialOp: Op }) {
|
||||
function Operation({ children, initialOp }: { children: ReactNode[], initialOp: Op}) {
|
||||
const [op, setOp] = React.useState(initialOp);
|
||||
const [contextMenu, setContextMenu] = React.useState<{
|
||||
mouseX: number;
|
||||
mouseY: number;
|
||||
} | null>(null);
|
||||
|
||||
const [id, ] = React.useState(randomUUID);
|
||||
|
||||
const handleContextMenu = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
setContextMenu(
|
||||
|
5
src/components/PromptArea.css
Normal file
5
src/components/PromptArea.css
Normal file
@ -0,0 +1,5 @@
|
||||
.add-button {
|
||||
position: absolute;
|
||||
right: 10pt;
|
||||
top: 10pt;
|
||||
}
|
@ -1,14 +1,37 @@
|
||||
import { Button, ButtonGroup, Chip } from '@material-ui/core';
|
||||
import React, { Children, Component, ReactNode } from 'react';
|
||||
import { Button } from '@material-ui/core';
|
||||
import { Children, ReactNode } from 'react';
|
||||
import Nugget from './Nugget';
|
||||
import { Operation } from './Operation';
|
||||
// import { Composable } from './IComposable';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import "./PromptArea.css";
|
||||
import { PromptLibrary } from './PromptLibrary';
|
||||
import React from 'react';
|
||||
|
||||
type Composable = (typeof Nugget) | (typeof Operation);
|
||||
|
||||
export default function PromptArea({ children }: { children?: any }) {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
const handleClickOpen = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const handleClose = (value: string) => {
|
||||
setOpen(false);
|
||||
setSelectedValue(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button className="add-button">
|
||||
<AddIcon />
|
||||
<PromptLibrary
|
||||
open={isPromptLibraryOpen}
|
||||
onClose={handleClose}
|
||||
></PromptLibrary>
|
||||
|
||||
</Button>
|
||||
<div>
|
||||
{
|
||||
Children.map(children, child => {
|
||||
return (<div>
|
||||
@ -16,6 +39,7 @@ export default function PromptArea({ children }: { children?: any }) {
|
||||
</div>)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
43
src/components/PromptLibrary.tsx
Normal file
43
src/components/PromptLibrary.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { Dialog, DialogTitle, List, ListItem, ListItemAvatar, Avatar, ListItemText } from "@material-ui/core";
|
||||
import { blue } from "@material-ui/core/colors";
|
||||
import ListItemButton from "@mui/material/ListItemButton";
|
||||
|
||||
export type Category = {
|
||||
id: string,
|
||||
label: string,
|
||||
color?: string,
|
||||
}
|
||||
|
||||
const categories = [
|
||||
{ id: "style", label: "Styles", color: "blue" },
|
||||
{ id: "subject", label: "Subjects", color: "black" },
|
||||
{ id: "vibes", label: "Vibes", color: "gold" },
|
||||
{ id: "mediums", label: "Mediums", color: "black" },
|
||||
] as Category[];
|
||||
|
||||
export interface SimpleDialogProps {
|
||||
open: boolean;
|
||||
selectedValue: string;
|
||||
onClose: (value: string) => void;
|
||||
}
|
||||
|
||||
export function PromptLibrary(props: SimpleDialogProps) {
|
||||
const { onClose, selectedValue, open } = props;
|
||||
|
||||
const handleClose = () => {
|
||||
onClose(selectedValue);
|
||||
};
|
||||
|
||||
const handleNuggetClick = (value: string) => {
|
||||
onClose(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog onClose={handleClose} open={open}>
|
||||
<DialogTitle>Prompt Library</DialogTitle>
|
||||
<div>
|
||||
Prompt Library
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
@ -3,13 +3,17 @@ import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import { Provider } from 'react-redux';
|
||||
import store from "./store"
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider >
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
|
@ -1,7 +1,86 @@
|
||||
export interface AstNode {
|
||||
import { randomUUID } from "crypto";
|
||||
import { Op } from "./operator";
|
||||
import { createSlice } from '@reduxjs/toolkit'
|
||||
|
||||
export interface IAstNode {
|
||||
id: string;
|
||||
toPrompt(): string;
|
||||
}
|
||||
|
||||
export class Ast {
|
||||
export interface IToPrompt {
|
||||
}
|
||||
|
||||
}
|
||||
export class Nugget implements IAstNode, IToPrompt {
|
||||
public score: number = 0;
|
||||
public id: string;
|
||||
public constructor(public text: string) {
|
||||
this.id = randomUUID();
|
||||
}
|
||||
|
||||
get sign() {
|
||||
return this.score > 0 ? "+" : (this.score < 0 ? "-" : "");
|
||||
}
|
||||
|
||||
get repeatSign() {
|
||||
return Array(this.score).map(() => this.sign).join("")
|
||||
}
|
||||
|
||||
public toPrompt() {
|
||||
return `(${this.text})${this.repeatSign}`
|
||||
}
|
||||
}
|
||||
|
||||
export class Operation extends Array<Nugget> implements IAstNode, IToPrompt {
|
||||
public id: string;
|
||||
public constructor(public op: Op, ...items: Nugget[]) {
|
||||
super(...items);
|
||||
this.id = randomUUID();
|
||||
}
|
||||
|
||||
get nuggetStr() {
|
||||
return this.map(i => i.toPrompt()).join(", ")
|
||||
}
|
||||
|
||||
toPrompt(): string {
|
||||
return `(${this.nuggetStr}).${this.op}()`;
|
||||
}
|
||||
}
|
||||
|
||||
export class Ast extends Array<IAstNode> implements IToPrompt {
|
||||
public toPrompt(): string {
|
||||
return this.map(i => i.toPrompt()).join(",");
|
||||
}
|
||||
public changeOp(id : string, op : Op) : Ast {
|
||||
return this.map(n => {
|
||||
if (n.id != id) return n;
|
||||
if (n instanceof Operation) {
|
||||
n.op = op;
|
||||
}
|
||||
return n;
|
||||
}) as Ast;
|
||||
}
|
||||
public removeNode(id : string) : Ast{
|
||||
return this.filter(n => n.id != id) as Ast;
|
||||
}
|
||||
}
|
||||
|
||||
export const astSlice = createSlice({
|
||||
name: "ast",
|
||||
initialState: new Ast(),
|
||||
reducers: {
|
||||
addNugget (state, action) {
|
||||
state.push(
|
||||
new Nugget(action.payload)
|
||||
);
|
||||
},
|
||||
// addOperation (state, action) {
|
||||
// state.push(
|
||||
// new Operation(...action.payload)
|
||||
// )
|
||||
// }
|
||||
}
|
||||
});
|
||||
|
||||
export const { addNugget } = astSlice.actions
|
||||
|
||||
export default astSlice.reducer;
|
8
src/lib/operator.ts
Normal file
8
src/lib/operator.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export enum Op {
|
||||
JOINED = "joined",
|
||||
AND = "and",
|
||||
SWAPPED = "swaped",
|
||||
SWAP = "swap",
|
||||
BLENDED = "blended",
|
||||
BLEND = "blend",
|
||||
}
|
9
src/store.ts
Normal file
9
src/store.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { configureStore } from '@reduxjs/toolkit'
|
||||
|
||||
import astReducer from "./lib/ast"
|
||||
|
||||
export default configureStore({
|
||||
reducer: {
|
||||
ast: astReducer,
|
||||
},
|
||||
});
|
@ -7,8 +7,7 @@
|
||||
"esnext"
|
||||
],
|
||||
"paths": {
|
||||
|
||||
"@material-ui/*": ["./node_modules/@material-ui/core/esm/*"]
|
||||
"@material-ui/*": ["./node_modules/@material-ui/core/esm/*"],
|
||||
},
|
||||
"typeRoots": [
|
||||
"node_modules/@types",
|
||||
|
Loading…
Reference in New Issue
Block a user