Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add ai package #192

Merged
merged 1 commit into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/documentation/api-json.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export default {
sources: [
'@ui5/webcomponents-base/dist/custom-elements-internal.json',
'@ui5/webcomponents-fiori/dist/custom-elements-internal.json',
'@ui5/webcomponents/dist/custom-elements-internal.json'
'@ui5/webcomponents/dist/custom-elements-internal.json',
'@ui5/webcomponents-ai/dist/custom-elements-internal.json'
]
}),
transformers: [
Expand Down
2 changes: 1 addition & 1 deletion apps/documentation/src/api-json.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,17 @@ export class ComponentFile extends AngularGeneratedFile {
}

private initializeImportsAndExports(): void {

let exportedName = this.componentClassName;

if ( this.componentData.path.includes('/ai/') ) {
console.warn('exportedName: ', exportedName);
exportedName = `Ai${this.componentClassName}`;

}
this.addExport({
local: this.componentClassName,
exported: this.componentClassName,
exported: exportedName,
types: [ExportSpecifierType.Class, AngularExportSpecifierType.NgModule]
})
this.addImport(['Component', 'ElementRef', 'NgZone', 'ChangeDetectorRef', 'booleanAttribute', 'Input as InputDecorator', 'inject'], '@angular/core');
Expand Down
1 change: 1 addition & 0 deletions libs/transformer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"license": "Apache-2.0",
"peerDependencies": {
"@ui5/webcomponents": "2.7.2",
"@ui5/webcomponents-ai": "2.7.2",
"@ui5/webcomponents-base": "2.7.2",
"@ui5/webcomponents-fiori": "2.7.2",
"@ui5/webcomponents-icons": "2.7.2",
Expand Down
11 changes: 8 additions & 3 deletions libs/transformer/src/lib/generated-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ export abstract class GeneratedFile<ExportsType = unknown> {
typeof path === 'function' ? path(this.relativePathCaller) : path;
const isSelfExport =
relativePath === this.relativePathFrom(this.relativePathCaller);
const shouldRename = relativePath.includes('/ai/') && !relativePath.includes('/ai/theming');

const uniqueSpecifiers = Object.values(
specifiers.reduce(
(
Expand All @@ -226,9 +228,12 @@ export abstract class GeneratedFile<ExportsType = unknown> {
typeof specifier.local === 'string'
? specifier.local
: specifier.local();
if (!acc[exportedName]) {
acc[exportedName] = {
exported: exportedName,

const finalExportedName = shouldRename ? `Ai${exportedName}` : exportedName;

if (!acc[finalExportedName]) {
acc[finalExportedName] = {
exported: finalExportedName,
local: localName,
};
}
Expand Down
66 changes: 66 additions & 0 deletions libs/ui5-angular/ai/button-state/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {
ChangeDetectorRef,
Component,
ElementRef,
Input as InputDecorator,
NgZone,
booleanAttribute,
inject,
} from '@angular/core';
import '@ui5/webcomponents-ai/dist/ButtonState.js';
import ButtonState from '@ui5/webcomponents-ai/dist/ButtonState.js';
import { ProxyInputs } from '@ui5/webcomponents-ngx/utils';
@ProxyInputs(['name', 'text', 'icon', 'endIcon', 'showArrowButton'])
@Component({
standalone: true,
selector: 'ui5-ai-button-state',
template: '<ng-content></ng-content>',
inputs: ['name', 'text', 'icon', 'endIcon', 'showArrowButton'],
exportAs: 'ui5AiButtonState',
})
class ButtonStateComponent {
/**
Defines the name of the button state.
*/
name!: string | undefined;
/**
Defines the text of the button in this state.
*/
text!: string | undefined;
/**
Defines the icon to be displayed as graphical element within the component before the text.
The SAP-icons font provides numerous options.

**Example:**

See all the available icons in the [Icon Explorer](https://sdk.openui5.org/test-resources/sap/m/demokit/iconExplorer/webapp/index.html).
*/
icon!: string | undefined;
/**
Defines the icon to be displayed as graphical element within the component after the text.
The SAP-icons font provides numerous options.

**Example:**

See all the available icons in the [Icon Explorer](https://sdk.openui5.org/test-resources/sap/m/demokit/iconExplorer/webapp/index.html).
*/
endIcon!: string | undefined;
/**
Defines if the component is in split button mode.
*/
@InputDecorator({ transform: booleanAttribute })
showArrowButton!: boolean;

private elementRef: ElementRef<ButtonState> = inject(ElementRef);
private zone = inject(NgZone);
private cdr = inject(ChangeDetectorRef);

get element(): ButtonState {
return this.elementRef.nativeElement;
}

constructor() {
this.cdr.detach();
}
}
export { ButtonStateComponent };
1 change: 1 addition & 0 deletions libs/ui5-angular/ai/button-state/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"lib":{"entryFile":"./index.ts"}}
79 changes: 79 additions & 0 deletions libs/ui5-angular/ai/button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
Input as InputDecorator,
NgZone,
booleanAttribute,
inject,
} from '@angular/core';
import '@ui5/webcomponents-ai/dist/Button.js';
import Button from '@ui5/webcomponents-ai/dist/Button.js';
import { ProxyInputs, ProxyOutputs } from '@ui5/webcomponents-ngx/utils';
@ProxyInputs(['design', 'disabled', 'state', 'arrowButtonPressed'])
@ProxyOutputs(['click: ui5Click', 'arrow-button-click: ui5ArrowButtonClick'])
@Component({
standalone: true,
selector: 'ui5-ai-button',
template: '<ng-content></ng-content>',
inputs: ['design', 'disabled', 'state', 'arrowButtonPressed'],
outputs: ['ui5Click', 'ui5ArrowButtonClick'],
exportAs: 'ui5AiButton',
})
class ButtonComponent {
/**
Defines the component design.
*/
design!:
| 'Default'
| 'Positive'
| 'Negative'
| 'Transparent'
| 'Emphasized'
| 'Attention'
| undefined;
/**
Defines whether the component is disabled.
A disabled component can't be pressed or
focused, and it is not in the tab chain.
*/
@InputDecorator({ transform: booleanAttribute })
disabled!: boolean;
/**
Defines the current state of the component.
*/
state!: string | undefined;
/**
Defines the active state of the arrow button in split mode.
Set to true when the button is in split mode and a menu with additional options
is opened by the arrow button. Set back to false when the menu is closed.
*/
@InputDecorator({ transform: booleanAttribute })
arrowButtonPressed!: boolean;

/**
Fired when the component is activated either with a
mouse/tap or by using the Enter or Space key.
*/
ui5Click!: EventEmitter<void>;
/**
Fired when the component is in split mode and after the arrow button
is activated either by clicking or tapping it or by using the [Arrow Up] / [Arrow Down],
[Alt] + [Arrow Up]/ [Arrow Down], or [F4] keyboard keys.
*/
ui5ArrowButtonClick!: EventEmitter<void>;

private elementRef: ElementRef<Button> = inject(ElementRef);
private zone = inject(NgZone);
private cdr = inject(ChangeDetectorRef);

get element(): Button {
return this.elementRef.nativeElement;
}

constructor() {
this.cdr.detach();
}
}
export { ButtonComponent };
1 change: 1 addition & 0 deletions libs/ui5-angular/ai/button/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"lib":{"entryFile":"./index.ts"}}
1 change: 1 addition & 0 deletions libs/ui5-angular/ai/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Ui5AiModule } from './ui5-ai.module';
1 change: 1 addition & 0 deletions libs/ui5-angular/ai/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"lib":{"entryFile":"./index.ts"}}
133 changes: 133 additions & 0 deletions libs/ui5-angular/ai/prompt-input/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import {
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
Input as InputDecorator,
NgZone,
booleanAttribute,
inject,
} from '@angular/core';
import '@ui5/webcomponents-ai/dist/PromptInput.js';
import PromptInput from '@ui5/webcomponents-ai/dist/PromptInput.js';
import { ProxyInputs, ProxyOutputs } from '@ui5/webcomponents-ngx/utils';
@ProxyInputs([
'value',
'placeholder',
'label',
'showClearIcon',
'showExceededText',
'disabled',
'readonly',
'maxlength',
'valueState',
'showSuggestions',
])
@ProxyOutputs(['submit: ui5Submit', 'input: ui5Input', 'change: ui5Change'])
@Component({
standalone: true,
selector: 'ui5-ai-prompt-input',
template: '<ng-content></ng-content>',
inputs: [
'value',
'placeholder',
'label',
'showClearIcon',
'showExceededText',
'disabled',
'readonly',
'maxlength',
'valueState',
'showSuggestions',
],
outputs: ['ui5Submit', 'ui5Input', 'ui5Change'],
exportAs: 'ui5AiPromptInput',
})
class PromptInputComponent {
/**
Defines the value of the component.
*/
value!: string;
/**
Defines a short hint intended to aid the user with data entry when the
component has no value.
*/
placeholder!: string | undefined;
/**
Defines the label of the input field.
*/
label!: string | undefined;
/**
Defines whether the clear icon of the input will be shown.
*/
@InputDecorator({ transform: booleanAttribute })
showClearIcon!: boolean;
/**
Determines whether the characters exceeding the maximum allowed character count are visible
in the component.

If set to `false`, the user is not allowed to enter more characters than what is set in the
`maxlength` property.
If set to `true` the characters exceeding the `maxlength` value are selected on
paste and the counter below the component displays their number.
*/
@InputDecorator({ transform: booleanAttribute })
showExceededText!: boolean;
/**
Defines whether the component is in disabled state.

**Note:** A disabled component is completely noninteractive.
*/
@InputDecorator({ transform: booleanAttribute })
disabled!: boolean;
/**
Defines whether the component is read-only.

**Note:** A read-only component is not editable,
but still provides visual feedback upon user interaction.
*/
@InputDecorator({ transform: booleanAttribute })
readonly!: boolean;
/**
Sets the maximum number of characters available in the input field.
*/
maxlength!: number | undefined;
/**
Defines the value state of the component.
*/
valueState!: 'None' | 'Positive' | 'Critical' | 'Negative' | 'Information';
/**
Defines whether the component should show suggestions, if such are present.
*/
@InputDecorator({ transform: booleanAttribute })
showSuggestions!: boolean;

/**
Fired when the input operation has finished by pressing Enter
or AI button is clicked.
*/
ui5Submit!: EventEmitter<void>;
/**
Fired when the value of the component changes at each keystroke,
and when a suggestion item has been selected.
*/
ui5Input!: EventEmitter<void>;
/**
Fired when the input operation has finished by pressing Enter
or on focusout.
*/
ui5Change!: EventEmitter<void>;

private elementRef: ElementRef<PromptInput> = inject(ElementRef);
private zone = inject(NgZone);
private cdr = inject(ChangeDetectorRef);

get element(): PromptInput {
return this.elementRef.nativeElement;
}

constructor() {
this.cdr.detach();
}
}
export { PromptInputComponent };
1 change: 1 addition & 0 deletions libs/ui5-angular/ai/prompt-input/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"lib":{"entryFile":"./index.ts"}}
15 changes: 15 additions & 0 deletions libs/ui5-angular/ai/theming/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Injectable } from '@angular/core';
import { WebcomponentsThemingProvider } from '@ui5/webcomponents-ngx/theming';

@Injectable({ providedIn: 'root' })
class Ui5WebcomponentsAiThemingService extends WebcomponentsThemingProvider {
name = 'ui-5-webcomponents-ai-theming-service';
constructor() {
super(
() =>
import('@ui5/webcomponents-ai/dist/generated/json-imports/Themes.js'),
);
}
}

export { Ui5WebcomponentsAiThemingService };
1 change: 1 addition & 0 deletions libs/ui5-angular/ai/theming/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"lib":{"entryFile":"./index.ts"}}
Loading