@gui-chat-plugin/canvas 0.1.0
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/README.md +75 -0
- package/dist/core/definition.d.ts +15 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/plugin.d.ts +11 -0
- package/dist/core/types.d.ts +18 -0
- package/dist/core.cjs +1 -0
- package/dist/core.js +27 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +8 -0
- package/dist/style.css +1 -0
- package/dist/vue/Preview.vue.d.ts +8 -0
- package/dist/vue/View.vue.d.ts +12 -0
- package/dist/vue/index.d.ts +16 -0
- package/dist/vue.cjs +1 -0
- package/dist/vue.js +207 -0
- package/package.json +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# @gui-chat-plugin/canvas
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@gui-chat-plugin/canvas)
|
|
4
|
+
|
|
5
|
+
A drawing canvas plugin for [MulmoChat](https://github.com/receptron/MulmoChat).
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This plugin provides a drawing canvas where users can create drawings, sketches, or diagrams. The AI can then interpret or transform the drawing into other formats.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
yarn add @gui-chat-plugin/canvas
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Dependencies
|
|
18
|
+
|
|
19
|
+
This plugin requires `vue-drawing-canvas`:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn add vue-drawing-canvas
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Vue Implementation (for MulmoChat)
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// In src/tools/index.ts
|
|
31
|
+
import CanvasPlugin from "@gui-chat-plugin/canvas/vue";
|
|
32
|
+
|
|
33
|
+
const pluginList = [
|
|
34
|
+
// ... other plugins
|
|
35
|
+
CanvasPlugin,
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
// In src/main.ts
|
|
39
|
+
import "@gui-chat-plugin/canvas/style.css";
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Core Only (Framework-agnostic)
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { pluginCore, TOOL_NAME } from "@gui-chat-plugin/canvas";
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Package Exports
|
|
49
|
+
|
|
50
|
+
| Export | Description |
|
|
51
|
+
|--------|-------------|
|
|
52
|
+
| `@gui-chat-plugin/canvas` | Core (framework-agnostic) |
|
|
53
|
+
| `@gui-chat-plugin/canvas/vue` | Vue implementation |
|
|
54
|
+
| `@gui-chat-plugin/canvas/style.css` | Tailwind CSS styles |
|
|
55
|
+
|
|
56
|
+
## Test Prompts
|
|
57
|
+
|
|
58
|
+
1. "I want to draw something"
|
|
59
|
+
2. "Open the drawing canvas"
|
|
60
|
+
3. "Let me sketch an idea"
|
|
61
|
+
4. "Open canvas so I can draw a diagram"
|
|
62
|
+
|
|
63
|
+
## Development
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
yarn install
|
|
67
|
+
yarn dev # Start dev server
|
|
68
|
+
yarn build # Build
|
|
69
|
+
yarn typecheck # Type check
|
|
70
|
+
yarn lint # Lint
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canvas Plugin Tool Definition
|
|
3
|
+
*/
|
|
4
|
+
export declare const TOOL_NAME = "openCanvas";
|
|
5
|
+
export declare const TOOL_DEFINITION: {
|
|
6
|
+
type: "function";
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object";
|
|
11
|
+
properties: {};
|
|
12
|
+
required: string[];
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export declare const SYSTEM_PROMPT = "When the user asks 'I want to draw an image.', call openCanvas API to open the canvas.";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canvas Plugin - Core (Framework-agnostic)
|
|
3
|
+
*/
|
|
4
|
+
export type { CanvasArgs, ImageToolData, CanvasDrawingState } from "./types";
|
|
5
|
+
export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT } from "./definition";
|
|
6
|
+
export { executeOpenCanvas, pluginCore } from "./plugin";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canvas Plugin Core (Framework-agnostic)
|
|
3
|
+
*/
|
|
4
|
+
import type { ToolPluginCore, ToolContext, ToolResult } from "gui-chat-protocol";
|
|
5
|
+
import type { CanvasArgs, ImageToolData } from "./types";
|
|
6
|
+
export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT } from "./definition";
|
|
7
|
+
/**
|
|
8
|
+
* Execute the openCanvas function
|
|
9
|
+
*/
|
|
10
|
+
export declare const executeOpenCanvas: (_context: ToolContext, _args: CanvasArgs) => Promise<ToolResult<ImageToolData>>;
|
|
11
|
+
export declare const pluginCore: ToolPluginCore<ImageToolData, unknown, CanvasArgs>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canvas Plugin Types
|
|
3
|
+
*/
|
|
4
|
+
/** Canvas takes no arguments */
|
|
5
|
+
export type CanvasArgs = Record<string, never>;
|
|
6
|
+
/** Image data returned by the canvas */
|
|
7
|
+
export interface ImageToolData {
|
|
8
|
+
imageData: string;
|
|
9
|
+
prompt: string;
|
|
10
|
+
}
|
|
11
|
+
/** Drawing state for canvas persistence */
|
|
12
|
+
export interface CanvasDrawingState {
|
|
13
|
+
brushSize?: number;
|
|
14
|
+
brushColor?: string;
|
|
15
|
+
canvasWidth?: number;
|
|
16
|
+
canvasHeight?: number;
|
|
17
|
+
strokes?: unknown[];
|
|
18
|
+
}
|
package/dist/core.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="openCanvas",a={type:"function",name:e,description:"Open a drawing canvas for the user to create drawings, sketches, or diagrams.",parameters:{type:"object",properties:{},required:[]}},t=`When the user asks 'I want to draw an image.', call ${e} API to open the canvas.`,n=async(s,o)=>({message:"Drawing canvas opened",instructions:"Tell the user that you are able to turn the drawing into a photographic image, a manga or any other art style.",title:"Drawing Canvas"}),r={toolDefinition:a,execute:n,generatingMessage:"Opening drawing canvas...",isEnabled:()=>!0,systemPrompt:t};exports.SYSTEM_PROMPT=t;exports.TOOL_DEFINITION=a;exports.TOOL_NAME=e;exports.executeOpenCanvas=n;exports.pluginCore=r;
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const e = "openCanvas", a = {
|
|
2
|
+
type: "function",
|
|
3
|
+
name: e,
|
|
4
|
+
description: "Open a drawing canvas for the user to create drawings, sketches, or diagrams.",
|
|
5
|
+
parameters: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {},
|
|
8
|
+
required: []
|
|
9
|
+
}
|
|
10
|
+
}, t = `When the user asks 'I want to draw an image.', call ${e} API to open the canvas.`, n = async (r, s) => ({
|
|
11
|
+
message: "Drawing canvas opened",
|
|
12
|
+
instructions: "Tell the user that you are able to turn the drawing into a photographic image, a manga or any other art style.",
|
|
13
|
+
title: "Drawing Canvas"
|
|
14
|
+
}), o = {
|
|
15
|
+
toolDefinition: a,
|
|
16
|
+
execute: n,
|
|
17
|
+
generatingMessage: "Opening drawing canvas...",
|
|
18
|
+
isEnabled: () => !0,
|
|
19
|
+
systemPrompt: t
|
|
20
|
+
};
|
|
21
|
+
export {
|
|
22
|
+
t as SYSTEM_PROMPT,
|
|
23
|
+
a as TOOL_DEFINITION,
|
|
24
|
+
e as TOOL_NAME,
|
|
25
|
+
n as executeOpenCanvas,
|
|
26
|
+
o as pluginCore
|
|
27
|
+
};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs");exports.SYSTEM_PROMPT=e.SYSTEM_PROMPT;exports.TOOL_DEFINITION=e.TOOL_DEFINITION;exports.TOOL_NAME=e.TOOL_NAME;exports.executeOpenCanvas=e.executeOpenCanvas;exports.pluginCore=e.pluginCore;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-300:oklch(80.8% .114 19.571);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--container-2xl:42rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-semibold:600;--font-weight-bold:700;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mx-auto{margin-inline:auto}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.contents{display:contents}.flex{display:flex}.h-8{height:calc(var(--spacing)*8)}.h-auto{height:auto}.h-full{height:100%}.min-h-\[100px\]{min-height:100px}.min-h-screen{min-height:100vh}.w-8{width:calc(var(--spacing)*8)}.w-12{width:calc(var(--spacing)*12)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-full{max-width:100%}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-blue-500{border-color:var(--color-blue-500)}.border-gray-300{border-color:var(--color-gray-300)}.border-red-300{border-color:var(--color-red-300)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-800{background-color:var(--color-gray-800)}.bg-white{background-color:var(--color-white)}.p-4{padding:calc(var(--spacing)*4)}.p-8{padding:calc(var(--spacing)*8)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-2{padding-block:calc(var(--spacing)*2)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-gray-400{color:var(--color-gray-400)}.text-gray-900{color:var(--color-gray-900)}.text-white{color:var(--color-white)}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media(hover:hover){.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}}@media(prefers-color-scheme:dark){.dark\:bg-gray-800{background-color:var(--color-gray-800)}.dark\:bg-gray-900{background-color:var(--color-gray-900)}.dark\:text-white{color:var(--color-white)}}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ToolResult } from "gui-chat-protocol/vue";
|
|
2
|
+
import type { ImageToolData } from "../core/types";
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
result: ToolResult<ImageToolData>;
|
|
5
|
+
};
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
|
+
declare const _default: typeof __VLS_export;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ToolResult } from "gui-chat-protocol/vue";
|
|
2
|
+
import type { ImageToolData } from "../core/types";
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
selectedResult: ToolResult<ImageToolData> | null;
|
|
5
|
+
};
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
7
|
+
updateResult: (result: ToolResult<ImageToolData, unknown>) => any;
|
|
8
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
9
|
+
onUpdateResult?: ((result: ToolResult<ImageToolData, unknown>) => any) | undefined;
|
|
10
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const _default: typeof __VLS_export;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canvas Plugin - Vue Implementation
|
|
3
|
+
*/
|
|
4
|
+
import "../style.css";
|
|
5
|
+
import type { ToolPlugin } from "gui-chat-protocol/vue";
|
|
6
|
+
import type { CanvasArgs, ImageToolData } from "../core/types";
|
|
7
|
+
import View from "./View.vue";
|
|
8
|
+
import Preview from "./Preview.vue";
|
|
9
|
+
export declare const plugin: ToolPlugin<ImageToolData, unknown, CanvasArgs>;
|
|
10
|
+
export type { CanvasArgs, ImageToolData, CanvasDrawingState } from "../core/types";
|
|
11
|
+
export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT, executeOpenCanvas, pluginCore, } from "../core/plugin";
|
|
12
|
+
export { View, Preview };
|
|
13
|
+
declare const _default: {
|
|
14
|
+
plugin: ToolPlugin<ImageToolData, unknown, CanvasArgs, import("gui-chat-protocol/vue").InputHandler, Record<string, unknown>>;
|
|
15
|
+
};
|
|
16
|
+
export default _default;
|
package/dist/vue.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const d=require("./core.cjs"),e=require("vue"),V=require("vue-drawing-canvas"),T={class:"w-full h-full flex flex-col bg-white"},O={class:"flex-shrink-0 p-4 border-b bg-gray-50"},B={class:"flex items-center justify-between gap-4"},D={class:"flex items-center gap-4"},F={class:"flex items-center gap-2"},$={class:"flex gap-1"},j=["onClick"],I={class:"flex items-center gap-2"},L={class:"flex-1 p-4 overflow-hidden"},x=e.defineComponent({__name:"View",props:{selectedResult:{}},emits:["updateResult"],setup(u,{emit:f}){const l=u,N=f,n=e.ref(null),p=e.ref(""),r=e.ref(5),s=e.ref("#000000"),h=e.ref([]),i=e.ref(800),c=e.ref(600),w=e.ref(0),b=()=>{if(l.selectedResult?.viewState?.drawingState){const t=l.selectedResult.viewState.drawingState;r.value=t.brushSize||5,s.value=t.brushColor||"#000000",i.value=t.canvasWidth||800,c.value=t.canvasHeight||600,t.strokes?h.value=t.strokes:h.value=[]}else h.value=[]};b();const R=async()=>{if(n.value)try{n.value.undo(),setTimeout(v,50)}catch(t){console.warn("Undo operation failed:",t)}},S=async()=>{if(n.value)try{n.value.redo(),setTimeout(v,50)}catch(t){console.warn("Redo operation failed:",t)}},M=()=>{if(n.value)try{n.value.reset(),v()}catch(t){console.warn("Clear operation failed:",t)}},_=()=>{v()},v=async()=>{if(n.value&&l.selectedResult)try{const t=await n.value.save(),a={strokes:n.value.getAllStrokes(),brushSize:r.value,brushColor:s.value,canvasWidth:i.value,canvasHeight:c.value},m={...l.selectedResult,data:{prompt:l.selectedResult.data?.prompt||"",imageData:t},viewState:{drawingState:a}};N("updateResult",m)}catch(t){console.error("Failed to save drawing state:",t)}};e.watch(()=>l.selectedResult,()=>{b()},{immediate:!1}),e.watch([r,s],()=>{v()}),e.watch([i,c],()=>{w.value++});const g=()=>{const t=n.value?.$el?.parentElement;if(t){const o=t.getBoundingClientRect(),a=o.width-64,m=o.height-64,y=Math.max(300,Math.min(600,Math.floor(a))),k=Math.max(200,Math.min(400,Math.floor(m)));(y!==i.value||k!==c.value)&&(i.value=y,c.value=k)}};return e.onMounted(async()=>{await e.nextTick(),g(),window.addEventListener("resize",g)}),e.onUnmounted(()=>{window.removeEventListener("resize",g)}),(t,o)=>(e.openBlock(),e.createElementBlock("div",T,[e.createElementVNode("div",O,[e.createElementVNode("div",B,[e.createElementVNode("div",D,[e.createElementVNode("div",F,[e.createElementVNode("div",$,[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList([2,5,10,20],a=>e.createElementVNode("button",{key:a,onClick:m=>r.value=a,class:e.normalizeClass(["w-8 h-8 rounded border-2 transition-colors",r.value===a?"border-blue-500 bg-blue-100":"border-gray-300 bg-white hover:bg-gray-50"])},[e.createElementVNode("div",{class:e.normalizeClass("bg-gray-800 rounded-full mx-auto"),style:e.normalizeStyle({width:Math.max(2,a*1)+"px",height:Math.max(2,a*1)+"px"})},null,4)],10,j)),64))])]),e.createElementVNode("div",I,[e.withDirectives(e.createElementVNode("input",{"onUpdate:modelValue":o[0]||(o[0]=a=>s.value=a),type:"color",class:"w-12 h-8 rounded border border-gray-300"},null,512),[[e.vModelText,s.value]])])]),e.createElementVNode("div",{class:"flex items-center gap-1"},[e.createElementVNode("button",{onClick:R,class:"w-8 h-8 flex items-center justify-center rounded border-2 border-gray-300 bg-white hover:bg-gray-50",title:"Undo"}," ↩ "),e.createElementVNode("button",{onClick:S,class:"w-8 h-8 flex items-center justify-center rounded border-2 border-gray-300 bg-white hover:bg-gray-50",title:"Redo"}," ↪ "),e.createElementVNode("button",{onClick:M,class:"w-8 h-8 flex items-center justify-center rounded border-2 border-red-300 bg-white hover:bg-red-50",title:"Clear"}," 🗑 ")])])]),e.createElementVNode("div",L,[(e.openBlock(),e.createBlock(e.unref(V),{ref_key:"canvasRef",ref:n,key:`${u.selectedResult?.uuid||"default"}-${w.value}`,image:p.value,"onUpdate:image":o[1]||(o[1]=a=>p.value=a),width:i.value,height:c.value,"stroke-type":"dash","line-cap":"round","line-join":"round","fill-shape":!1,eraser:!1,lineWidth:r.value,color:s.value,"background-color":"#FFFFFF","background-image":void 0,watermark:void 0,"initial-image":h.value,saveAs:"png",styles:{border:"1px solid #ddd",borderRadius:"8px"},lock:!1,onMouseup:_,onTouchend:_},null,8,["image","width","height","lineWidth","color","initial-image"]))])]))}}),P={class:"min-h-[100px] flex items-center justify-center"},W=["src"],z={key:1,class:"text-gray-400 text-sm"},E=e.defineComponent({__name:"Preview",props:{result:{}},setup(u){return(f,l)=>(e.openBlock(),e.createElementBlock("div",P,[u.result.data?.imageData?(e.openBlock(),e.createElementBlock("img",{key:0,src:u.result.data.imageData,class:"max-w-full h-auto rounded",alt:"Canvas drawing"},null,8,W)):(e.openBlock(),e.createElementBlock("div",z,"No drawing yet"))]))}}),C={...d.pluginCore,viewComponent:x,previewComponent:E},H={plugin:C};exports.SYSTEM_PROMPT=d.SYSTEM_PROMPT;exports.TOOL_DEFINITION=d.TOOL_DEFINITION;exports.TOOL_NAME=d.TOOL_NAME;exports.executeOpenCanvas=d.executeOpenCanvas;exports.pluginCore=d.pluginCore;exports.Preview=E;exports.View=x;exports.default=H;exports.plugin=C;
|
package/dist/vue.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { pluginCore as $ } from "./core.js";
|
|
2
|
+
import { SYSTEM_PROMPT as ue, TOOL_DEFINITION as ve, TOOL_NAME as he, executeOpenCanvas as ge } from "./core.js";
|
|
3
|
+
import { defineComponent as M, ref as n, watch as w, onMounted as O, nextTick as W, onUnmounted as j, createElementBlock as g, openBlock as u, createElementVNode as t, Fragment as H, renderList as L, normalizeClass as S, normalizeStyle as N, withDirectives as U, vModelText as V, createBlock as z, unref as B } from "vue";
|
|
4
|
+
import I from "vue-drawing-canvas";
|
|
5
|
+
const P = { class: "w-full h-full flex flex-col bg-white" }, A = { class: "flex-shrink-0 p-4 border-b bg-gray-50" }, K = { class: "flex items-center justify-between gap-4" }, Y = { class: "flex items-center gap-4" }, q = { class: "flex items-center gap-2" }, G = { class: "flex gap-1" }, J = ["onClick"], Q = { class: "flex items-center gap-2" }, X = { class: "flex-1 p-4 overflow-hidden" }, Z = /* @__PURE__ */ M({
|
|
6
|
+
__name: "View",
|
|
7
|
+
props: {
|
|
8
|
+
selectedResult: {}
|
|
9
|
+
},
|
|
10
|
+
emits: ["updateResult"],
|
|
11
|
+
setup(v, { emit: b }) {
|
|
12
|
+
const r = v, T = b, s = n(null), x = n(""), l = n(5), i = n("#000000"), m = n([]), c = n(800), d = n(600), y = n(0), _ = () => {
|
|
13
|
+
if (r.selectedResult?.viewState?.drawingState) {
|
|
14
|
+
const e = r.selectedResult.viewState.drawingState;
|
|
15
|
+
l.value = e.brushSize || 5, i.value = e.brushColor || "#000000", c.value = e.canvasWidth || 800, d.value = e.canvasHeight || 600, e.strokes ? m.value = e.strokes : m.value = [];
|
|
16
|
+
} else
|
|
17
|
+
m.value = [];
|
|
18
|
+
};
|
|
19
|
+
_();
|
|
20
|
+
const D = async () => {
|
|
21
|
+
if (s.value)
|
|
22
|
+
try {
|
|
23
|
+
s.value.undo(), setTimeout(h, 50);
|
|
24
|
+
} catch (e) {
|
|
25
|
+
console.warn("Undo operation failed:", e);
|
|
26
|
+
}
|
|
27
|
+
}, E = async () => {
|
|
28
|
+
if (s.value)
|
|
29
|
+
try {
|
|
30
|
+
s.value.redo(), setTimeout(h, 50);
|
|
31
|
+
} catch (e) {
|
|
32
|
+
console.warn("Redo operation failed:", e);
|
|
33
|
+
}
|
|
34
|
+
}, F = () => {
|
|
35
|
+
if (s.value)
|
|
36
|
+
try {
|
|
37
|
+
s.value.reset(), h();
|
|
38
|
+
} catch (e) {
|
|
39
|
+
console.warn("Clear operation failed:", e);
|
|
40
|
+
}
|
|
41
|
+
}, k = () => {
|
|
42
|
+
h();
|
|
43
|
+
}, h = async () => {
|
|
44
|
+
if (s.value && r.selectedResult)
|
|
45
|
+
try {
|
|
46
|
+
const e = await s.value.save(), a = {
|
|
47
|
+
strokes: s.value.getAllStrokes(),
|
|
48
|
+
brushSize: l.value,
|
|
49
|
+
brushColor: i.value,
|
|
50
|
+
canvasWidth: c.value,
|
|
51
|
+
canvasHeight: d.value
|
|
52
|
+
}, f = {
|
|
53
|
+
...r.selectedResult,
|
|
54
|
+
data: {
|
|
55
|
+
prompt: r.selectedResult.data?.prompt || "",
|
|
56
|
+
imageData: e
|
|
57
|
+
},
|
|
58
|
+
viewState: {
|
|
59
|
+
drawingState: a
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
T("updateResult", f);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.error("Failed to save drawing state:", e);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
w(
|
|
68
|
+
() => r.selectedResult,
|
|
69
|
+
() => {
|
|
70
|
+
_();
|
|
71
|
+
},
|
|
72
|
+
{ immediate: !1 }
|
|
73
|
+
), w([l, i], () => {
|
|
74
|
+
h();
|
|
75
|
+
}), w([c, d], () => {
|
|
76
|
+
y.value++;
|
|
77
|
+
});
|
|
78
|
+
const p = () => {
|
|
79
|
+
const e = s.value?.$el?.parentElement;
|
|
80
|
+
if (e) {
|
|
81
|
+
const o = e.getBoundingClientRect(), a = o.width - 64, f = o.height - 64, C = Math.max(300, Math.min(600, Math.floor(a))), R = Math.max(200, Math.min(400, Math.floor(f)));
|
|
82
|
+
(C !== c.value || R !== d.value) && (c.value = C, d.value = R);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
return O(async () => {
|
|
86
|
+
await W(), p(), window.addEventListener("resize", p);
|
|
87
|
+
}), j(() => {
|
|
88
|
+
window.removeEventListener("resize", p);
|
|
89
|
+
}), (e, o) => (u(), g("div", P, [
|
|
90
|
+
t("div", A, [
|
|
91
|
+
t("div", K, [
|
|
92
|
+
t("div", Y, [
|
|
93
|
+
t("div", q, [
|
|
94
|
+
t("div", G, [
|
|
95
|
+
(u(), g(H, null, L([2, 5, 10, 20], (a) => t("button", {
|
|
96
|
+
key: a,
|
|
97
|
+
onClick: (f) => l.value = a,
|
|
98
|
+
class: S([
|
|
99
|
+
"w-8 h-8 rounded border-2 transition-colors",
|
|
100
|
+
l.value === a ? "border-blue-500 bg-blue-100" : "border-gray-300 bg-white hover:bg-gray-50"
|
|
101
|
+
])
|
|
102
|
+
}, [
|
|
103
|
+
t("div", {
|
|
104
|
+
class: S("bg-gray-800 rounded-full mx-auto"),
|
|
105
|
+
style: N({
|
|
106
|
+
width: Math.max(2, a * 1) + "px",
|
|
107
|
+
height: Math.max(2, a * 1) + "px"
|
|
108
|
+
})
|
|
109
|
+
}, null, 4)
|
|
110
|
+
], 10, J)), 64))
|
|
111
|
+
])
|
|
112
|
+
]),
|
|
113
|
+
t("div", Q, [
|
|
114
|
+
U(t("input", {
|
|
115
|
+
"onUpdate:modelValue": o[0] || (o[0] = (a) => i.value = a),
|
|
116
|
+
type: "color",
|
|
117
|
+
class: "w-12 h-8 rounded border border-gray-300"
|
|
118
|
+
}, null, 512), [
|
|
119
|
+
[V, i.value]
|
|
120
|
+
])
|
|
121
|
+
])
|
|
122
|
+
]),
|
|
123
|
+
t("div", { class: "flex items-center gap-1" }, [
|
|
124
|
+
t("button", {
|
|
125
|
+
onClick: D,
|
|
126
|
+
class: "w-8 h-8 flex items-center justify-center rounded border-2 border-gray-300 bg-white hover:bg-gray-50",
|
|
127
|
+
title: "Undo"
|
|
128
|
+
}, " ↩ "),
|
|
129
|
+
t("button", {
|
|
130
|
+
onClick: E,
|
|
131
|
+
class: "w-8 h-8 flex items-center justify-center rounded border-2 border-gray-300 bg-white hover:bg-gray-50",
|
|
132
|
+
title: "Redo"
|
|
133
|
+
}, " ↪ "),
|
|
134
|
+
t("button", {
|
|
135
|
+
onClick: F,
|
|
136
|
+
class: "w-8 h-8 flex items-center justify-center rounded border-2 border-red-300 bg-white hover:bg-red-50",
|
|
137
|
+
title: "Clear"
|
|
138
|
+
}, " 🗑 ")
|
|
139
|
+
])
|
|
140
|
+
])
|
|
141
|
+
]),
|
|
142
|
+
t("div", X, [
|
|
143
|
+
(u(), z(B(I), {
|
|
144
|
+
ref_key: "canvasRef",
|
|
145
|
+
ref: s,
|
|
146
|
+
key: `${v.selectedResult?.uuid || "default"}-${y.value}`,
|
|
147
|
+
image: x.value,
|
|
148
|
+
"onUpdate:image": o[1] || (o[1] = (a) => x.value = a),
|
|
149
|
+
width: c.value,
|
|
150
|
+
height: d.value,
|
|
151
|
+
"stroke-type": "dash",
|
|
152
|
+
"line-cap": "round",
|
|
153
|
+
"line-join": "round",
|
|
154
|
+
"fill-shape": !1,
|
|
155
|
+
eraser: !1,
|
|
156
|
+
lineWidth: l.value,
|
|
157
|
+
color: i.value,
|
|
158
|
+
"background-color": "#FFFFFF",
|
|
159
|
+
"background-image": void 0,
|
|
160
|
+
watermark: void 0,
|
|
161
|
+
"initial-image": m.value,
|
|
162
|
+
saveAs: "png",
|
|
163
|
+
styles: {
|
|
164
|
+
border: "1px solid #ddd",
|
|
165
|
+
borderRadius: "8px"
|
|
166
|
+
},
|
|
167
|
+
lock: !1,
|
|
168
|
+
onMouseup: k,
|
|
169
|
+
onTouchend: k
|
|
170
|
+
}, null, 8, ["image", "width", "height", "lineWidth", "color", "initial-image"]))
|
|
171
|
+
])
|
|
172
|
+
]));
|
|
173
|
+
}
|
|
174
|
+
}), ee = { class: "min-h-[100px] flex items-center justify-center" }, te = ["src"], ae = {
|
|
175
|
+
key: 1,
|
|
176
|
+
class: "text-gray-400 text-sm"
|
|
177
|
+
}, se = /* @__PURE__ */ M({
|
|
178
|
+
__name: "Preview",
|
|
179
|
+
props: {
|
|
180
|
+
result: {}
|
|
181
|
+
},
|
|
182
|
+
setup(v) {
|
|
183
|
+
return (b, r) => (u(), g("div", ee, [
|
|
184
|
+
v.result.data?.imageData ? (u(), g("img", {
|
|
185
|
+
key: 0,
|
|
186
|
+
src: v.result.data.imageData,
|
|
187
|
+
class: "max-w-full h-auto rounded",
|
|
188
|
+
alt: "Canvas drawing"
|
|
189
|
+
}, null, 8, te)) : (u(), g("div", ae, "No drawing yet"))
|
|
190
|
+
]));
|
|
191
|
+
}
|
|
192
|
+
}), oe = {
|
|
193
|
+
...$,
|
|
194
|
+
viewComponent: Z,
|
|
195
|
+
previewComponent: se
|
|
196
|
+
}, ie = { plugin: oe };
|
|
197
|
+
export {
|
|
198
|
+
se as Preview,
|
|
199
|
+
ue as SYSTEM_PROMPT,
|
|
200
|
+
ve as TOOL_DEFINITION,
|
|
201
|
+
he as TOOL_NAME,
|
|
202
|
+
Z as View,
|
|
203
|
+
ie as default,
|
|
204
|
+
ge as executeOpenCanvas,
|
|
205
|
+
oe as plugin,
|
|
206
|
+
$ as pluginCore
|
|
207
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gui-chat-plugin/canvas",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Drawing canvas plugin for GUIChat",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./core": {
|
|
16
|
+
"types": "./dist/core/index.d.ts",
|
|
17
|
+
"import": "./dist/core.js",
|
|
18
|
+
"require": "./dist/core.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./vue": {
|
|
21
|
+
"types": "./dist/vue/index.d.ts",
|
|
22
|
+
"import": "./dist/vue.js",
|
|
23
|
+
"require": "./dist/vue.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./style.css": "./dist/style.css"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"dev": "vite",
|
|
32
|
+
"build": "vite build && vue-tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
33
|
+
"typecheck": "vue-tsc --noEmit",
|
|
34
|
+
"lint": "eslint src demo"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"gui-chat-protocol": "^0.0.1",
|
|
38
|
+
"vue": "^3.5.0"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"vue-drawing-canvas": "^1.0.14"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@tailwindcss/vite": "^4.1.18",
|
|
45
|
+
"@typescript-eslint/eslint-plugin": "^8.53.0",
|
|
46
|
+
"@typescript-eslint/parser": "^8.53.0",
|
|
47
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
48
|
+
"eslint": "^9.39.2",
|
|
49
|
+
"eslint-plugin-vue": "^10.6.2",
|
|
50
|
+
"globals": "^17.0.0",
|
|
51
|
+
"gui-chat-protocol": "^0.0.1",
|
|
52
|
+
"tailwindcss": "^4.1.18",
|
|
53
|
+
"typescript": "~5.9.3",
|
|
54
|
+
"vite": "^7.3.1",
|
|
55
|
+
"vue": "^3.5.27",
|
|
56
|
+
"vue-eslint-parser": "^10.2.0",
|
|
57
|
+
"vue-tsc": "^3.2.2"
|
|
58
|
+
},
|
|
59
|
+
"keywords": [
|
|
60
|
+
"guichat",
|
|
61
|
+
"plugin",
|
|
62
|
+
"canvas",
|
|
63
|
+
"drawing"
|
|
64
|
+
],
|
|
65
|
+
"license": "MIT"
|
|
66
|
+
}
|