Skip to content

Commit 092ffea

Browse files
committed
Convert SuperSelect::Single::Base to TypeScript
1 parent 8fe90bd commit 092ffea

File tree

4 files changed

+104
-21
lines changed

4 files changed

+104
-21
lines changed

packages/components/src/components/hds/form/super-select/single/base.hbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
@placeholder={{@placeholder}}
4545
@placeholderComponent={{component "hds/form/super-select/placeholder"}}
4646
@preventScroll={{@preventScroll}}
47-
@registerAPI={{@registerAPI}}
47+
@registerAPI={{this.setPowerSelectAPI}}
4848
@renderInPlace={{true}}
4949
@resultCountMessage={{@resultCountMessage}}
5050
@scrollTo={{@scrollTo}}
@@ -60,7 +60,7 @@
6060
@triggerComponent={{@triggerComponent}}
6161
@triggerId={{@triggerId}}
6262
@triggerRole={{@triggerRole}}
63-
@typeAheadMatcher={{@typeAheadMatcher}}
63+
@typeAheadOptionMatcher={{@typeAheadOptionMatcher}}
6464
@verticalPosition={{@verticalPosition}}
6565
...attributes
6666
as |option select|

packages/components/src/components/hds/form/super-select/single/base.ts

Lines changed: 75 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,87 @@
33
* SPDX-License-Identifier: MPL-2.0
44
*/
55

6-
import PowerSelectComponent from 'ember-power-select/components/power-select';
6+
import Component from '@glimmer/component';
77
import anchoredPositionModifier from '../../../../../modifiers/hds-anchored-position.ts';
88

99
import { action } from '@ember/object';
10+
import { tracked } from '@glimmer/tracking';
11+
import {
12+
HdsFormSuperSelectHorizontalPositionValues,
13+
HdsFormSuperSelectHorizontalPositionToPlacementValues,
14+
} from '../types.ts';
1015

11-
const DEFAULT_HORIZONTAL_POSITION = 'bottom-start';
12-
const HORIZONTAL_POSITION_MAPPING = {
13-
left: 'bottom-start',
14-
center: 'bottom',
15-
right: 'bottom-end',
16-
};
16+
import type { PowerSelectSignature } from 'ember-power-select/components/power-select';
17+
import type { Select as PowerSelect } from 'ember-power-select/components/power-select';
18+
import type { CalculatePositionResult } from 'ember-basic-dropdown/utils/calculate-position';
19+
import type { HdsFormSuperSelectHorizontalPositions } from '../types.ts';
1720

18-
export default class HdsSuperSelectSingleBaseComponent extends PowerSelectComponent {
19-
@action calculatePosition(trigger, content) {
21+
export const DEFAULT_HORIZONTAL_POSITION: string =
22+
HdsFormSuperSelectHorizontalPositionValues.Left;
23+
export const HORIZONTAL_POSITION_MAPPING =
24+
HdsFormSuperSelectHorizontalPositionToPlacementValues;
25+
26+
export interface HdsFormSuperSelectSingleBaseSignature {
27+
Args: PowerSelectSignature['Args'] & {
28+
showAfterOptions?: boolean;
29+
afterOptionsContent?: string;
30+
resultCountMessage?: string;
31+
dropdownMaxWidth?: string;
32+
matchTriggerWidth?: boolean;
33+
isInvalid?: boolean;
34+
};
35+
Blocks: PowerSelectSignature['Blocks'];
36+
Element: PowerSelectSignature['Element'];
37+
}
38+
39+
export default class HdsFormSuperSelectSingleBaseComponent extends Component<HdsFormSuperSelectSingleBaseSignature> {
40+
@tracked powerSelectAPI?: PowerSelect;
41+
42+
get horizontalPosition(): HdsFormSuperSelectHorizontalPositions {
43+
const { horizontalPosition = DEFAULT_HORIZONTAL_POSITION } = this.args;
44+
return horizontalPosition as HdsFormSuperSelectHorizontalPositions;
45+
}
46+
47+
get resultCountMessage(): string {
48+
return `${this.powerSelectAPI?.resultsCount || 0} total`;
49+
}
50+
51+
/**
52+
* This action sets the powerSelectAPI property and optionally calls a registerAPI function.
53+
*
54+
* @param {Object} powerSelectAPI - The API object for the PowerSelect component.
55+
*
56+
* If a `registerAPI` function is passed in through the component's arguments,
57+
* this function will be called with the `powerSelectAPI` as its argument.
58+
* This allows parent components or controllers to have access to the PowerSelect API.
59+
*
60+
* The `powerSelectAPI` is also stored on the component instance and used in `clearSelected`
61+
*/
62+
@action
63+
setPowerSelectAPI(powerSelectAPI: PowerSelect): void {
64+
if (typeof this.args.registerAPI === 'function') {
65+
this.args.registerAPI(powerSelectAPI);
66+
}
67+
this.powerSelectAPI = powerSelectAPI;
68+
}
69+
70+
@action calculatePosition(
71+
trigger: Element,
72+
content: HTMLElement
73+
): CalculatePositionResult {
2074
// use `hds-anchored-position` to calculate and set position
75+
// @ts-expect-error: known issue with type of invocation
2176
anchoredPositionModifier(content, [trigger], {
22-
placement: this.args.horizontalPosition
23-
? HORIZONTAL_POSITION_MAPPING[this.args.horizontalPosition]
24-
: DEFAULT_HORIZONTAL_POSITION,
77+
placement: HORIZONTAL_POSITION_MAPPING[this.horizontalPosition],
2578
offsetOptions: 4,
2679
enableCollisionDetection: true,
2780
});
2881
// prevent PowerSelect from setting position
29-
return {};
82+
return {
83+
horizontalPosition: 'auto',
84+
verticalPosition: 'auto',
85+
style: {},
86+
};
3087
}
3188

3289
/**
@@ -35,7 +92,7 @@ export default class HdsSuperSelectSingleBaseComponent extends PowerSelectCompon
3592
* @type {boolean}
3693
* @default false
3794
*/
38-
get showAfterOptions() {
95+
get showAfterOptions(): boolean | string {
3996
return this.args.showAfterOptions ?? this.args.afterOptionsContent ?? false;
4097
}
4198

@@ -45,7 +102,7 @@ export default class HdsSuperSelectSingleBaseComponent extends PowerSelectCompon
45102
* @type {string}
46103
* @default 'Search'
47104
*/
48-
get searchPlaceholder() {
105+
get searchPlaceholder(): string {
49106
return this.args.searchPlaceholder ?? 'Search';
50107
}
51108

@@ -56,7 +113,7 @@ export default class HdsSuperSelectSingleBaseComponent extends PowerSelectCompon
56113
* @default 'none'
57114
*/
58115
get dropdownMaxWidthStyle() {
59-
const maxWidthStyle = {};
116+
const maxWidthStyle: { [key: string]: string } = {};
60117
if (this.args.dropdownMaxWidth) {
61118
maxWidthStyle['--hds-form-super-select-dropdown-max-width'] =
62119
this.args.dropdownMaxWidth;
@@ -69,8 +126,8 @@ export default class HdsSuperSelectSingleBaseComponent extends PowerSelectCompon
69126
* @method classNames
70127
* @return {string} The "class" attribute to apply to the component.
71128
*/
72-
get classNames() {
73-
let classes = ['hds-form-super-select', 'hds-form-super-select-single'];
129+
get classNames(): string {
130+
const classes = ['hds-form-super-select', 'hds-form-super-select-single'];
74131

75132
// add a class based on the @matchTriggerWidth argument or whether dropdownMaxWidth is set
76133
if (this.args.matchTriggerWidth === false || this.args.dropdownMaxWidth) {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Copyright (c) HashiCorp, Inc.
3+
* SPDX-License-Identifier: MPL-2.0
4+
*/
5+
6+
import type { FloatingUIOptions } from '../../../../modifiers/hds-anchored-position.ts';
7+
8+
export enum HdsFormSuperSelectHorizontalPositionValues {
9+
Left = 'left',
10+
Center = 'center',
11+
Right = 'right',
12+
}
13+
14+
export type HdsFormSuperSelectHorizontalPositions =
15+
`${HdsFormSuperSelectHorizontalPositionValues}`;
16+
17+
// map SuperSelect's `horizontalPosition` values to anchoredPositionModifier's `placement` values
18+
export const HdsFormSuperSelectHorizontalPositionToPlacementValues: Record<
19+
// SuperSelect's `horizontalPosition` values
20+
HdsFormSuperSelectHorizontalPositionValues,
21+
FloatingUIOptions['placement']
22+
> = {
23+
[HdsFormSuperSelectHorizontalPositionValues.Left]: 'bottom-start',
24+
[HdsFormSuperSelectHorizontalPositionValues.Center]: 'bottom',
25+
[HdsFormSuperSelectHorizontalPositionValues.Right]: 'bottom-end',
26+
};

showcase/tests/integration/components/hds/form/super-select/single/base-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ module(
6363
.dom(
6464
'.hds-form-super-select__after-options .hds-form-super-select__result-count'
6565
)
66-
.hasText('3 results');
66+
.hasText('3 total');
6767
});
6868

6969
test('it should render custom content in the after options block when `@afterOptionsContent` exists', async function (assert) {

0 commit comments

Comments
 (0)