@automattic/jetpack-ai-client 0.1.0 → 0.1.2

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.
Files changed (32) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +18 -96
  3. package/index.ts +28 -1
  4. package/package.json +17 -4
  5. package/src/ask-question/Readme.md +1 -1
  6. package/src/ask-question/index.ts +21 -7
  7. package/src/components/ai-control/Readme.md +29 -0
  8. package/src/components/ai-control/index.tsx +165 -0
  9. package/src/components/ai-control/stories/index.stories.tsx +68 -0
  10. package/src/components/ai-control/style.scss +130 -0
  11. package/src/components/ai-status-indicator/Readme.md +11 -0
  12. package/src/components/ai-status-indicator/index.tsx +43 -0
  13. package/src/components/ai-status-indicator/stories/index.mdx +25 -0
  14. package/src/components/ai-status-indicator/stories/index.stories.tsx +84 -0
  15. package/src/components/ai-status-indicator/style.scss +50 -0
  16. package/src/data-flow/Readme.md +115 -0
  17. package/src/data-flow/context.tsx +76 -0
  18. package/src/data-flow/index.ts +3 -0
  19. package/src/data-flow/use-ai-context.ts +88 -0
  20. package/src/data-flow/with-ai-assistant-data.tsx +52 -0
  21. package/src/hooks/use-ai-suggestions/Readme.md +127 -0
  22. package/src/hooks/use-ai-suggestions/index.ts +358 -0
  23. package/src/icons/Readme.md +22 -0
  24. package/src/icons/ai-assistant.tsx +31 -0
  25. package/src/icons/index.ts +3 -0
  26. package/src/icons/origami-plane.tsx +20 -0
  27. package/src/icons/speak-tone.tsx +24 -0
  28. package/src/icons/stories/index.stories.tsx +46 -0
  29. package/src/icons/stories/style.module.scss +21 -0
  30. package/src/suggestions-event-source/index.ts +113 -15
  31. package/src/types.ts +48 -0
  32. package/src/index.js +0 -26
package/CHANGELOG.md CHANGED
@@ -5,6 +5,42 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.1.2] - 2023-08-07
9
+ ### Added
10
+ - AI Assistant: add options parameter to request function on useAiSuggestions hook [#32198]
11
+ - AI Client: add @wordpress/compose dependency [#32228]
12
+ - AI Client: add clear button in AI Control component [#32274]
13
+ - AI Client: add keyboard shortcut to AIControl [#32239]
14
+ - AI Client: add onError() response support [#32223]
15
+ - AI Client: export types [#32209]
16
+ - AI Client: start supporting request options on requestSuggestion callback. [#32303]
17
+ - AI Control: introduce AiStatusIndicator component [#32258]
18
+
19
+ ### Changed
20
+ - AI Client: complete/update/improve doc [#32311]
21
+ - AI Client: rename the prop name of the requesting state of the AiStatusIndicator component [#32279]
22
+
23
+ ### Fixed
24
+ - AI Client: Fix wrong disabled state condition. [#32210]
25
+
26
+ ## [0.1.1] - 2023-08-01
27
+ ### Added
28
+ - Add AI Client icon components [#32079]
29
+ - AI Assistant: add function calling feature. [#32161]
30
+ - AI Client: add AI Assistant data context. [#32129]
31
+ - AI Client: add useAiContext() react hook. [#32145]
32
+ - AI Client: add useAiSuggestions() react custom hook. [#32022]
33
+ - AI Client: introduce AI Control component. [#32163]
34
+ - AI Client: introduce withAiDataProvider HOC. [#32142]
35
+
36
+ ### Changed
37
+ - AI Client: add Icon suffix to icon components. [#32173]
38
+ - AI Client: handle properly passing the post_id parameter to endpoint. [#32104]
39
+ - AI Client: replace using CSS modules with the regular way. [#32171]
40
+
41
+ ### Removed
42
+ - AI Client: remove unused image library [#32127]
43
+
8
44
  ## 0.1.0 - 2023-07-25
9
45
  ### Added
10
46
  - Add Jetpack AI Client [#30855]
@@ -17,3 +53,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
53
  - Updated package dependencies. [#31468]
18
54
  - Updated package dependencies. [#31659]
19
55
  - Updated package dependencies. [#31785]
56
+
57
+ [0.1.2]: https://github.com/Automattic/jetpack-ai-client/compare/v0.1.1...v0.1.2
58
+ [0.1.1]: https://github.com/Automattic/jetpack-ai-client/compare/v0.1.0...v0.1.1
package/README.md CHANGED
@@ -10,118 +10,40 @@ To install the Jetpack AI Client, clone the repository to your local machine and
10
10
  npm install @automattic/jetpack-ai-client
11
11
  ```
12
12
 
13
- ## Usage
13
+ ## Libraries & Components
14
14
 
15
- ### Example
15
+ ### Requesting
16
16
 
17
- ```
18
- import { requestCompletion } from '@automattic/jetpack-ai-client';
19
-
20
- const MyComp = ( props ) => {
21
- const [ completion, setCompletion ] = useState( '' );
22
-
23
- const newHaiku = async () => {
24
- const eventSource = await requestCompletion( 'Write a haiku about WordPress' );
25
- eventSource.addEventListener( 'suggestion', answer => setCompletion( answer.detail ) );
26
- eventSource.addEventListener( 'done', event => {
27
- console.log( "Full completion", event.detail );
28
- } );
29
-
30
- eventSource.addEventListener( 'suggestion', event => {
31
- console.log( "Received so far", event.detail );
32
- } );
33
-
34
- eventSource.addEventListener( 'error_quota_exceeded', event => {
35
- console.log( "You reached the AI query quota for your current plan.", event.detail );
36
- } );
37
- };
38
-
39
- return (
40
- <div>
41
- <div> { completion } </div>
42
- <button onClick={ newHaiku }>Get new Haiku</button>
43
- </div>
44
- )
45
- };
46
- ```
47
-
48
- ### Requesting a Completion from the Jetpack AI API
49
-
50
- You can request a completion from the Jetpack AI API using the `requestCompletion` function. This function takes a prompt and optionally a post ID as parameters and returns an instance of `SuggestionsEventSource`.
51
-
52
- ```
53
- import { requestCompletion } from '@automattic/jetpack-ai-client';
54
-
55
- // postId is the post where the request is being triggered
56
- // It's only used for loggin purposes and can be omitted.
57
- const postId = 123;
58
- const eventSource = requestCompletion( 'A haiku', postId ))
59
-
60
- eventSource.addEventListener('done', event => {
61
- console.log( "Full completion", event.detail );
62
- } );
63
-
64
- eventSource.addEventListener('suggestion', event => {
65
- console.log( "Received so far", event.detail );
66
- } );
67
- ```
17
+ #### [askQuestion](./src/ask-question/Readme.md) helper
18
+ Async function that sends a question and optional configurations, retrieves a JWT token, and returns a [SuggestionsEventSource](./src/suggestions-event-source/Readme.md) instance.
68
19
 
69
- ### Requesting Images from the Jetpack AI API
20
+ #### [SuggestionsEventSouce](./src/suggestions-event-source/Readme.md) Class
70
21
 
71
- You can fetch images from Jetpack AI using the `requestImages` function. This function takes a prompt and a post ID as parameters and returns a promise that resolves to an array of base64 encoded images.
22
+ Class that connects to an AI model to receive and emit suggestion streams, using EventTarget for handling data chunks.
72
23
 
73
- ```
74
- import { requestImages } from '@automattic/jetpack-ai-client';
75
-
76
- requestImages( 'a flower', postId )
77
- .then( images => {
78
- document.getElementById("imgid").src= image[0]
79
- } )
80
- .catch( error => {
81
- // Handle the error
82
- } );
83
- ```
84
-
85
- ### Using the SuggestionsEventSource Class
86
-
87
- The `SuggestionsEventSource` class is a wrapper around `EventSource` that emits events for each chunk of data received, when the stream is closed, and when a full suggestion has been received.
88
-
89
- You shouldn't need to instantiate this class. You get one of these by calling `requestCompletion()`.
24
+ #### [useAiSuggestions](./src/hooks/use-ai-suggestions/Readme.md) hook
90
25
 
91
- ```
92
- import { requestCompletion } from '@automattic/jetpack-ai-client';
26
+ A custom React hook that obtains suggestions from an AI by hitting a specific query endpoint.
93
27
 
94
- const eventSource = new SuggestionsEventSource( url );
28
+ #### [JWT](./src/jwt/Readme.md) helper
95
29
 
96
- eventSource.addEventListener( 'done', event => {
97
- console.log( "Full completion", event.detail );
98
- } );
30
+ Library to manage JWT tokens for Jetpack AI across various site types, handling acquisition, caching in localStorage, expiration, and customization of request options.
99
31
 
100
- eventSource.addEventListener( 'suggestion', event => {
101
- console.log( "Received so far", event.detail );
102
- } );
103
- ```
32
+ #### [Data Flow](./src/data-flow/Readme.md) implementation
104
33
 
105
- ### Requesting a Token from the Jetpack Site
34
+ Data Flow offers a streamlined way to manage an AI Assistant's state and functionality within a React app, using React context, HOCs, and custom hooks to handle suggestions, errors, and requests.
106
35
 
107
- You can request a token from the Jetpack site using the `requestCompletionAuthToken` function. This function returns a promise that resolves to an object containing the token and the blogId.
36
+ ### [Components](./src/components/)
108
37
 
109
- This function behaves properly whether it's called from a Jetpack environment or a WordPress.com one.
38
+ #### [AIControl](./src/components/ai-control/Readme.md)
110
39
 
111
- ```
112
- import { requestCompletionAuthToken } from '@automattic/jetpack-ai-client';
113
-
114
- requestCompletionAuthToken()
115
- .then(tokenData => {
116
- // Do something with the token data
117
- })
118
- .catch(error => {
119
- // Handle the error
120
- });
121
- ```
40
+ #### [AiStatusIndicator](./src/components/ai-status-indicator/)
122
41
 
42
+ ### [Icons](./src/icons/Readme.md)
123
43
  ## Contribute
124
44
 
45
+ React components useful for when you need to create some UI implementations.
46
+
125
47
  We welcome contributions from the community. Please submit your pull requests on the GitHub repository.
126
48
 
127
49
  ## Get Help
package/index.ts CHANGED
@@ -1,4 +1,31 @@
1
+ /*
2
+ * Core library exports
3
+ */
1
4
  export { default as requestJwt } from './src/jwt';
2
5
  export { default as SuggestionsEventSource } from './src/suggestions-event-source';
3
6
  export { default as askQuestion } from './src/ask-question';
4
- export * from './src/index.js';
7
+
8
+ /*
9
+ * Hooks
10
+ */
11
+ export { default as useAiSuggestions } from './src/hooks/use-ai-suggestions';
12
+
13
+ /*
14
+ * Components: Icons
15
+ */
16
+ export * from './src/icons';
17
+
18
+ /*
19
+ * Components
20
+ */
21
+ export { default as AIControl } from './src/components/ai-control';
22
+
23
+ /*
24
+ * Contexts
25
+ */
26
+ export * from './src/data-flow';
27
+
28
+ /*
29
+ * Types
30
+ */
31
+ export * from './src/types';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@automattic/jetpack-ai-client",
4
- "version": "0.1.0",
4
+ "version": "0.1.2",
5
5
  "description": "A JS client for consuming Jetpack AI services",
6
6
  "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/ai-client/#readme",
7
7
  "bugs": {
@@ -21,7 +21,10 @@
21
21
  },
22
22
  "type": "module",
23
23
  "devDependencies": {
24
- "jest": "*",
24
+ "@storybook/addon-actions": "7.1.0",
25
+ "@storybook/blocks": "7.1.0",
26
+ "@storybook/react": "7.1.0",
27
+ "jest": "^29.6.2",
25
28
  "jest-environment-jsdom": "29.5.0",
26
29
  "typescript": "5.0.4"
27
30
  },
@@ -30,9 +33,19 @@
30
33
  },
31
34
  "dependencies": {
32
35
  "@automattic/jetpack-connection": "workspace:*",
33
- "@automattic/jetpack-shared-extension-utils": "^0.10.9",
36
+ "@automattic/jetpack-shared-extension-utils": "^0.11.0",
34
37
  "@microsoft/fetch-event-source": "2.0.1",
35
38
  "@wordpress/api-fetch": "6.34.0",
36
- "debug": "4.3.4"
39
+ "@wordpress/block-editor": "12.5.0",
40
+ "@wordpress/components": "25.3.0",
41
+ "@wordpress/compose": "6.14.0",
42
+ "@wordpress/data": "9.7.0",
43
+ "@wordpress/element": "5.14.0",
44
+ "@wordpress/i18n": "4.37.0",
45
+ "@wordpress/icons": "9.28.0",
46
+ "classnames": "2.3.2",
47
+ "debug": "4.3.4",
48
+ "react": "18.2.0",
49
+ "react-dom": "18.2.0"
37
50
  }
38
51
  }
@@ -11,7 +11,7 @@ function askQuestion(
11
11
  ): Promise< SuggestionsEventSource >
12
12
  ```
13
13
 
14
- ## Parameters
14
+ <h2 id="ask-question-parameters">Parameters</h2>
15
15
 
16
16
  - `question` (**string** | **PromptItemProps[]**):
17
17
  - The question to ask.
@@ -7,9 +7,9 @@ import SuggestionsEventSource from '../suggestions-event-source';
7
7
  /*
8
8
  * Types & constants
9
9
  */
10
- import type { PromptItemProps } from '../types';
10
+ import type { PromptProp } from '../types';
11
11
 
12
- type AskQuestionOptionsArgProps = {
12
+ export type AskQuestionOptionsArgProps = {
13
13
  /*
14
14
  * ID of the post where the question is asked.
15
15
  */
@@ -24,6 +24,16 @@ type AskQuestionOptionsArgProps = {
24
24
  * Allows to use a specific AI assistant feature. Default value is undefined.
25
25
  */
26
26
  feature?: 'ai-assistant-experimental' | string | undefined;
27
+
28
+ /*
29
+ * Allows the use of function calling. Default value is undefined.
30
+ */
31
+ functions?: Array< {
32
+ name?: string;
33
+ arguments?: string;
34
+ // eslint-disable-next-line @typescript-eslint/ban-types
35
+ implementation?: Function;
36
+ } >;
27
37
  };
28
38
 
29
39
  const debug = debugFactory( 'jetpack-ai-client:ask-question' );
@@ -32,7 +42,7 @@ const debug = debugFactory( 'jetpack-ai-client:ask-question' );
32
42
  * An asynchronous function that asks a question
33
43
  * and returns an event source with suggestions.
34
44
  *
35
- * @param {string|PromptItemProps[]} question - The question to ask. It can be a simple string or an array of PromptItemProps objects.
45
+ * @param {PromptProp} question - The question to ask. It can be a simple string or an array of PromptMessageItemProps objects.
36
46
  * @param {AskQuestionOptionsArgProps} options - An optional object for additional configuration:
37
47
  * @returns {Promise<SuggestionsEventSource>} A promise that resolves to an instance of the SuggestionsEventSource
38
48
  * @example
@@ -47,12 +57,16 @@ const debug = debugFactory( 'jetpack-ai-client:ask-question' );
47
57
  * } );
48
58
  */
49
59
  export default async function askQuestion(
50
- question: string | PromptItemProps[],
51
- { postId = null, fromCache = false, feature }: AskQuestionOptionsArgProps = {}
60
+ question: PromptProp,
61
+ { postId = null, fromCache = false, feature, functions }: AskQuestionOptionsArgProps = {}
52
62
  ): Promise< SuggestionsEventSource > {
53
- debug( 'Asking question: %o. options: %o', question, { postId, fromCache, feature } );
63
+ debug( 'Asking question: %o. options: %o', question, { postId, fromCache, feature, functions } );
54
64
 
55
65
  const { token } = await requestJwt();
56
66
 
57
- return new SuggestionsEventSource( { question, token, options: { postId, feature, fromCache } } );
67
+ return new SuggestionsEventSource( {
68
+ question,
69
+ token,
70
+ options: { postId, feature, fromCache, functions },
71
+ } );
58
72
  }
@@ -0,0 +1,29 @@
1
+ ### AIControl
2
+
3
+ #### Properties
4
+
5
+ - `loading` (**boolean**) (Optional): Determines the loading state. Default value is `false`.
6
+ - `value` (**string**): Current input value. Default value is `''`.
7
+ - `placeholder` (**string**) (Optional): Placeholder text for the input field. Default value is `''`.
8
+ - `showAccept` (**boolean**) (Optional): Determines if the accept button is shown. Default value is `false`.
9
+ - `acceptLabel` (**string**) (Optional): Label text for the accept button. Default value is `'Accept'`.
10
+ - `showButtonsLabel` (**boolean**) (Optional): Determines if button labels are shown. Default value is `true`.
11
+ - `isOpaque` (**boolean**) (Optional): Controls the opacity of the component. Default value is `false`.
12
+ - `requestingState` (**RequestingStateProp**) (Optional): Determines the state of the request. Default value is `'init'`.
13
+ - `onChange` (**Function**) (Optional): Handler for input change. Default action is no operation.
14
+ - `onSend` (**Function**) (Optional): Handler to send a request. Default action is no operation.
15
+ - `onStop` (**Function**) (Optional): Handler to stop a request. Default action is no operation.
16
+ - `onAccept` (**Function**) (Optional): Handler to accept the input. Default action is no operation.
17
+
18
+ #### Example Usage
19
+
20
+ ```jsx
21
+ <AIControl
22
+ value="Type here"
23
+ placeholder="Placeholder text"
24
+ onChange={ handleChange }
25
+ onSend={ handleSend }
26
+ onStop={ handleStop }
27
+ onAccept={ handleAccept }
28
+ />
29
+ ```
@@ -0,0 +1,165 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { PlainText } from '@wordpress/block-editor';
5
+ import { Button } from '@wordpress/components';
6
+ import { useKeyboardShortcut } from '@wordpress/compose';
7
+ import { useRef } from '@wordpress/element';
8
+ import { __ } from '@wordpress/i18n';
9
+ import { Icon, closeSmall, check, arrowUp } from '@wordpress/icons';
10
+ import classNames from 'classnames';
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import './style.scss';
15
+ import AiStatusIndicator from '../ai-status-indicator';
16
+ /**
17
+ * Types
18
+ */
19
+ import type { RequestingStateProp } from '../../types';
20
+
21
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
22
+ const noop = () => {};
23
+
24
+ /**
25
+ * AI Control component.
26
+ *
27
+ * @param {object} props - component props
28
+ * @param {boolean} props.loading - loading state
29
+ * @param {string} props.value - input value
30
+ * @param {string} props.placeholder - input placeholder
31
+ * @param {boolean} props.showAccept - show accept button
32
+ * @param {string} props.acceptLabel - accept button label
33
+ * @param {boolean} props.showButtonsLabel - show buttons label
34
+ * @param {boolean} props.isOpaque - is opaque
35
+ * @param {Function} props.onChange - input change handler
36
+ * @param {Function} props.onSend - send request handler
37
+ * @param {Function} props.onStop - stop request handler
38
+ * @param {Function} props.onAccept - accept handler
39
+ * @param {string} props.requestingState - requesting state
40
+ * @returns {object} - AI Control component
41
+ */
42
+ export default function AIControl( {
43
+ loading = false,
44
+ value = '',
45
+ placeholder = '',
46
+ showAccept = false,
47
+ acceptLabel = __( 'Accept', 'jetpack-ai-client' ),
48
+ showButtonsLabel = true,
49
+ isOpaque = false,
50
+ requestingState = 'init',
51
+ onChange = noop,
52
+ onSend = noop,
53
+ onStop = noop,
54
+ onAccept = noop,
55
+ }: {
56
+ loading?: boolean;
57
+ value: string;
58
+ placeholder?: string;
59
+ showAccept?: boolean;
60
+ acceptLabel?: string;
61
+ showButtonsLabel?: boolean;
62
+ isOpaque?: boolean;
63
+ requestingState?: RequestingStateProp;
64
+ onChange?: ( newValue: string ) => void;
65
+ onSend?: ( currentValue: string ) => void;
66
+ onStop?: () => void;
67
+ onAccept?: () => void;
68
+ } ) {
69
+ const promptUserInputRef = useRef( null );
70
+
71
+ useKeyboardShortcut(
72
+ 'mod+enter',
73
+ () => {
74
+ if ( showAccept ) {
75
+ onAccept?.();
76
+ }
77
+ },
78
+ {
79
+ target: promptUserInputRef,
80
+ }
81
+ );
82
+
83
+ useKeyboardShortcut(
84
+ 'enter',
85
+ e => {
86
+ e.preventDefault();
87
+ onSend?.( value );
88
+ },
89
+ {
90
+ target: promptUserInputRef,
91
+ }
92
+ );
93
+
94
+ return (
95
+ <div className="jetpack-components-ai-control__container">
96
+ <div
97
+ className={ classNames( 'jetpack-components-ai-control__wrapper', {
98
+ 'is-opaque': isOpaque,
99
+ } ) }
100
+ >
101
+ <AiStatusIndicator state={ requestingState } />
102
+
103
+ <div className="jetpack-components-ai-control__input-wrapper">
104
+ <PlainText
105
+ value={ value }
106
+ onChange={ onChange }
107
+ placeholder={ placeholder }
108
+ className="jetpack-components-ai-control__input"
109
+ disabled={ loading }
110
+ ref={ promptUserInputRef }
111
+ />
112
+
113
+ { value?.length > 0 && (
114
+ <Icon
115
+ icon={ closeSmall }
116
+ className="jetpack-components-ai-control__clear"
117
+ onClick={ () => onChange( '' ) }
118
+ />
119
+ ) }
120
+ </div>
121
+
122
+ <div className="jetpack-components-ai-control__controls">
123
+ <div className="jetpack-components-ai-control__controls-prompt_button_wrapper">
124
+ { ! loading ? (
125
+ <Button
126
+ className="jetpack-components-ai-control__controls-prompt_button"
127
+ onClick={ () => onSend( value ) }
128
+ isSmall={ true }
129
+ disabled={ ! value?.length }
130
+ label={ __( 'Send request', 'jetpack-ai-client' ) }
131
+ >
132
+ <Icon icon={ arrowUp } />
133
+ { showButtonsLabel && __( 'Send', 'jetpack-ai-client' ) }
134
+ </Button>
135
+ ) : (
136
+ <Button
137
+ className="jetpack-components-ai-control__controls-prompt_button"
138
+ onClick={ onStop }
139
+ isSmall={ true }
140
+ label={ __( 'Stop request', 'jetpack-ai-client' ) }
141
+ >
142
+ <Icon icon={ closeSmall } />
143
+ { showButtonsLabel && __( 'Stop', 'jetpack-ai-client' ) }
144
+ </Button>
145
+ ) }
146
+ </div>
147
+
148
+ { showAccept && (
149
+ <div className="jetpack-components-ai-control__controls-prompt_button_wrapper">
150
+ <Button
151
+ className="jetpack-components-ai-control__controls-prompt_button"
152
+ onClick={ onAccept }
153
+ isSmall={ true }
154
+ label={ acceptLabel }
155
+ >
156
+ <Icon icon={ check } />
157
+ { acceptLabel }
158
+ </Button>
159
+ </div>
160
+ ) }
161
+ </div>
162
+ </div>
163
+ </div>
164
+ );
165
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { action } from '@storybook/addon-actions';
5
+ import { useState } from '@wordpress/element';
6
+ import React from 'react';
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import { REQUESTING_STATES } from '../../../types';
11
+ import AIControl from '../index';
12
+ /**
13
+ * Types
14
+ */
15
+ import type { Meta } from '@storybook/react';
16
+
17
+ export default {
18
+ title: 'JS Packages/AI Client/AI Control',
19
+ component: AIControl,
20
+ decorators: [
21
+ Story => (
22
+ <div style={ { backgroundColor: 'white' } }>
23
+ <Story />
24
+ </div>
25
+ ),
26
+ ],
27
+ argTypes: {
28
+ requestingState: {
29
+ control: {
30
+ type: 'select',
31
+ },
32
+ options: REQUESTING_STATES,
33
+ },
34
+ },
35
+ parameters: {
36
+ controls: {
37
+ exclude: /on[A-Z].*/,
38
+ },
39
+ },
40
+ } as Meta< typeof AIControl >;
41
+
42
+ const Template = args => {
43
+ const [ value, setValue ] = useState( '' );
44
+
45
+ const handleChange = ( newValue: string ) => {
46
+ setValue( newValue );
47
+ args?.onChange?.( newValue );
48
+ };
49
+
50
+ return <AIControl { ...args } onChange={ handleChange } value={ args?.value ?? value } />;
51
+ };
52
+
53
+ const DefaultArgs = {
54
+ loading: false,
55
+ isOpaque: false,
56
+ placeholder: '',
57
+ requestingState: 'init',
58
+ showButtonsLabel: true,
59
+ showAccept: false,
60
+ acceptLabel: 'Accept',
61
+ onChange: action( 'onChange' ),
62
+ onSend: action( 'onSend' ),
63
+ onStop: action( 'onStop' ),
64
+ onAccept: action( 'onAccept' ),
65
+ };
66
+
67
+ export const Default = Template.bind( {} );
68
+ Default.args = DefaultArgs;