diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index 920e5e7eb..5c5fa8648 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: '20.x' + node-version: '24.x' registry-url: 'https://registry.npmjs.org' scope: '@aws' - run: npm ci diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b8fa1c638..dd7aaa3fe 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: '20.x' + node-version: '24.x' registry-url: 'https://registry.npmjs.org' scope: '@aws' - run: npm ci diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index af85381cd..d840fc393 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,7 +12,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: '24.x' registry-url: 'https://registry.npmjs.org' scope: '@aws' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0e590193c..25c20faa9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: '24.x' registry-url: 'https://registry.npmjs.org' scope: '@aws' - name: Install dependencies and build diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 857345928..6819f8ccd 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -11,7 +11,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: '24.x' registry-url: 'https://registry.npmjs.org' scope: '@aws' diff --git a/example/src/config.ts b/example/src/config.ts index f0053c539..5525b23ab 100644 --- a/example/src/config.ts +++ b/example/src/config.ts @@ -312,15 +312,18 @@ export const mynahUIDefaults: Partial = { options: [ { label: 'Fast', - value: 'fast' + value: 'fast', + description: 'Quick responses with good accuracy' }, { label: 'Fast 2.0 (Exp.)', - value: 'fast-2-experimental' + value: 'fast-2-experimental', + description: 'Experimental faster model with enhanced capabilities' }, { label: 'Decisive', - value: 'decisive' + value: 'decisive', + description: 'More thorough analysis with detailed responses' }, ] } diff --git a/package-lock.json b/package-lock.json index 0671a0762..1e05f86e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@aws/mynah-ui", - "version": "4.36.6", + "version": "4.36.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@aws/mynah-ui", - "version": "4.36.6", + "version": "4.36.8", "hasInstallScript": true, "license": "Apache License 2.0", "dependencies": { @@ -26,7 +26,7 @@ "@types/jest": "^29.5.5", "@types/json-schema": "7.0.7", "@types/minimatch": "^5.1.2", - "@types/node": "17.0.29", + "@types/node": "^24.0.0", "@types/sanitize-html": "^2.11.0", "@typescript-eslint/eslint-plugin": "^5.34.0", "@typescript-eslint/parser": "^5.62.0", @@ -1749,10 +1749,14 @@ "dev": true }, "node_modules/@types/node": { - "version": "17.0.29", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.29.tgz", - "integrity": "sha512-tx5jMmMFwx7wBwq/V7OohKDVb/JwJU5qCVkeLMh1//xycAJ/ESuw9aJ9SEtlCZDYi2pBfe4JkisSoAtbOsBNAA==", - "dev": true + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.0.tgz", + "integrity": "sha512-y1dMvuvJspJiPSDZUQ+WMBvF7dpnEqN4x9DDC9ie5Fs/HUZJA3wFp7EhHoVaKX/iI0cRoECV8X2jL8zi0xrHCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.12.0" + } }, "node_modules/@types/sanitize-html": { "version": "2.11.0", @@ -10214,6 +10218,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", + "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/unescape-html": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unescape-html/-/unescape-html-1.1.0.tgz", diff --git a/package.json b/package.json index e5fe4f163..d37399fbe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@aws/mynah-ui", "displayName": "AWS Mynah UI", - "version": "4.36.6", + "version": "4.36.8", "description": "AWS Toolkit VSCode and Intellij IDE Extension Mynah UI", "publisher": "Amazon Web Services", "license": "Apache License 2.0", @@ -74,7 +74,7 @@ "@types/jest": "^29.5.5", "@types/json-schema": "7.0.7", "@types/minimatch": "^5.1.2", - "@types/node": "17.0.29", + "@types/node": "^24.0.0", "@types/sanitize-html": "^2.11.0", "@typescript-eslint/eslint-plugin": "^5.34.0", "@typescript-eslint/parser": "^5.62.0", diff --git a/src/components/form-items/select.ts b/src/components/form-items/select.ts index 8263f1382..31c7b2d60 100644 --- a/src/components/form-items/select.ts +++ b/src/components/form-items/select.ts @@ -83,41 +83,17 @@ export class SelectInternal { value: '', description: undefined } ] - : []), ...props.options ?? [] ].flatMap(option => { - const mainOption = { - type: 'option', - testId: props.optionTestId, - classNames: option.value === '' ? [ 'empty-option' ] : [], - attributes: { - value: option.value, - ...(option.description != null && option.description.trim() !== '' ? { 'data-description': option.description } : {}) - }, - children: [ - option.label - ] - }; - - // Add disabled description option if description exists - if (option.description != null && option.description.trim() !== '') { - return [ - mainOption, - { - type: 'option', - testId: props.optionTestId, - classNames: [ 'description-option' ], - attributes: { - value: '', - disabled: 'disabled' - }, - children: [ - ` ${option.description}` - ] - } - ]; - } - - return [ mainOption ]; - }) as DomBuilderObject[] + : []), ...props.options ?? [] ].map(option => ({ + type: 'option', + testId: props.optionTestId, + classNames: option.value === '' ? [ 'empty-option' ] : [], + attributes: { + value: option.value, + }, + children: [ + option.label + ] + })) as DomBuilderObject[] }); if (props.value !== undefined) { this.selectElement.value = props.value; @@ -149,22 +125,36 @@ export class SelectInternal { ] }); - // Add tooltip functionality if tooltip is provided - if (props.tooltip != null && props.tooltip.trim() !== '') { - this.selectContainer.update({ - events: { - mouseenter: () => { - if (props.tooltip != null && props.tooltip.trim() !== '') { - this.showTooltip(props.tooltip); - } - }, - mouseleave: () => { - this.hideTooltip(); + // Add tooltip functionality + this.setupTooltip(); + } + + private readonly setupTooltip = (): void => { + this.selectContainer.update({ + events: { + mouseenter: () => { + const currentTooltip = this.getCurrentTooltip(); + if (currentTooltip != null && currentTooltip.trim() !== '') { + this.showTooltip(currentTooltip); } + }, + mouseleave: () => { + this.hideTooltip(); } - }); + } + }); + }; + + private readonly getCurrentTooltip = (): string => { + const currentValue = this.selectElement.value; + const selectedOption = this.props.options?.find(option => option.value === currentValue); + + // If there's a selected option, show label and description; otherwise use the base tooltip + if (selectedOption?.description != null) { + return `${selectedOption.label}
${selectedOption.description}`; } - } + return this.props.tooltip ?? ''; + }; setValue = (value: string): void => { this.selectElement.value = value;