1
1
mirror of https://github.com/leon-ai/leon.git synced 2024-10-27 10:38:35 +03:00

feat: final widget new structure

This commit is contained in:
louistiti 2023-12-10 08:48:13 +08:00
parent 7167849d6a
commit 05200a195b
No known key found for this signature in database
GPG Key ID: 0A1C3B043E70C77D
5 changed files with 32 additions and 110 deletions

View File

@ -9,9 +9,7 @@ import '@leon-ai/aurora/style.css'
import { createRoot } from 'react-dom/client'
import { createElement } from 'react'
import parse from 'html-react-parser'
import * as auroraComponents from '@leon-ai/aurora'
import { WidgetWrapper, Button } from '@leon-ai/aurora'
export default class Chatbot {
constructor() {
@ -112,36 +110,6 @@ export default class Chatbot {
const root = createRoot(container)
/* string = {
"component": "WidgetWrapper",
"props": {
"children": [
{
"component": "Button",
"props": {
"children": "Hello World"
}
}
]
}
}*/
// render WidgetWrapper component
/*if (string.component === 'WidgetWrapper') {
const WidgetWrapperComponent = auroraComponents[string.component]
console.log('WidgetWrapperComponent', WidgetWrapperComponent)
console.log('string.props', string.props)
const widgetWrapper = createElement(WidgetWrapperComponent, string.props)
root.render(widgetWrapper)
}*/
// should be recursive for all children props need to load component
const render = (component) => {
if (component) {
const reactComponent = auroraComponents[component.component]

View File

@ -22,7 +22,7 @@ export type ActionFunction = (params: ActionParams) => Promise<void>
*/
export interface Answer {
key?: string
widget?: Widget
widget?: Widget<unknown>
data?: AnswerData
core?: SkillAnswerCoreData
}
@ -30,7 +30,7 @@ export interface TextAnswer extends Answer {
key: string
}
export interface WidgetAnswer extends Answer {
widget: Widget
widget: Widget<unknown>
key?: string
}
export type AnswerData = Record<string, string | number> | null

View File

@ -1,11 +1,25 @@
import { type WidgetWrapperProps } from '@leon-ai/aurora'
interface WidgetOptions {
wrapperProps: Omit<WidgetWrapperProps, 'children'>
export interface WidgetOptions<T> {
wrapperProps?: Omit<WidgetWrapperProps, 'children'>
params?: T
}
export abstract class Widget {
public abstract wrapperProps: WidgetOptions['wrapperProps']
export abstract class Widget<T> {
public wrapperProps: WidgetOptions<T>['wrapperProps']
public params: WidgetOptions<T>['params']
protected constructor(options?: WidgetOptions<T>) {
if (options?.wrapperProps) {
this.wrapperProps = options.wrapperProps
}
if (!options?.params) {
this.params = undefined
} else {
this.params = options.params
}
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore

View File

@ -1,13 +1,7 @@
import fs from 'node:fs'
import path from 'node:path'
import type { ActionFunction } from '@sdk/types'
import { leon } from '@sdk/leon'
// TODO: import widgets @sdk/aurora
// import { Button, Card } from '@sdk/aurora'
import PlaygroundTestWidget from '../widgets/playground-test'
// import tsxTemplate from '../widgets/playground-test'
export const run: ActionFunction = async function () {
/**
@ -216,25 +210,6 @@ export const run: ActionFunction = async function () {
// const widget = createElement('Card', null, createElement('Button', null, 'Click me'))
// Problem with this solution: can't pass dynamic value to the widget
const widgetPath = path.resolve(__dirname, '../widgets/playground-test.tsx')
const fileContent = await fs.promises.readFile(widgetPath, 'utf-8')
const regex = /return\s*\(\s*([\s\S]*?)\s*\)/
const match = fileContent.match(regex)
let widgetContent = null
if (match) {
const [content] = match
widgetContent = content.slice(8, -1)
} else {
// TODO: error in skill not respecting guideline
}
/**
* TODO: non-JSX trial
*/
const playgroundTestWidget = new PlaygroundTestWidget({
params: {
value1: 'Hello',
@ -245,13 +220,5 @@ export const run: ActionFunction = async function () {
}
})
// TODO: from SDK, auto call render()
// await leon.answer({ widget })
await leon.answer({ widget: playgroundTestWidget })
/**
* TODO: think of parsing JSX at the server side instead
* No need to develop a parser for every future client
*/
// await leon.answer({ widget: widgetContent })
}

View File

@ -1,52 +1,25 @@
// TODO: "Widget" mother class from SDK
// export default class WidgetPlayground extends Widget {
import { Button, Flexbox } from '@sdk/aurora'
import { Widget } from '@sdk/widget'
interface WidgetOptions {
wrapperProps: Widget['wrapperProps']
params: Params
}
import { Widget, type WidgetOptions } from '@sdk/widget'
import { Button } from '@sdk/aurora'
interface Params {
value1: string
value2: string
}
export default class PlaygroundTestWidget extends Widget {
public readonly wrapperProps: Widget['wrapperProps']
private readonly params: Params
constructor(options: WidgetOptions) {
super()
this.wrapperProps = options.wrapperProps
this.params = options.params
export default class PlaygroundTestWidget extends Widget<Params> {
constructor(options?: WidgetOptions<Params>) {
super(options)
}
public render() {
// TODO: force WidgetWrapper to be the root element (from mother class render method)
public render(): Button {
let children = 'Click me'
if (this.params) {
children = this.params.value1 + ' ' + this.params.value2
}
return new Button({
children: this.params.value1 + ' ' + this.params.value2
children
})
/*return new WidgetWrapper({
children: [
new Flexbox({
gap: 'md',
children: [
new Button({
children: this.params.value1 + ' ' + this.params.value2
}),
new Button({
danger: true,
children: 'Danger button'
})
]
})
]
})*/
}
}