diff --git a/.storybook/custom-element-manifests/ai.json b/.storybook/custom-element-manifests/ai.json new file mode 100644 index 00000000000..fd971af176c --- /dev/null +++ b/.storybook/custom-element-manifests/ai.json @@ -0,0 +1,635 @@ +{ + "schemaVersion": "1.0.0", + "readme": "", + "modules": [ + { + "kind": "javascript-module", + "path": "dist/Assets.js", + "declarations": [], + "exports": [] + }, + { + "kind": "javascript-module", + "path": "dist/Button.js", + "declarations": [ + { + "kind": "class", + "description": "### Overview\n\nThe `ui5-ai-button` component serves as a button for AI-related scenarios. Users can trigger actions by clicking or tapping the `ui5-ai-button`\nor by pressing keyboard keys like [Enter] or [Space].\n\n### Usage\n\nFor the `ui5-ai-button` user interface, you can define one or more button states by placing `ui5-ai-button-state` components in their default slot.\nEach state has a name for identification and can include text, an icon, and an end icon, as needed for its purpose.\nYou can define a split mode for the `ui5-ai-button`, which will results in displaying an arrow button for additional actions.\n\nYou can choose from a set of predefined designs for `ui5-ai-button` (as in `ui5-button`) to match the desired styling.\n\nThe `ui5-ai-button` can be activated by clicking or tapping it. You can change the button state in the click event handler. When the button is\nin split mode, you can activate the default button action by clicking or tapping it, or by pressing keyboard keys like [Enter] or [Space].\nYou can activate the arrow button by clicking or tapping it, or by pressing keyboard keys like [Arrow Up], [Arrow Down], or [F4].\nTo display additional actions, you can attach a menu to the arrow button.\n\n### ES6 Module Import\n\n`import \"@ui5/webcomponents-ai/dist/Button.js\";`", + "name": "Button", + "slots": [ + { + "name": "default", + "description": "Defines the available states of the component.\n**Note:** Although this slot accepts HTML Elements, it is strongly recommended that\nyou only use `ui5-ai-button-state` components in order to preserve the intended design.", + "_ui5propertyName": "states", + "_ui5type": { + "text": "Array", + "references": [ + { + "name": "ButtonState", + "package": "@ui5/webcomponents-ai", + "module": "dist/ButtonState.js" + } + ] + }, + "_ui5privacy": "public" + } + ], + "members": [ + { + "kind": "field", + "name": "design", + "type": { + "text": "ButtonDesign | undefined", + "references": [ + { + "name": "ButtonDesign", + "package": "@ui5/webcomponents", + "module": "dist/types/ButtonDesign.js" + } + ] + }, + "default": "\"Default\"", + "description": "Defines the component design.", + "privacy": "public" + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Defines whether the component is disabled.\nA disabled component can't be pressed or\nfocused, and it is not in the tab chain.", + "privacy": "public" + }, + { + "kind": "field", + "name": "state", + "type": { + "text": "string | undefined" + }, + "description": "Defines the current state of the component.", + "default": "undefined", + "privacy": "public" + }, + { + "kind": "field", + "name": "arrowButtonPressed", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Defines the active state of the arrow button in split mode.\nSet to true when the button is in split mode and a menu with additional options\nis opened by the arrow button. Set back to false when the menu is closed.", + "privacy": "public", + "_ui5since": "2.6.0", + "_ui5noAttribute": true + } + ], + "events": [ + { + "name": "click", + "_ui5privacy": "public", + "type": { + "text": "CustomEvent" + }, + "description": "Fired when the component is activated either with a\nmouse/tap or by using the Enter or Space key.", + "_ui5Cancelable": false, + "_ui5allowPreventDefault": false, + "_ui5Bubbles": true + }, + { + "name": "arrow-button-click", + "_ui5privacy": "public", + "type": { + "text": "CustomEvent" + }, + "description": "Fired when the component is in split mode and after the arrow button\nis activated either by clicking or tapping it or by using the [Arrow Up] / [Arrow Down],\n[Alt] + [Arrow Up]/ [Arrow Down], or [F4] keyboard keys.", + "_ui5Cancelable": false, + "_ui5allowPreventDefault": false, + "_ui5Bubbles": true + } + ], + "attributes": [ + { + "description": "Defines the component design.", + "name": "design", + "default": "\"Default\"", + "fieldName": "design", + "type": { + "text": "\"Default\" | \"Positive\" | \"Negative\" | \"Transparent\" | \"Emphasized\" | \"Attention\" | undefined" + } + }, + { + "description": "Defines whether the component is disabled.\nA disabled component can't be pressed or\nfocused, and it is not in the tab chain.", + "name": "disabled", + "default": "false", + "fieldName": "disabled", + "type": { + "text": "boolean" + } + }, + { + "description": "Defines the current state of the component.", + "name": "state", + "default": "undefined", + "fieldName": "state", + "type": { + "text": "string | undefined" + } + }, + { + "description": "Defines the active state of the arrow button in split mode.\nSet to true when the button is in split mode and a menu with additional options\nis opened by the arrow button. Set back to false when the menu is closed.", + "name": "arrow-button-pressed", + "default": "false", + "fieldName": "arrowButtonPressed", + "type": { + "text": "boolean" + } + } + ], + "superclass": { + "name": "UI5Element", + "package": "@ui5/webcomponents-base", + "module": "dist/UI5Element.js" + }, + "tagName": "ui5-ai-button", + "customElement": true, + "_ui5experimental": "The Button and ButtonState web components are availabe since 2.0 under an experimental flag and their API and behaviour are subject to change.", + "_ui5since": "2.0.0", + "_ui5privacy": "public" + } + ], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "name": "Button", + "module": "dist/Button.js" + } + }, + { + "kind": "custom-element-definition", + "name": "ui5-ai-button", + "declaration": { + "name": "Button", + "module": "dist/Button.js" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "dist/ButtonState.js", + "declarations": [ + { + "kind": "class", + "description": "### Overview\n\n`ui5-ai-button-state` is the item to use for defining states of `ui5-ai-button` components.\n\n### Usage\n\n`ui5-si-button-state` is an abstract element, representing a state of `ui5-ai-button`. It is meant to be used in the `states` slot\nof `ui5-ai-button` and should be used as standalone component.\n\n### ES6 Module Import\n\n`import \"@ui5/webcomponents/dist/AiButtonState.js\";`", + "name": "ButtonState", + "members": [ + { + "kind": "field", + "name": "name", + "type": { + "text": "string | undefined" + }, + "description": "Defines the name of the button state.", + "default": "undefined", + "privacy": "public" + }, + { + "kind": "field", + "name": "text", + "type": { + "text": "string | undefined" + }, + "description": "Defines the text of the button in this state.", + "default": "undefined", + "privacy": "public" + }, + { + "kind": "field", + "name": "icon", + "type": { + "text": "string | undefined" + }, + "description": "Defines the icon to be displayed as graphical element within the component before the text.\nThe SAP-icons font provides numerous options.\n\n**Example:**\n\nSee all the available icons in the [Icon Explorer](https://sdk.openui5.org/test-resources/sap/m/demokit/iconExplorer/webapp/index.html).", + "default": "undefined", + "privacy": "public" + }, + { + "kind": "field", + "name": "endIcon", + "type": { + "text": "string | undefined" + }, + "description": "Defines the icon to be displayed as graphical element within the component after the text.\nThe SAP-icons font provides numerous options.\n\n**Example:**\n\nSee all the available icons in the [Icon Explorer](https://sdk.openui5.org/test-resources/sap/m/demokit/iconExplorer/webapp/index.html).", + "default": "undefined", + "privacy": "public" + }, + { + "kind": "field", + "name": "showArrowButton", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Defines if the component is in split button mode.", + "privacy": "public", + "_ui5since": "2.6.0" + } + ], + "attributes": [ + { + "description": "Defines the name of the button state.", + "name": "name", + "default": "undefined", + "fieldName": "name", + "type": { + "text": "string | undefined" + } + }, + { + "description": "Defines the text of the button in this state.", + "name": "text", + "default": "undefined", + "fieldName": "text", + "type": { + "text": "string | undefined" + } + }, + { + "description": "Defines the icon to be displayed as graphical element within the component before the text.\nThe SAP-icons font provides numerous options.\n\n**Example:**\n\nSee all the available icons in the [Icon Explorer](https://sdk.openui5.org/test-resources/sap/m/demokit/iconExplorer/webapp/index.html).", + "name": "icon", + "default": "undefined", + "fieldName": "icon", + "type": { + "text": "string | undefined" + } + }, + { + "description": "Defines the icon to be displayed as graphical element within the component after the text.\nThe SAP-icons font provides numerous options.\n\n**Example:**\n\nSee all the available icons in the [Icon Explorer](https://sdk.openui5.org/test-resources/sap/m/demokit/iconExplorer/webapp/index.html).", + "name": "end-icon", + "default": "undefined", + "fieldName": "endIcon", + "type": { + "text": "string | undefined" + } + }, + { + "description": "Defines if the component is in split button mode.", + "name": "show-arrow-button", + "default": "false", + "fieldName": "showArrowButton", + "type": { + "text": "boolean" + } + } + ], + "superclass": { + "name": "UI5Element", + "package": "@ui5/webcomponents-base", + "module": "dist/UI5Element.js" + }, + "tagName": "ui5-ai-button-state", + "customElement": true, + "_ui5experimental": "The Button and ButtonState web components are availabe since 2.0 under an experimental flag and their API and behaviour are subject to change.", + "_ui5since": "2.0.0", + "_ui5privacy": "public", + "_ui5abstract": true + } + ], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "name": "ButtonState", + "module": "dist/ButtonState.js" + } + }, + { + "kind": "custom-element-definition", + "name": "ui5-ai-button-state", + "declaration": { + "name": "ButtonState", + "module": "dist/ButtonState.js" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "dist/PromptInput.js", + "declarations": [ + { + "kind": "class", + "description": "### Overview\n\nThe `ui5-ai-prompt-input` component allows the user to write custom instructions in natural language, so that AI is guided to generate content tailored to user needs.\n\n**Note:** The web component is in an experimental state\n\n### ES6 Module Import\n\n`import \"@ui5/webcomponents-ai/dist/PromptInput.js", + "name": "PromptInput", + "slots": [ + { + "name": "default", + "description": "Defines the suggestion items.\n\n**Note:** The suggestions would be displayed only if the `showSuggestions`\nproperty is set to `true`.\n\n**Note:** The ``, `` and `ui5-suggestion-item-custom` are recommended to be used as suggestion items.", + "_ui5propertyName": "suggestionItems", + "_ui5type": { + "text": "Array", + "references": [ + { + "name": "IInputSuggestionItem", + "package": "@ui5/webcomponents", + "module": "dist/Input.js" + } + ] + }, + "_ui5privacy": "public" + }, + { + "name": "valueStateMessage", + "description": "Defines the value state message that will be displayed as pop up under the component.\nThe value state message slot should contain only one root element.\n\n**Note:** If not specified, a default text (in the respective language) will be displayed.\n\n**Note:** The `valueStateMessage` would be displayed,\nwhen the component is in `Information`, `Critical` or `Negative` value state.", + "_ui5since": "2.0.0", + "_ui5type": { + "text": "Array" + }, + "_ui5privacy": "public" + } + ], + "members": [ + { + "kind": "field", + "name": "value", + "type": { + "text": "string" + }, + "default": "\"\"", + "description": "Defines the value of the component.", + "privacy": "public", + "_ui5since": "2.0.0" + }, + { + "kind": "field", + "name": "placeholder", + "type": { + "text": "string | undefined" + }, + "description": "Defines a short hint intended to aid the user with data entry when the\ncomponent has no value.", + "default": "undefined", + "privacy": "public", + "_ui5since": "2.0.0" + }, + { + "kind": "field", + "name": "label", + "type": { + "text": "string | undefined" + }, + "description": "Defines the label of the input field.", + "default": "undefined", + "privacy": "public", + "_ui5since": "2.0.0" + }, + { + "kind": "field", + "name": "showClearIcon", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Defines whether the clear icon of the input will be shown.", + "privacy": "public", + "_ui5since": "2.0.0" + }, + { + "kind": "field", + "name": "showExceededText", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Determines whether the characters exceeding the maximum allowed character count are visible\nin the component.\n\nIf set to `false`, the user is not allowed to enter more characters than what is set in the\n`maxlength` property.\nIf set to `true` the characters exceeding the `maxlength` value are selected on\npaste and the counter below the component displays their number.", + "privacy": "public", + "_ui5since": "2.0.0" + }, + { + "kind": "field", + "name": "disabled", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Defines whether the component is in disabled state.\n\n**Note:** A disabled component is completely noninteractive.", + "privacy": "public", + "_ui5since": "2.0.0" + }, + { + "kind": "field", + "name": "readonly", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Defines whether the component is read-only.\n\n**Note:** A read-only component is not editable,\nbut still provides visual feedback upon user interaction.", + "privacy": "public", + "_ui5since": "2.0.0" + }, + { + "kind": "field", + "name": "maxlength", + "type": { + "text": "number | undefined" + }, + "description": "Sets the maximum number of characters available in the input field.", + "default": "undefined", + "privacy": "public", + "_ui5since": "2.0.0" + }, + { + "kind": "field", + "name": "valueState", + "type": { + "text": "ValueState", + "references": [ + { + "name": "ValueState", + "package": "@ui5/webcomponents-base", + "module": "dist/types/ValueState.js" + } + ] + }, + "default": "\"None\"", + "description": "Defines the value state of the component.", + "privacy": "public", + "_ui5since": "2.0.0" + }, + { + "kind": "field", + "name": "showSuggestions", + "type": { + "text": "boolean" + }, + "default": "false", + "description": "Defines whether the component should show suggestions, if such are present.", + "privacy": "public" + } + ], + "events": [ + { + "name": "submit", + "_ui5privacy": "public", + "type": { + "text": "CustomEvent" + }, + "description": "Fired when the input operation has finished by pressing Enter\nor AI button is clicked.", + "_ui5Cancelable": false, + "_ui5allowPreventDefault": false, + "_ui5Bubbles": true, + "_ui5since": "2.0.0" + }, + { + "name": "input", + "_ui5privacy": "public", + "type": { + "text": "CustomEvent" + }, + "description": "Fired when the value of the component changes at each keystroke,\nand when a suggestion item has been selected.", + "_ui5Cancelable": false, + "_ui5allowPreventDefault": false, + "_ui5Bubbles": true, + "_ui5since": "2.0.0" + }, + { + "name": "change", + "_ui5privacy": "public", + "type": { + "text": "CustomEvent" + }, + "description": "Fired when the input operation has finished by pressing Enter\nor on focusout.", + "_ui5Cancelable": false, + "_ui5allowPreventDefault": false, + "_ui5Bubbles": true, + "_ui5since": "2.0.0" + } + ], + "attributes": [ + { + "description": "Defines the value of the component.", + "name": "value", + "default": "\"\"", + "fieldName": "value", + "type": { + "text": "string" + } + }, + { + "description": "Defines a short hint intended to aid the user with data entry when the\ncomponent has no value.", + "name": "placeholder", + "default": "undefined", + "fieldName": "placeholder", + "type": { + "text": "string | undefined" + } + }, + { + "description": "Defines the label of the input field.", + "name": "label", + "default": "undefined", + "fieldName": "label", + "type": { + "text": "string | undefined" + } + }, + { + "description": "Defines whether the clear icon of the input will be shown.", + "name": "show-clear-icon", + "default": "false", + "fieldName": "showClearIcon", + "type": { + "text": "boolean" + } + }, + { + "description": "Determines whether the characters exceeding the maximum allowed character count are visible\nin the component.\n\nIf set to `false`, the user is not allowed to enter more characters than what is set in the\n`maxlength` property.\nIf set to `true` the characters exceeding the `maxlength` value are selected on\npaste and the counter below the component displays their number.", + "name": "show-exceeded-text", + "default": "false", + "fieldName": "showExceededText", + "type": { + "text": "boolean" + } + }, + { + "description": "Defines whether the component is in disabled state.\n\n**Note:** A disabled component is completely noninteractive.", + "name": "disabled", + "default": "false", + "fieldName": "disabled", + "type": { + "text": "boolean" + } + }, + { + "description": "Defines whether the component is read-only.\n\n**Note:** A read-only component is not editable,\nbut still provides visual feedback upon user interaction.", + "name": "readonly", + "default": "false", + "fieldName": "readonly", + "type": { + "text": "boolean" + } + }, + { + "description": "Sets the maximum number of characters available in the input field.", + "name": "maxlength", + "default": "undefined", + "fieldName": "maxlength", + "type": { + "text": "number | undefined" + } + }, + { + "description": "Defines the value state of the component.", + "name": "value-state", + "default": "\"None\"", + "fieldName": "valueState", + "type": { + "text": "\"Positive\" | \"Negative\" | \"None\" | \"Critical\" | \"Information\"" + } + }, + { + "description": "Defines whether the component should show suggestions, if such are present.", + "name": "show-suggestions", + "default": "false", + "fieldName": "showSuggestions", + "type": { + "text": "boolean" + } + } + ], + "superclass": { + "name": "UI5Element", + "package": "@ui5/webcomponents-base", + "module": "dist/UI5Element.js" + }, + "tagName": "ui5-ai-prompt-input", + "customElement": true, + "_ui5experimental": "The **@ui5/webcomponents-ai** package is under development and considered experimental - components' APIs are subject to change.", + "_ui5privacy": "public" + } + ], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "name": "PromptInput", + "module": "dist/PromptInput.js" + } + }, + { + "kind": "custom-element-definition", + "name": "ui5-ai-prompt-input", + "declaration": { + "name": "PromptInput", + "module": "dist/PromptInput.js" + } + } + ] + } + ] +} diff --git a/.storybook/main.ts b/.storybook/main.ts index 9e4ec0e49f9..dbb00f232a9 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -60,6 +60,11 @@ const config: StorybookConfig = { }, '../packages/main/**/*.mdx', '../packages/main/**/*.stories.@(tsx|jsx)', + { + directory: '../packages/ai', + files: '**/*.@(mdx|stories.@(mdx|js|jsx|mjs|ts|tsx))', + titlePrefix: 'AI' + }, { directory: '../packages/compat', files: '**/*.@(mdx|stories.@(mdx|js|jsx|mjs|ts|tsx))', diff --git a/.storybook/manager-head.html b/.storybook/manager-head.html index b1b4f5a185e..5c0fffe870e 100644 --- a/.storybook/manager-head.html +++ b/.storybook/manager-head.html @@ -52,6 +52,8 @@ } /*experimental components */ + #ai-promptinput::after, + #ai-button::after, #data-display-table::after, #inputs-tokenizer::after, #modals-popovers-usermenu::after, diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 8c3ac6cd1ca..5f043684b25 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -149,6 +149,8 @@ const preview: Preview = { 'Layouts & Floorplans', 'Modals & Popovers', 'User Feedback', + 'AI', + ['Docs'], 'Legacy Components' ] } diff --git a/.storybook/utils.ts b/.storybook/utils.ts index 8313c3b4596..5c818e46027 100644 --- a/.storybook/utils.ts +++ b/.storybook/utils.ts @@ -1,6 +1,8 @@ import { DocsContext } from '@storybook/blocks'; import { useContext, useMemo } from 'react'; // @ts-expect-error: storybook can handle this +import cemAi from './custom-element-manifests/ai.json'; +// @ts-expect-error: storybook can handle this import cemFiori from './custom-element-manifests/fiori.json'; // @ts-expect-error: storybook can handle this import cemMain from './custom-element-manifests/main.json'; @@ -16,10 +18,6 @@ export const MAPPED_THEMES = [ { value: 'sap_fiori_3_dark', title: 'Quartz Dark' }, { value: 'sap_fiori_3_hcb', title: 'Quartz High Contrast Black' }, { value: 'sap_fiori_3_hcw', title: 'Quartz High Contrast White' } - // deprecated - // { value: 'sap_belize', title: 'Belize' }, - // { value: 'sap_belize_hcb', title: 'Belize High Contrast Black' }, - // { value: 'sap_belize_hcw', title: 'Belize High Contrast White' } ]; export const excludePropsForAbstract = ['className', 'style']; @@ -50,6 +48,8 @@ export function useGetCem() { return cemMain; case 'package:@ui5/webcomponents-fiori': return cemFiori; + case 'package:@ui5/webcomponents-ai': + return cemAi; } } diff --git a/README.md b/README.md index b0ff3b518fb..acb4ee4fcb6 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,10 @@ You can find our documentation under the following links: [![](https://badgen.net/npm/v/@ui5/webcomponents-cypress-commands?icon=npm)](https://www.npmjs.com/package/@ui5/webcomponents-cypress-commands) +- [@ui5/webcomponents-ai-react](https://github.com/SAP/ui5-webcomponents-react/tree/main/packages/ai) - React wrapper for the `@ui5/webcomponents-ai` Package + + [![](https://badgen.net/npm/v/@ui5/webcomponents-ai-react?icon=npm)](https://www.npmjs.com/package/@ui5/webcomponents-ai-react) + diff --git a/docs/ReadMeAI.mdx b/docs/ReadMeAI.mdx new file mode 100644 index 00000000000..c42fff0c953 --- /dev/null +++ b/docs/ReadMeAI.mdx @@ -0,0 +1,11 @@ +import { Footer, TableOfContent } from '@sb/components'; +import { Markdown, Meta } from '@storybook/blocks'; +import ReadMe from '../packages/ai/README.md?raw'; + + + + + +{ReadMe.split('## Documentation')[0].trim()} + +