add prompt library dialog.

This commit is contained in:
Jordan Hewitt 2024-02-23 06:56:03 -08:00
parent 199ddb6848
commit 5c3c8a0beb
12 changed files with 11576 additions and 28 deletions

View File

@ -8,6 +8,7 @@
"@material-ui/core": "^4.12.4", "@material-ui/core": "^4.12.4",
"@mui/icons-material": "^5.15.10", "@mui/icons-material": "^5.15.10",
"@mui/material": "^5.15.10", "@mui/material": "^5.15.10",
"@reduxjs/toolkit": "^2.2.1",
"@testing-library/jest-dom": "^5.17.0", "@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
@ -17,22 +18,20 @@
"@types/react-dom": "^18.2.19", "@types/react-dom": "^18.2.19",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-redux": "^9.1.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"typescript": "^4.9.5", "typescript": "^4.9.5",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"browser": {
"crypto": false
},
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",
"build": "react-scripts build", "build": "react-scripts build",
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject" "eject": "react-scripts eject"
}, },
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": { "browserslist": {
"production": [ "production": [
">0.2%", ">0.2%",

11382
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,10 @@ import './App.css';
import PromptArea from './components/PromptArea'; import PromptArea from './components/PromptArea';
import { Op, Operation } from './components/Operation'; import { Op, Operation } from './components/Operation';
import Nugget from './components/Nugget'; import Nugget from './components/Nugget';
import { Ast } from './lib/ast';
function App() { function App() {
const ast = new Ast();
const c = ( const c = (
<div className="App"> <div className="App">
<PromptArea> <PromptArea>

View File

@ -1,25 +1,19 @@
import { Badge, Chip, Menu, MenuItem } from "@material-ui/core"; import { Menu, MenuItem } from "@material-ui/core";
import Nugget from "./Nugget"; import React, { Children, ReactNode } from 'react';
import React, { Children, Component, ReactNode, ReactPropTypes } from 'react';
import { Composable } from "./IComposable";
import "./Operation.css"; 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 [op, setOp] = React.useState(initialOp);
const [contextMenu, setContextMenu] = React.useState<{ const [contextMenu, setContextMenu] = React.useState<{
mouseX: number; mouseX: number;
mouseY: number; mouseY: number;
} | null>(null); } | null>(null);
const [id, ] = React.useState(randomUUID);
const handleContextMenu = (event: React.MouseEvent) => { const handleContextMenu = (event: React.MouseEvent) => {
event.preventDefault(); event.preventDefault();
setContextMenu( setContextMenu(

View File

@ -0,0 +1,5 @@
.add-button {
position: absolute;
right: 10pt;
top: 10pt;
}

View File

@ -1,13 +1,36 @@
import { Button, ButtonGroup, Chip } from '@material-ui/core'; import { Button } from '@material-ui/core';
import React, { Children, Component, ReactNode } from 'react'; import { Children, ReactNode } from 'react';
import Nugget from './Nugget'; import Nugget from './Nugget';
import { Operation } from './Operation'; 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); type Composable = (typeof Nugget) | (typeof Operation);
export default function PromptArea({ children }: { children?: any }) { 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 ( return (
<div>
<Button className="add-button">
<AddIcon />
<PromptLibrary
open={isPromptLibraryOpen}
onClose={handleClose}
></PromptLibrary>
</Button>
<div> <div>
{ {
Children.map(children, child => { Children.map(children, child => {
@ -17,5 +40,6 @@ export default function PromptArea({ children }: { children?: any }) {
}) })
} }
</div> </div>
</div>
); );
} }

View 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>
);
}

View File

@ -3,13 +3,17 @@ import ReactDOM from 'react-dom/client';
import './index.css'; import './index.css';
import App from './App'; import App from './App';
import reportWebVitals from './reportWebVitals'; import reportWebVitals from './reportWebVitals';
import { Provider } from 'react-redux';
import store from "./store"
const root = ReactDOM.createRoot( const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement document.getElementById('root') as HTMLElement
); );
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<Provider store={store}>
<App /> <App />
</Provider >
</React.StrictMode> </React.StrictMode>
); );

View File

@ -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
View 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
View File

@ -0,0 +1,9 @@
import { configureStore } from '@reduxjs/toolkit'
import astReducer from "./lib/ast"
export default configureStore({
reducer: {
ast: astReducer,
},
});

View File

@ -7,8 +7,7 @@
"esnext" "esnext"
], ],
"paths": { "paths": {
"@material-ui/*": ["./node_modules/@material-ui/core/esm/*"],
"@material-ui/*": ["./node_modules/@material-ui/core/esm/*"]
}, },
"typeRoots": [ "typeRoots": [
"node_modules/@types", "node_modules/@types",