refactor: migrate to HDS select form fields (#1447)
* chore: 🤖 install HDS and associated assets * chore: 🤖 bump HDS version * refactor: 💡 optimize hds/icon addon content build * test: 💍 fix intermittent test failure * refactor: 💡 replace auth method selects with HDS select * refactor: 💡 update storybook and tests to reflect HDS selects * style: 💄 fix style linting issue * fix: 🐛 fix bad scss syntax * fix: 🐛 fix scss syntax again * refactor: 💡 remove references to rose/form/select * chore: 🤖 experimental HDS dark mode * refactor: 💡 add custom set helper to replace action helper * chore: 🤖 remove HDS dark mode, to be implemented in another pr * refactor: 💡 apply custom dark mode for HDS * chore: 🤖 add tier 2 color tweaks for better dark mode contrast * chore: 🤖 tweak HDS form borders in dark mode * docs: ✏️ add set function comment Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>
This commit is contained in:
1 parent
87b1fb1c5c
commit
02b6afa5e7
18 files changed
+228
-481
No files matched your search
@@ -22,7 +22,6 @@
|
||||
'rose/form/checkbox/group' disabled=this.disabled
|
||||
)
|
||||
input=(component 'rose/form/input' disabled=this.disabled)
|
||||
select=(component 'rose/form/select' disabled=this.disabled)
|
||||
textarea=(component 'rose/form/textarea' disabled=this.disabled)
|
||||
fieldset=(component 'rose/form/fieldset')
|
||||
actions=(component
|
||||
@@ -37,6 +36,7 @@
|
||||
enableEdit=this.enableEdit
|
||||
)
|
||||
isEditable=this.isEditable
|
||||
disabled=this.disabled
|
||||
)
|
||||
}}
|
||||
</form>
|
||||
@@ -19,19 +19,22 @@ export const Template = (args) => ({
|
||||
>
|
||||
<form.input @label='Label' @helperText='Helper text' @value='Text' />
|
||||
<form.textarea @label='Label' @helperText='Helper text' @value='Text' />
|
||||
<form.select
|
||||
@label='Label'
|
||||
@helperText='Helper text'
|
||||
@onChange={{selectChange}}
|
||||
as |field|
|
||||
<Hds::Form::Select::Field
|
||||
@value={{selectedValue}}
|
||||
@isInvalid={{false}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'change' (fn selectChange)}}
|
||||
as |F|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose an option</select.option>
|
||||
<select.option @value='value-1'>Value 1</select.option>
|
||||
<select.option @value='value-2'>Value 2</select.option>
|
||||
<select.option @value='value-3'>Value 3</select.option>
|
||||
</field.field>
|
||||
</form.select>
|
||||
<F.Label>Label</F.Label>
|
||||
<F.HelperText>Helper text</F.HelperText>
|
||||
<F.Options>
|
||||
<option>Choose an option</option>
|
||||
<option value='value-1' selected={{eq value 'value-1'}}>Value 1</option>
|
||||
<option value='value-2' selected={{eq value 'value-2'}}>Value 2</option>
|
||||
<option value='value-3' selected={{eq value 'value-3'}}>Value 3</option>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
<form.radioGroup @name='color' @selectedValue='green' as |radioGroup|>
|
||||
<radioGroup.radio @label='Red' @value='red' />
|
||||
<radioGroup.radio @label='Green' @value='green' />
|
||||
@@ -76,19 +79,24 @@ export const Template = (args) => ({
|
||||
>
|
||||
<form.input @label='Label' @helperText='Helper text' @value='Text' />
|
||||
<form.textarea @label='Label' @helperText='Helper text' @value='Text' />
|
||||
<form.select
|
||||
@label='Label'
|
||||
@helperText='Helper text'
|
||||
@onChange={{fn this.actionHandler}}
|
||||
as |field|
|
||||
|
||||
<Hds::Form::Select::Field
|
||||
@value={{selectedValue}}
|
||||
@isInvalid={{false}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'change' (set-from-event this 'selectedValue')}}
|
||||
as |F|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose an option</select.option>
|
||||
<select.option @value='value-1'>Value 1</select.option>
|
||||
<select.option @value='value-2'>Value 2</select.option>
|
||||
<select.option @value='value-3'>Value 3</select.option>
|
||||
</field.field>
|
||||
</form.select>
|
||||
<F.Label>Label</F.Label>
|
||||
<F.HelperText>Helper text</F.HelperText>
|
||||
<F.Options>
|
||||
<option>Choose an option</option>
|
||||
<option value='value-1' selected={{eq value 'value-1'}}>Value 1</option>
|
||||
<option value='value-2' selected={{eq value 'value-2'}}>Value 2</option>
|
||||
<option value='value-3' selected={{eq value 'value-3'}}>Value 3</option>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
|
||||
<form.radioGroup @name='color' @selectedValue='green' as |radioGroup|>
|
||||
<radioGroup.radio @label='Red' @value='red' />
|
||||
<radioGroup.radio @label='Green' @value='green' />
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
{{#if @contextual}}
|
||||
{{yield
|
||||
(hash
|
||||
label=(component 'rose/form/label' for=this.id error=@error)
|
||||
helperText=(component
|
||||
'rose/form/helper-text' id=(concat 'helper-text-' this.id) error=@error
|
||||
)
|
||||
field=(component
|
||||
'rose/form/select/select'
|
||||
id=this.id
|
||||
name=@name
|
||||
value=@value
|
||||
onChange=@onChange
|
||||
disabled=@disabled
|
||||
error=@error
|
||||
aria-describedby=(concat
|
||||
(if @helperText (concat 'helper-text-' this.id))
|
||||
(if @error (concat ' errors-' this.id))
|
||||
)
|
||||
)
|
||||
errors=(component 'rose/form/errors' id=(concat 'errors-' this.id))
|
||||
)
|
||||
}}
|
||||
{{else}}
|
||||
<div class='rose-form-select'>
|
||||
|
||||
<Rose::Form::Label @for={{this.id}} @error={{@error}}>
|
||||
{{@label}}
|
||||
</Rose::Form::Label>
|
||||
|
||||
{{#if @helperText}}
|
||||
<Rose::Form::HelperText @id='helper-text-{{this.id}}' @error={{@error}}>
|
||||
{{@helperText}}
|
||||
</Rose::Form::HelperText>
|
||||
{{/if}}
|
||||
|
||||
{{yield
|
||||
(hash
|
||||
field=(component
|
||||
'rose/form/select/select'
|
||||
id=this.id
|
||||
name=@name
|
||||
value=@value
|
||||
onChange=@onChange
|
||||
disabled=@disabled
|
||||
error=@error
|
||||
aria-describedby=(concat
|
||||
(if @helperText (concat 'helper-text-' this.id))
|
||||
(if @error (concat ' errors-' this.id))
|
||||
)
|
||||
)
|
||||
errors=(component 'rose/form/errors' id=(concat 'errors-' this.id))
|
||||
)
|
||||
}}
|
||||
|
||||
</div>
|
||||
{{/if}}
|
||||
@@ -1,8 +0,0 @@
|
||||
import Component from '@glimmer/component';
|
||||
import { generateComponentID } from '../../../../utilities/component-auto-id';
|
||||
|
||||
export default class RoseFormSelectComponent extends Component {
|
||||
// =attributes
|
||||
|
||||
id = generateComponentID();
|
||||
}
|
||||
@@ -1,50 +1,52 @@
|
||||
import { Meta, Story, Preview } from '@storybook/addon-docs';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
<Meta title="Rose/Form/Select" component="Form/Select" />
|
||||
<Meta title="Rose/Form/Select (removed)" component="Form/Select" />
|
||||
|
||||
# Form Select
|
||||
# Select (removed)
|
||||
|
||||
Renders a form select element.
|
||||
Rose/Form/Select has been removed in favor of
|
||||
[HDS::Form::Select](https://design-system-components-hashicorp.vercel.app/components/form/select).
|
||||
|
||||
```handlebars
|
||||
<Rose::Form::Select
|
||||
@name='select-name'
|
||||
@value='green'
|
||||
@label='Color'
|
||||
@helperText='Set your desired color'
|
||||
@disabled={{false}}
|
||||
@error={{false}}
|
||||
as |field|
|
||||
<Hds::Form::Select::Field
|
||||
@value={{this.selectedValue}}
|
||||
@isInvalid={{false}}
|
||||
disabled={{false}}
|
||||
name='select_name'
|
||||
{{on 'change' (set-from-event this 'selectedValue')}}
|
||||
as |F|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose a color</select.option>
|
||||
<select.option @value='red'>Red</select.option>
|
||||
<select.option @value='green'>Green</select.option>
|
||||
<select.option @value='blue'>Blue</select.option>
|
||||
</field.field>
|
||||
</Rose::Form::Select>
|
||||
<F.Label>Color</F.Label>
|
||||
<F.HelperText>Set your desired color</F.Label>
|
||||
<F.Options>
|
||||
<option>Choose a color</option>
|
||||
<option value='red' selected={{eq this.selectedValue 'red'}}>Red</option>
|
||||
<option value='green' selected={{eq this.selectedValue 'green'}}>Green</option>
|
||||
<option value='blue' selected={{eq this.selectedValue 'blue'}}>Blue</option>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
```
|
||||
|
||||
export const Template = (args) => ({
|
||||
template: hbs`
|
||||
<Rose::Form::Select
|
||||
@name={{name}}
|
||||
<Hds::Form::Select::Field
|
||||
@value={{value}}
|
||||
@label={{label}}
|
||||
@helperText={{helperText}}
|
||||
@disabled={{disabled}}
|
||||
@error={{false}}
|
||||
@onChange={{fn onChange}}
|
||||
as |field|
|
||||
@isInvalid={{error}}
|
||||
disabled={{disabled}}
|
||||
name={{name}}
|
||||
{{on 'change' (set-from-event this 'value')}}
|
||||
as |F|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose an option</select.option>
|
||||
<select.option @value='value-1'>Value 1</select.option>
|
||||
<select.option @value='value-2'>Value 2</select.option>
|
||||
<select.option @value='value-3'>Value 3</select.option>
|
||||
</field.field>
|
||||
</Rose::Form::Select>`,
|
||||
<F.Label>{{label}}</F.Label>
|
||||
<F.HelperText>{{helperText}}</F.HelperText>
|
||||
<F.Options>
|
||||
<option>Choose an option</option>
|
||||
<option value='value-1' selected={{eq value 'value-1'}}>Value 1</option>
|
||||
<option value='value-2' selected={{eq value 'value-2'}}>Value 2</option>
|
||||
<option value='value-3' selected={{eq value 'value-3'}}>Value 3</option>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>`,
|
||||
context: args,
|
||||
});
|
||||
|
||||
@@ -53,10 +55,11 @@ export const Template = (args) => ({
|
||||
name="Basic"
|
||||
height="10rem"
|
||||
args={{
|
||||
name: 'select-name',
|
||||
name: 'select_name',
|
||||
label: 'Label',
|
||||
helperText: 'Helper text',
|
||||
disabled: false,
|
||||
error: false,
|
||||
}}
|
||||
argTypes={{
|
||||
value: { control: 'select', options: ['value-1', 'value-2', 'value-3'] },
|
||||
@@ -66,78 +69,3 @@ export const Template = (args) => ({
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Preview>
|
||||
|
||||
export const ErrorTemplate = (args) => ({
|
||||
template: hbs`
|
||||
<Rose::Form::Select
|
||||
@name={{name}}
|
||||
@value={{value}}
|
||||
@label={{label}}
|
||||
@helperText={{helperText}}
|
||||
@disabled={{disabled}}
|
||||
@error={{true}}
|
||||
@onChange={{fn onChange}}
|
||||
as |field|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose an option</select.option>
|
||||
<select.option @value='value-1'>Value 1</select.option>
|
||||
<select.option @value='value-2'>Value 2</select.option>
|
||||
<select.option @value='value-3'>Value 3</select.option>
|
||||
</field.field>
|
||||
<field.errors as |errors|>
|
||||
<errors.message>An error occurred.</errors.message>
|
||||
</field.errors>
|
||||
</Rose::Form::Select>`,
|
||||
context: args,
|
||||
});
|
||||
|
||||
<Preview>
|
||||
<Story
|
||||
name="Select with Errors"
|
||||
height="10rem"
|
||||
args={{
|
||||
name: 'select-name',
|
||||
label: 'Label',
|
||||
helperText: 'Helper text',
|
||||
disabled: false,
|
||||
}}
|
||||
argTypes={{
|
||||
value: { control: 'select', options: ['value-1', 'value-2', 'value-3'] },
|
||||
onChange: { action: 'changed' },
|
||||
}}
|
||||
>
|
||||
{ErrorTemplate.bind({})}
|
||||
</Story>
|
||||
</Preview>
|
||||
|
||||
export const ContextualTemplate = (args) => ({
|
||||
template: hbs`
|
||||
<Rose::Form::Select
|
||||
@value='value-3'
|
||||
@error={{true}}
|
||||
@contextual={{true}}
|
||||
as |field|
|
||||
>
|
||||
<hr />
|
||||
<field.label>Label</field.label>
|
||||
<hr />
|
||||
<field.helperText>Help</field.helperText>
|
||||
<hr />
|
||||
<field.field as |select|>
|
||||
<select.option @value='value-1'>Value 1</select.option>
|
||||
<select.option @value='value-2'>Value 2</select.option>
|
||||
<select.option @value='value-3'>Value 3</select.option>
|
||||
</field.field>
|
||||
<hr />
|
||||
<field.errors as |errors|>
|
||||
<errors.message>An error occurred.</errors.message>
|
||||
</field.errors>
|
||||
<hr />
|
||||
</Rose::Form::Select>`,
|
||||
context: args,
|
||||
});
|
||||
|
||||
<Preview>
|
||||
<Story name="Fully Contextual Select">{ContextualTemplate.bind({})}</Story>
|
||||
</Preview>
|
||||
@@ -1,13 +0,0 @@
|
||||
<XSelect
|
||||
...attributes
|
||||
class='rose-form-select-field{{if @error " error"}}'
|
||||
id={{@id}}
|
||||
name={{@name}}
|
||||
disabled={{@disabled}}
|
||||
@value={{@value}}
|
||||
@onChange={{@onChange}}
|
||||
aria-describedby={{@aria-describedby}}
|
||||
as |xs|
|
||||
>
|
||||
{{yield xs}}
|
||||
</XSelect>
|
||||
@@ -0,0 +1,11 @@
|
||||
import { helper } from '@ember/component/helper';
|
||||
import { set } from '@ember/object';
|
||||
|
||||
export function setFromEvent([context, field]) {
|
||||
// The Ember `set` function is used here because `field` may be in dotted
|
||||
// notation, refering to nested fields within `context`.
|
||||
return (event) =>
|
||||
event?.target?.value ? set(context, field, event.target.value) : null;
|
||||
}
|
||||
|
||||
export default helper(setFromEvent);
|
||||
@@ -70,6 +70,7 @@
|
||||
--token-color-foreground-warning-on-surface: var(--token-color-palette-amber-400);
|
||||
--token-color-foreground-critical-on-surface: var(--token-color-palette-red-400);
|
||||
--token-color-surface-strong: var(--token-color-palette-neutral-50);
|
||||
--token-form-control-base-border-color-default: var(--token-color-palette-neutral-200);
|
||||
}
|
||||
|
||||
// HDS Light Mode
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'rose/components/rose/form/select';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'rose/components/rose/form/select/select';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'rose/helpers/set-from-event';
|
||||
@@ -19,8 +19,8 @@
|
||||
// This styles are add to stop the input to apply extra margin (default on forms)
|
||||
.rose-form-input,
|
||||
.rose-form-input-field,
|
||||
.rose-form-select,
|
||||
.rose-form-select-field {
|
||||
.hds-form-select,
|
||||
[class^='hds-form-field-'] .hds-form-select:not(:first-child) {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
"ember-named-blocks-polyfill": "^0.2.5",
|
||||
"ember-radio-button": "github:yapplabs/ember-radio-button.git#b2ab65f",
|
||||
"ember-uuid": "^2.1.0",
|
||||
"emberx-select": "github:adopted-ember-addons/emberx-select#bc5f774",
|
||||
"sass": "^1.55.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -42,14 +42,24 @@ module('Integration | Component | rose/form', function (hooks) {
|
||||
>
|
||||
<form.input @label="Input" @name="input-field" />
|
||||
<form.textarea @label="Textarea" @name="textarea-field" />
|
||||
<form.select
|
||||
@label="Select"
|
||||
@name="select-field"
|
||||
@onChange={{this.select}}
|
||||
as |field|
|
||||
|
||||
<Hds::Form::Select::Field
|
||||
@isInvalid={{false}}
|
||||
disabled={{form.disabled}}
|
||||
name='select-field'
|
||||
{{on 'change' (set-from-event this 'selectedValue')}}
|
||||
as |F|
|
||||
>
|
||||
<field.field />
|
||||
</form.select>
|
||||
<F.Label>Select</F.Label>
|
||||
<F.HelperText>Helper text</F.HelperText>
|
||||
<F.Options>
|
||||
<option>Choose an option</option>
|
||||
<option value='value-1'>Value 1</option>
|
||||
<option value='value-2'>Value 2</option>
|
||||
<option value='value-3'>Value 3</option>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
|
||||
<form.checkbox @label="Checkbox" @name="checkbox-field" />
|
||||
<form.radioGroup @name="radio-group-field" @selectedValue="green" as |radioGroup|>
|
||||
<radioGroup.radio
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, find, findAll, fillIn } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
module('Integration | Component | rose/form/select', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function (assert) {
|
||||
this.onChange = () => {};
|
||||
await render(hbs`
|
||||
<Rose::Form::Select
|
||||
@label="Label"
|
||||
@onChange={{fn this.onChange}}
|
||||
as |field|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose an option</select.option>
|
||||
<select.option @value="value-1">Value 1</select.option>
|
||||
<select.option @value="value-2">Value 2</select.option>
|
||||
<select.option @value="value-3">Value 3</select.option>
|
||||
</field.field>
|
||||
</Rose::Form::Select>
|
||||
`);
|
||||
assert.strictEqual(find('label').textContent.trim(), 'Label');
|
||||
assert.ok(find('select'));
|
||||
assert.strictEqual(findAll('option').length, 4);
|
||||
});
|
||||
|
||||
test('it displays optional helper text', async function (assert) {
|
||||
this.onChange = () => {};
|
||||
await render(hbs`
|
||||
<Rose::Form::Select
|
||||
@label="Label"
|
||||
@helperText="Help me"
|
||||
@onChange={{fn this.onChange}}
|
||||
as |field|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose an option</select.option>
|
||||
</field.field>
|
||||
</Rose::Form::Select>
|
||||
`);
|
||||
const fieldEl = find('select');
|
||||
const id = fieldEl.id;
|
||||
const helperId = `helper-text-${id}`;
|
||||
const helperTextEl = find('.rose-form-helper-text');
|
||||
assert.strictEqual(helperTextEl.textContent.trim(), 'Help me');
|
||||
assert.strictEqual(helperTextEl.id, helperId);
|
||||
assert.strictEqual(
|
||||
fieldEl.getAttribute('aria-describedby').trim(),
|
||||
helperId
|
||||
);
|
||||
});
|
||||
|
||||
test('it displays optional errors', async function (assert) {
|
||||
this.onChange = () => {};
|
||||
await render(hbs`
|
||||
<Rose::Form::Select
|
||||
@label="Label"
|
||||
@helperText="Help me"
|
||||
@onChange={{fn this.onChange}}
|
||||
@error={{true}}
|
||||
as |field|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose an option</select.option>
|
||||
</field.field>
|
||||
<field.errors as |errors|>
|
||||
<errors.message>An error occurred.</errors.message>
|
||||
</field.errors>
|
||||
</Rose::Form::Select>
|
||||
`);
|
||||
const fieldEl = find('select');
|
||||
const id = fieldEl.id;
|
||||
const errorsId = `errors-${id}`;
|
||||
const errorMessageEl = find('.rose-form-errors');
|
||||
assert.strictEqual(errorMessageEl.id, errorsId);
|
||||
assert.strictEqual(errorMessageEl.textContent.trim(), 'An error occurred.');
|
||||
assert.strictEqual(
|
||||
fieldEl.getAttribute('aria-describedby').split(' ')[1],
|
||||
errorsId
|
||||
);
|
||||
});
|
||||
|
||||
test('it supports disabled attribute', async function (assert) {
|
||||
this.onChange = () => {};
|
||||
await render(hbs`
|
||||
<Rose::Form::Select
|
||||
@onChange={{fn this.onChange}}
|
||||
@disabled={{true}}
|
||||
as |field|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose an option</select.option>
|
||||
</field.field>
|
||||
</Rose::Form::Select>
|
||||
`);
|
||||
assert.ok(find('[disabled]'));
|
||||
});
|
||||
|
||||
test('its value is bound to and udpated by @value', async function (assert) {
|
||||
this.onChange = () => {};
|
||||
this.value = 'value-1';
|
||||
await render(hbs`
|
||||
<Rose::Form::Select
|
||||
@onChange={{fn this.onChange}}
|
||||
@value={{value}}
|
||||
as |field|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option @value="value-1">value-1</select.option>
|
||||
<select.option @value="value-2">value-2</select.option>
|
||||
</field.field>
|
||||
</Rose::Form::Select>
|
||||
`);
|
||||
assert.strictEqual(find('select').value, 'value-1');
|
||||
this.set('value', 'value-2');
|
||||
assert.strictEqual(find('select').value, 'value-2');
|
||||
});
|
||||
|
||||
test('it triggers an action on change', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.onChange1 = (value) => {
|
||||
assert.strictEqual(
|
||||
value,
|
||||
null,
|
||||
'On initial render, onChange is triggered with null'
|
||||
);
|
||||
this.set('onChange', this.onChange2);
|
||||
};
|
||||
this.onChange2 = (value) => {
|
||||
assert.strictEqual(value, 'value-1', 'On change, value is passed in.');
|
||||
};
|
||||
this.onChange = this.onChange1;
|
||||
await render(hbs`
|
||||
<Rose::Form::Select
|
||||
@name="my-select"
|
||||
@onChange={{fn this.onChange}}
|
||||
as |field|
|
||||
>
|
||||
<field.field as |select|>
|
||||
<select.option>Choose an option</select.option>
|
||||
<select.option @value="value-1">value-1</select.option>
|
||||
</field.field>
|
||||
</Rose::Form::Select>
|
||||
`);
|
||||
await fillIn('[name="my-select"]', 'value-1');
|
||||
});
|
||||
|
||||
test('it supports a fully contextual usage', async function (assert) {
|
||||
assert.expect(5);
|
||||
await render(hbs`
|
||||
<Rose::Form::Select @value="value-1" @error={{true}} @contextual={{true}} as |field|>
|
||||
<field.label>Label</field.label>
|
||||
<field.helperText>Help</field.helperText>
|
||||
<field.field as |select|>
|
||||
<select.option @value="value-1">value-1</select.option>
|
||||
</field.field>
|
||||
<field.errors as |errors|>
|
||||
<errors.message>An error occurred.</errors.message>
|
||||
</field.errors>
|
||||
</Rose::Form::Select>
|
||||
`);
|
||||
assert.notOk(
|
||||
find('.rose-form-input'),
|
||||
'The form field wrapper element is not present in contextual mode'
|
||||
);
|
||||
assert.ok(find('.rose-form-label.error'));
|
||||
assert.ok(find('.rose-form-helper-text.error'));
|
||||
assert.ok(find('.rose-form-select-field.error'));
|
||||
assert.ok(find('.rose-form-error-message'));
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, click, select } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import { setFromEvent } from 'rose/helpers/set-from-event';
|
||||
|
||||
module('Integration | Helper | set-from-event', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it returns a function that sets the specified value to event.target.value', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.set('inputValue', '1234');
|
||||
assert.deepEqual(this.inputValue, '1234');
|
||||
const handler = setFromEvent([this, 'inputValue']);
|
||||
handler({ target: { value: 'foobar' } });
|
||||
assert.deepEqual(this.inputValue, 'foobar');
|
||||
});
|
||||
|
||||
test('it can be used with the on modifier to set a specified field with the value of event.target.value', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.set('inputValue', '1234');
|
||||
await render(
|
||||
hbs`<button value="foobar" {{on 'click' (set-from-event this 'inputValue')}} />`
|
||||
);
|
||||
assert.deepEqual(this.inputValue, '1234');
|
||||
await click('button');
|
||||
assert.deepEqual(this.inputValue, 'foobar');
|
||||
});
|
||||
|
||||
test('it can be used in an HDS select element to set a specified field with the value of the selected option', async function (assert) {
|
||||
assert.expect(3);
|
||||
this.set('selectedValue', 'blue');
|
||||
await render(hbs`
|
||||
<Hds::Form::Select::Field
|
||||
@value={{this.selectedValue}}
|
||||
@isInvalid={{false}}
|
||||
disabled={{false}}
|
||||
name='select_name'
|
||||
{{on 'change' (set-from-event this 'selectedValue')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Options>
|
||||
<option>Choose a color</option>
|
||||
<option value='red' selected={{eq this.selectedValue 'red'}}>Red</option>
|
||||
<option value='green' selected={{eq this.selectedValue 'green'}}>Green</option>
|
||||
<option value='blue' selected={{eq this.selectedValue 'blue'}}>Blue</option>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
`);
|
||||
assert.deepEqual(this.selectedValue, 'blue');
|
||||
await select('[name=select_name]', 'green');
|
||||
assert.deepEqual(this.selectedValue, 'green');
|
||||
await select('[name=select_name]', 'red');
|
||||
assert.deepEqual(this.selectedValue, 'red');
|
||||
});
|
||||
});
|
||||
@@ -155,22 +155,27 @@
|
||||
{{#each @model.attributes.signing_algorithms as |algorithm i|}}
|
||||
<body.row as |row|>
|
||||
<row.cell>
|
||||
<form.select
|
||||
|
||||
<Hds::Form::Select::Field
|
||||
@value={{algorithm.value}}
|
||||
@error={{@model.errors.attributes_signing_algorithms}}
|
||||
@contextual={{true}}
|
||||
@onChange={{fn (mut algorithm.value)}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.attributes_signing_algorithms}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'change' (set-from-event algorithm 'value')}}
|
||||
as |F|
|
||||
>
|
||||
<field.label>{{t 'form.algorithm.label'}}</field.label>
|
||||
<field.field as |select|>
|
||||
{{#each this.signingAlgorithms as |algorithm|}}
|
||||
<select.option
|
||||
@value={{algorithm}}
|
||||
>{{algorithm}}</select.option>
|
||||
<F.Label class='sr-only'>{{t
|
||||
'form.algorithm.label'
|
||||
}}</F.Label>
|
||||
<F.Options>
|
||||
{{#each this.signingAlgorithms as |algorithmOption|}}
|
||||
<option
|
||||
value={{algorithmOption}}
|
||||
selected={{eq algorithmOption algorithm.value}}
|
||||
>{{algorithmOption}}</option>
|
||||
{{/each}}
|
||||
</field.field>
|
||||
</form.select>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
|
||||
</row.cell>
|
||||
<row.cell @shrink={{true}}>
|
||||
<Rose::Button
|
||||
@@ -195,22 +200,26 @@
|
||||
|
||||
<body.row as |row|>
|
||||
<row.cell>
|
||||
<form.select
|
||||
|
||||
<Hds::Form::Select::Field
|
||||
@value={{this.newSigningAlgorithm}}
|
||||
@label={{t
|
||||
'resources.auth-method.titles.new-signing-algorithm'
|
||||
}}
|
||||
@onChange={{fn (mut this.newSigningAlgorithm)}}
|
||||
as |field|
|
||||
disabled={{form.disabled}}
|
||||
{{on 'change' (set-from-event this 'newSigningAlgorithm')}}
|
||||
as |F|
|
||||
>
|
||||
<field.field as |select|>
|
||||
{{#each this.signingAlgorithms as |algorithm|}}
|
||||
<select.option
|
||||
@value={{algorithm}}
|
||||
>{{algorithm}}</select.option>
|
||||
<F.Label class='sr-only'>{{t
|
||||
'resources.auth-method.titles.new-signing-algorithm'
|
||||
}}</F.Label>
|
||||
<F.Options>
|
||||
{{#each this.signingAlgorithms as |algorithmOption|}}
|
||||
<option
|
||||
value={{algorithmOption}}
|
||||
selected={{eq algorithmOption this.newSigningAlgorithm}}
|
||||
>{{algorithmOption}}</option>
|
||||
{{/each}}
|
||||
</field.field>
|
||||
</form.select>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
|
||||
</row.cell>
|
||||
<row.cell @shrink={{true}}>
|
||||
<Rose::Button
|
||||
@@ -455,22 +464,25 @@
|
||||
</form.input>
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<form.select
|
||||
|
||||
<Hds::Form::Select::Field
|
||||
@value={{claimMap.to}}
|
||||
@error={{@model.errors.attributes_account_claim_maps}}
|
||||
@contextual={{true}}
|
||||
@onChange={{fn (mut claimMap.to)}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.attributes_account_claim_maps}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'change' (set-from-event claimMap 'to')}}
|
||||
as |F|
|
||||
>
|
||||
<field.label>{{t 'form.to_claim.label'}}</field.label>
|
||||
<field.field as |select|>
|
||||
{{#each this.toClaims as |toClaim|}}
|
||||
<select.option
|
||||
@value={{toClaim}}
|
||||
>{{toClaim}}</select.option>
|
||||
<F.Label class='sr-only'>{{t 'form.to_claim.label'}}</F.Label>
|
||||
<F.Options>
|
||||
{{#each this.toClaims as |toClaimOption|}}
|
||||
<option
|
||||
value={{toClaimOption}}
|
||||
selected={{eq toClaimOption claimMap.to}}
|
||||
>{{toClaimOption}}</option>
|
||||
{{/each}}
|
||||
</field.field>
|
||||
</form.select>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
|
||||
</row.cell>
|
||||
<row.cell @shrink={{true}}>
|
||||
<Rose::Button
|
||||
@@ -502,20 +514,26 @@
|
||||
/>
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<form.select
|
||||
|
||||
<Hds::Form::Select::Field
|
||||
@value={{this.newToClaim}}
|
||||
@label={{t 'resources.auth-method.titles.new-to-claim'}}
|
||||
@onChange={{fn (mut this.newToClaim)}}
|
||||
as |field|
|
||||
disabled={{form.disabled}}
|
||||
{{on 'change' (set-from-event this 'newToClaim')}}
|
||||
as |F|
|
||||
>
|
||||
<field.field as |select|>
|
||||
{{#each this.toClaims as |toClaim|}}
|
||||
<select.option
|
||||
@value={{toClaim}}
|
||||
>{{toClaim}}</select.option>
|
||||
<F.Label class='sr-only'>{{t
|
||||
'resources.auth-method.titles.new-to-claim'
|
||||
}}</F.Label>
|
||||
<F.Options>
|
||||
{{#each this.toClaims as |toClaimOption|}}
|
||||
<option
|
||||
value={{toClaimOption}}
|
||||
selected={{eq toClaimOption this.newToClaim}}
|
||||
>{{toClaimOption}}</option>
|
||||
{{/each}}
|
||||
</field.field>
|
||||
</form.select>
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
|
||||
</row.cell>
|
||||
<row.cell @shrink={{true}}>
|
||||
<Rose::Button
|
||||
|
||||
@@ -3389,18 +3389,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@bigtest/convergence@^1.1.1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@bigtest/convergence/-/convergence-1.1.2.tgz#1028f28378aae6876b3c07e577a2d4a320ad0acf"
|
||||
integrity sha512-f/tpOfdd5p40Omejmc+jwrNL0nZ0RDV2LEQQdIWYHtMdKfQQRQpdAhyfNVPLuLeKHw5D9dUX8v9WOrwGsMBTAw==
|
||||
|
||||
"@bigtest/interactor@^0.9.0":
|
||||
version "0.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@bigtest/interactor/-/interactor-0.9.3.tgz#f83fa868fc5742a482114af15d22f50677d3a81f"
|
||||
integrity sha512-MKbhp/j1TtlSp1kIM1btvPrMbxn1eW2Notd5oUChBtEpnm8FDAiZIg6LED1aTsUxyRWf2qb5RlJyoy9HZjRgzQ==
|
||||
dependencies:
|
||||
"@bigtest/convergence" "^1.1.1"
|
||||
|
||||
"@cnakazawa/watch@^1.0.3":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
|
||||
@@ -12003,7 +11991,7 @@ ember-a11y-testing@^4.2.0:
|
||||
fs-extra "^10.0.0"
|
||||
validate-peer-dependencies "^2.0.0"
|
||||
|
||||
ember-auto-import@^1.11.2, ember-auto-import@^1.2.15, ember-auto-import@^1.2.19:
|
||||
ember-auto-import@^1.11.2, ember-auto-import@^1.2.19:
|
||||
version "1.11.3"
|
||||
resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-1.11.3.tgz#6e3384a7fbb163384a34546f2e902cd297b0e683"
|
||||
integrity sha512-ekq/XCvsonESobFU30zjZ0I4XMy2E/2ZILCYWuQ1JdhcCSTYhnXDZcqRW8itUG7kbsPqAHT/XZ1LEZYm3seVwQ==
|
||||
@@ -12182,7 +12170,7 @@ ember-cli-babel-plugin-helpers@^1.0.0, ember-cli-babel-plugin-helpers@^1.1.0, em
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.1.tgz#5016b80cdef37036c4282eef2d863e1d73576879"
|
||||
integrity sha512-sKvOiPNHr5F/60NLd7SFzMpYPte/nnGkq/tMIfXejfKHIhaiIkYFqX8Z9UFTKWLLn+V7NOaby6niNPZUdvKCRw==
|
||||
|
||||
ember-cli-babel@^6.16.0, ember-cli-babel@^6.6.0, ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.0, ember-cli-babel@^7.10.0, ember-cli-babel@^7.11.1, ember-cli-babel@^7.13.0, ember-cli-babel@^7.13.2, ember-cli-babel@^7.19.0, ember-cli-babel@^7.20.5, ember-cli-babel@^7.21.0, ember-cli-babel@^7.22.1, ember-cli-babel@^7.23.0, ember-cli-babel@^7.23.1, ember-cli-babel@^7.26.10, ember-cli-babel@^7.26.11, ember-cli-babel@^7.26.3, ember-cli-babel@^7.26.5, ember-cli-babel@^7.26.6, ember-cli-babel@^7.26.8, ember-cli-babel@^7.4.0, ember-cli-babel@^7.5.0, ember-cli-babel@^7.7.3:
|
||||
ember-cli-babel@^6.6.0, ember-cli-babel@^7.0.0, ember-cli-babel@^7.1.0, ember-cli-babel@^7.10.0, ember-cli-babel@^7.11.1, ember-cli-babel@^7.13.0, ember-cli-babel@^7.13.2, ember-cli-babel@^7.19.0, ember-cli-babel@^7.20.5, ember-cli-babel@^7.21.0, ember-cli-babel@^7.22.1, ember-cli-babel@^7.23.0, ember-cli-babel@^7.23.1, ember-cli-babel@^7.26.10, ember-cli-babel@^7.26.11, ember-cli-babel@^7.26.3, ember-cli-babel@^7.26.5, ember-cli-babel@^7.26.6, ember-cli-babel@^7.26.8, ember-cli-babel@^7.4.0, ember-cli-babel@^7.5.0, ember-cli-babel@^7.7.3:
|
||||
version "7.26.11"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-7.26.11.tgz#50da0fe4dcd99aada499843940fec75076249a9f"
|
||||
integrity sha512-JJYeYjiz/JTn34q7F5DSOjkkZqy8qwFOOxXfE6pe9yEJqWGu4qErKxlz8I22JoVEQ/aBUO+OcKTpmctvykM9YA==
|
||||
@@ -12283,16 +12271,6 @@ ember-cli-get-component-path-option@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-get-component-path-option/-/ember-cli-get-component-path-option-1.0.0.tgz#0d7b595559e2f9050abed804f1d8eff1b08bc771"
|
||||
integrity sha1-DXtZVVni+QUKvtgE8djv8bCLx3E=
|
||||
|
||||
ember-cli-htmlbars@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-3.1.0.tgz#87806c2a0bca2ab52d4fb8af8e2215c1ca718a99"
|
||||
integrity sha512-cgvRJM73IT0aePUG7oQ/afB7vSRBV3N0wu9BrWhHX2zkR7A7cUBI7KC9VPk6tbctCXoM7BRGsCC4aIjF7yrfXA==
|
||||
dependencies:
|
||||
broccoli-persistent-filter "^2.3.1"
|
||||
hash-for-dep "^1.5.1"
|
||||
json-stable-stringify "^1.0.1"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
ember-cli-htmlbars@^4.0.0, ember-cli-htmlbars@^4.2.1, ember-cli-htmlbars@^4.3.1:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-4.5.0.tgz#d299e4f7eba6f30dc723ee086906cc550beb252e"
|
||||
@@ -13297,15 +13275,6 @@ ember-wormhole@^0.6.0:
|
||||
ember-cli-babel "^7.22.1"
|
||||
ember-cli-htmlbars "^5.3.1"
|
||||
|
||||
"emberx-select@github:adopted-ember-addons/emberx-select#bc5f774":
|
||||
version "4.0.0-beta.2"
|
||||
resolved "https://codeload.github.com/adopted-ember-addons/emberx-select/tar.gz/bc5f7746ae67d13e17fe2bd118cbed99b0e10aa2"
|
||||
dependencies:
|
||||
"@bigtest/interactor" "^0.9.0"
|
||||
ember-auto-import "^1.2.15"
|
||||
ember-cli-babel "^6.16.0"
|
||||
ember-cli-htmlbars "^3.0.0"
|
||||
|
||||
emittery@^0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860"
|
||||
|
||||
Reference in new issue
Block a user