@dhis2-ui/select 10.16.1 → 10.16.3-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/select/select.js +5 -2
- package/build/cjs/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +2 -2
- package/build/es/select/select.js +5 -2
- package/build/es/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +2 -2
- package/package.json +17 -16
- package/src/index.js +9 -0
- package/src/locales/ar/translations.json +7 -0
- package/src/locales/ar_IQ/translations.json +7 -0
- package/src/locales/ckb/translations.json +7 -0
- package/src/locales/cs/translations.json +7 -0
- package/src/locales/da/translations.json +7 -0
- package/src/locales/en/translations.json +11 -0
- package/src/locales/en_US/translations.json +9 -0
- package/src/locales/es/translations.json +7 -0
- package/src/locales/es_419/translations.json +7 -0
- package/src/locales/fr/translations.json +7 -0
- package/src/locales/hi_IN/translations.json +7 -0
- package/src/locales/id/translations.json +7 -0
- package/src/locales/index.js +80 -0
- package/src/locales/km/translations.json +7 -0
- package/src/locales/lo/translations.json +7 -0
- package/src/locales/my/translations.json +7 -0
- package/src/locales/nb/translations.json +7 -0
- package/src/locales/nl/translations.json +7 -0
- package/src/locales/prs/translations.json +7 -0
- package/src/locales/ps/translations.json +7 -0
- package/src/locales/pt/translations.json +7 -0
- package/src/locales/pt_BR/translations.json +7 -0
- package/src/locales/ru/translations.json +7 -0
- package/src/locales/sv/translations.json +7 -0
- package/src/locales/tet/translations.json +7 -0
- package/src/locales/tg/translations.json +7 -0
- package/src/locales/uk/translations.json +7 -0
- package/src/locales/ur/translations.json +7 -0
- package/src/locales/uz_Latn/translations.json +7 -0
- package/src/locales/uz_UZ_Cyrl/translations.json +7 -0
- package/src/locales/uz_UZ_Latn/translations.json +7 -0
- package/src/locales/vi/translations.json +7 -0
- package/src/locales/zh/translations.json +9 -0
- package/src/locales/zh_CN/translations.json +7 -0
- package/src/multi-select/__tests__/multi-select.test.js +23 -0
- package/src/multi-select/__tests__/selection-list.test.js +102 -0
- package/src/multi-select/features/accepts_blur_cb/index.js +14 -0
- package/src/multi-select/features/accepts_blur_cb.feature +8 -0
- package/src/multi-select/features/accepts_focus_cb/index.js +14 -0
- package/src/multi-select/features/accepts_focus_cb.feature +6 -0
- package/src/multi-select/features/accepts_initial_focus/index.js +5 -0
- package/src/multi-select/features/accepts_initial_focus.feature +5 -0
- package/src/multi-select/features/accepts_loading/index.js +22 -0
- package/src/multi-select/features/accepts_loading.feature +14 -0
- package/src/multi-select/features/accepts_max_height/index.js +31 -0
- package/src/multi-select/features/accepts_max_height.feature +11 -0
- package/src/multi-select/features/accepts_placeholder/index.js +25 -0
- package/src/multi-select/features/accepts_placeholder.feature +10 -0
- package/src/multi-select/features/accepts_prefix/index.js +19 -0
- package/src/multi-select/features/accepts_prefix.feature +10 -0
- package/src/multi-select/features/allows_invalid_options/index.js +27 -0
- package/src/multi-select/features/allows_invalid_options.feature +12 -0
- package/src/multi-select/features/allows_selecting/index.js +81 -0
- package/src/multi-select/features/allows_selecting.feature +44 -0
- package/src/multi-select/features/can_be_cleared/index.js +22 -0
- package/src/multi-select/features/can_be_cleared.feature +6 -0
- package/src/multi-select/features/can_be_disabled/index.js +36 -0
- package/src/multi-select/features/can_be_disabled.feature +32 -0
- package/src/multi-select/features/can_be_empty/index.js +28 -0
- package/src/multi-select/features/can_be_empty.feature +16 -0
- package/src/multi-select/features/can_be_filtered/index.js +23 -0
- package/src/multi-select/features/can_be_filtered.feature +14 -0
- package/src/multi-select/features/can_be_opened_and_closed/index.js +32 -0
- package/src/multi-select/features/can_be_opened_and_closed.feature +41 -0
- package/src/multi-select/features/common/index.js +49 -0
- package/src/multi-select/features/duplicate_option_values/index.js +21 -0
- package/src/multi-select/features/duplicate_option_values.feature +7 -0
- package/src/multi-select/features/menu_width_matches_input/index.js +53 -0
- package/src/multi-select/features/menu_width_matches_input.feature +11 -0
- package/src/multi-select/features/position/index.js +160 -0
- package/src/multi-select/features/position.feature +46 -0
- package/src/multi-select/features/shows_selections/index.js +18 -0
- package/src/multi-select/features/shows_selections.feature +9 -0
- package/src/multi-select/filterable-menu.js +43 -0
- package/src/multi-select/index.js +1 -0
- package/src/multi-select/input.js +129 -0
- package/src/multi-select/menu.js +91 -0
- package/src/multi-select/multi-select.e2e.stories.js +407 -0
- package/src/multi-select/multi-select.js +148 -0
- package/src/multi-select/multi-select.prod.stories.js +408 -0
- package/src/multi-select/selection-list.js +79 -0
- package/src/multi-select-field/__tests__/multi-select-field.test.js +29 -0
- package/src/multi-select-field/features/accepts_help_text/index.js +9 -0
- package/src/multi-select-field/features/accepts_help_text.feature +5 -0
- package/src/multi-select-field/features/accepts_label/index.js +9 -0
- package/src/multi-select-field/features/accepts_label.feature +5 -0
- package/src/multi-select-field/features/accepts_validation_text/index.js +9 -0
- package/src/multi-select-field/features/accepts_validation_text.feature +5 -0
- package/src/multi-select-field/features/can_be_required/index.js +11 -0
- package/src/multi-select-field/features/can_be_required.feature +5 -0
- package/src/multi-select-field/features/has_default_clear_text/index.js +16 -0
- package/src/multi-select-field/features/has_default_clear_text.feature +6 -0
- package/src/multi-select-field/features/has_default_empty_text/index.js +13 -0
- package/src/multi-select-field/features/has_default_empty_text.feature +6 -0
- package/src/multi-select-field/features/has_default_filter_nomatch_text/index.js +17 -0
- package/src/multi-select-field/features/has_default_filter_nomatch_text.feature +7 -0
- package/src/multi-select-field/features/has_default_filter_placeholder/index.js +15 -0
- package/src/multi-select-field/features/has_default_filter_placeholder.feature +6 -0
- package/src/multi-select-field/features/has_default_loading_text/index.js +13 -0
- package/src/multi-select-field/features/has_default_loading_text.feature +6 -0
- package/src/multi-select-field/index.js +1 -0
- package/src/multi-select-field/multi-select-field.e2e.stories.js +45 -0
- package/src/multi-select-field/multi-select-field.js +178 -0
- package/src/multi-select-field/multi-select-field.prod.stories.js +137 -0
- package/src/multi-select-option/index.js +1 -0
- package/src/multi-select-option/multi-select-option.js +70 -0
- package/src/select/__tests__/select.test.js +31 -0
- package/src/select/debounce/debounce.js +30 -0
- package/src/select/debounce/debounce.spec.js +35 -0
- package/src/select/empty.js +28 -0
- package/src/select/filter-input.js +42 -0
- package/src/select/filterable-menu.js +106 -0
- package/src/select/index.js +14 -0
- package/src/select/input-clear-button.js +66 -0
- package/src/select/input-placeholder.js +30 -0
- package/src/select/input-prefix.js +32 -0
- package/src/select/input-wrapper.js +114 -0
- package/src/select/loading.js +33 -0
- package/src/select/menu-wrapper.js +52 -0
- package/src/select/no-match.js +28 -0
- package/src/select/option-helpers.js +34 -0
- package/src/select/select.js +256 -0
- package/src/simple-single-select/__stories__/DefaultPosition.js +37 -0
- package/src/simple-single-select/__stories__/Dense.js +17 -0
- package/src/simple-single-select/__stories__/Empty.js +15 -0
- package/src/simple-single-select/__stories__/EmptyWithEmptyNode.js +27 -0
- package/src/simple-single-select/__stories__/EmptyWithEmptyText.js +16 -0
- package/src/simple-single-select/__stories__/FlippedPosition.js +36 -0
- package/src/simple-single-select/__stories__/InfiniteLoading.js +65 -0
- package/src/simple-single-select/__stories__/Loading.js +15 -0
- package/src/simple-single-select/__stories__/ShiftedIntoView.js +35 -0
- package/src/simple-single-select/__stories__/WithClearButton.js +26 -0
- package/src/simple-single-select/__stories__/WithCustomLowMaxHeight.js +17 -0
- package/src/simple-single-select/__stories__/WithCustomOptions.js +78 -0
- package/src/simple-single-select/__stories__/WithDisabledOption.js +25 -0
- package/src/simple-single-select/__stories__/WithFilterField.js +30 -0
- package/src/simple-single-select/__stories__/WithInitialFocus.js +29 -0
- package/src/simple-single-select/__stories__/WithManyOptions.js +19 -0
- package/src/simple-single-select/__stories__/WithMultipleSelectsAndScrollableParent.js +65 -0
- package/src/simple-single-select/__stories__/WithNoMatchText.js +25 -0
- package/src/simple-single-select/__stories__/WithOnBlur.js +22 -0
- package/src/simple-single-select/__stories__/WithOnFocus.js +22 -0
- package/src/simple-single-select/__stories__/WithOptionsAndDisabled.js +17 -0
- package/src/simple-single-select/__stories__/WithOptionsAndLoading.js +23 -0
- package/src/simple-single-select/__stories__/WithOptionsAndLoadingText.js +24 -0
- package/src/simple-single-select/__stories__/WithPlaceholder.js +18 -0
- package/src/simple-single-select/__stories__/WithPlaceholderAndSelection.js +20 -0
- package/src/simple-single-select/__stories__/WithPrefix.js +17 -0
- package/src/simple-single-select/__stories__/WithPrefixAndSelection.js +20 -0
- package/src/simple-single-select/__stories__/WithRTL.js +29 -0
- package/src/simple-single-select/__stories__/WithScrollingParent.js +51 -0
- package/src/simple-single-select/__stories__/WithSelection.js +19 -0
- package/src/simple-single-select/__stories__/WithSelectionAndDisabled.js +20 -0
- package/src/simple-single-select/__stories__/WithServerSideFilteringDemo.js +245 -0
- package/src/simple-single-select/__stories__/WithSimpleFilteringDemo.js +50 -0
- package/src/simple-single-select/__stories__/WithoutOptionsAndLoading.js +16 -0
- package/src/simple-single-select/__stories__/WithoutSelection.js +17 -0
- package/src/simple-single-select/__stories__/options.js +96 -0
- package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/CustomDataProvider.js +70 -0
- package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/dataElements.js +4271 -0
- package/src/simple-single-select/__stories__/simple-single-select-server-side-filtering/index.js +1 -0
- package/src/simple-single-select/features/keyboard-interactions.test.e2e.js +581 -0
- package/src/simple-single-select/features/menu-positioning.test.e2e.js +187 -0
- package/src/simple-single-select/index.js +2 -0
- package/src/simple-single-select/is-option-hidden.js +21 -0
- package/src/simple-single-select/menu/empty.js +27 -0
- package/src/simple-single-select/menu/filter.js +61 -0
- package/src/simple-single-select/menu/index.js +1 -0
- package/src/simple-single-select/menu/loading.js +38 -0
- package/src/simple-single-select/menu/menu.js +171 -0
- package/src/simple-single-select/menu/no-match.js +28 -0
- package/src/simple-single-select/menu/option.js +161 -0
- package/src/simple-single-select/menu/options-list.js +107 -0
- package/src/simple-single-select/selected-value/clear-button.js +71 -0
- package/src/simple-single-select/selected-value/container.js +146 -0
- package/src/simple-single-select/selected-value/index.js +1 -0
- package/src/simple-single-select/selected-value/placeholder.js +24 -0
- package/src/simple-single-select/selected-value/prefix.js +26 -0
- package/src/simple-single-select/selected-value/selected-value.js +174 -0
- package/src/simple-single-select/shared-prop-types.js +8 -0
- package/src/simple-single-select/simple-single-select.e2e.stories.js +216 -0
- package/src/simple-single-select/simple-single-select.js +389 -0
- package/src/simple-single-select/simple-single-select.prod.stories.js +41 -0
- package/src/simple-single-select/simple-single-select.test.js +1136 -0
- package/src/simple-single-select/use-handle-key-press/index.js +2 -0
- package/src/simple-single-select/use-handle-key-press/use-focus-option.js +24 -0
- package/src/simple-single-select/use-handle-key-press/use-handle-key-press-on-combobox.js +259 -0
- package/src/simple-single-select/use-handle-key-press/use-handle-key-press-on-filter-input.js +147 -0
- package/src/simple-single-select/use-handle-key-press/use-handle-typing.js +79 -0
- package/src/simple-single-select/use-handle-key-press/use-highlight-first-option-on-previous-page.js +62 -0
- package/src/simple-single-select/use-handle-key-press/use-highlight-first-visible-option.js +38 -0
- package/src/simple-single-select/use-handle-key-press/use-highlight-last-option-on-next-page.js +60 -0
- package/src/simple-single-select/use-handle-key-press/use-highlight-last-visible-option.js +52 -0
- package/src/simple-single-select/use-handle-key-press/use-page-down.js +50 -0
- package/src/simple-single-select/use-handle-key-press/use-page-up.js +50 -0
- package/src/simple-single-select/use-handle-key-press/utils.js +23 -0
- package/src/simple-single-select-field/index.js +1 -0
- package/src/simple-single-select-field/simple-single-select-field.js +198 -0
- package/src/simple-single-select-field/simple-single-select-field.prod.stories.js +188 -0
- package/src/simple-single-select-field/simple-single-select-field.test.js +144 -0
- package/src/single-select/__tests__/selection.test.js +102 -0
- package/src/single-select/__tests__/single-select.test.js +23 -0
- package/src/single-select/features/accepts_blur_cb/index.js +14 -0
- package/src/single-select/features/accepts_blur_cb.feature +8 -0
- package/src/single-select/features/accepts_focus_cb/index.js +14 -0
- package/src/single-select/features/accepts_focus_cb.feature +6 -0
- package/src/single-select/features/accepts_initial_focus/index.js +5 -0
- package/src/single-select/features/accepts_initial_focus.feature +5 -0
- package/src/single-select/features/accepts_loading/index.js +22 -0
- package/src/single-select/features/accepts_loading.feature +14 -0
- package/src/single-select/features/accepts_max_height/index.js +31 -0
- package/src/single-select/features/accepts_max_height.feature +11 -0
- package/src/single-select/features/accepts_placeholder/index.js +25 -0
- package/src/single-select/features/accepts_placeholder.feature +10 -0
- package/src/single-select/features/accepts_prefix/index.js +19 -0
- package/src/single-select/features/accepts_prefix.feature +10 -0
- package/src/single-select/features/allows_invalid_options/index.js +28 -0
- package/src/single-select/features/allows_invalid_options.feature +12 -0
- package/src/single-select/features/allows_selecting/index.js +38 -0
- package/src/single-select/features/allows_selecting.feature +21 -0
- package/src/single-select/features/can_be_cleared/index.js +22 -0
- package/src/single-select/features/can_be_cleared.feature +6 -0
- package/src/single-select/features/can_be_disabled/index.js +39 -0
- package/src/single-select/features/can_be_disabled.feature +32 -0
- package/src/single-select/features/can_be_empty/index.js +28 -0
- package/src/single-select/features/can_be_empty.feature +16 -0
- package/src/single-select/features/can_be_filtered/index.js +23 -0
- package/src/single-select/features/can_be_filtered.feature +14 -0
- package/src/single-select/features/can_be_opened_and_closed/index.js +32 -0
- package/src/single-select/features/can_be_opened_and_closed.feature +41 -0
- package/src/single-select/features/common/index.js +44 -0
- package/src/single-select/features/duplicate_option_values/index.js +26 -0
- package/src/single-select/features/duplicate_option_values.feature +7 -0
- package/src/single-select/features/menu_width_matches_input/index.js +53 -0
- package/src/single-select/features/menu_width_matches_input.feature +11 -0
- package/src/single-select/features/position/index.js +111 -0
- package/src/single-select/features/position.feature +26 -0
- package/src/single-select/features/shows_selections/index.js +9 -0
- package/src/single-select/features/shows_selections.feature +5 -0
- package/src/single-select/filterable-menu.js +41 -0
- package/src/single-select/index.js +1 -0
- package/src/single-select/input.js +101 -0
- package/src/single-select/menu.js +75 -0
- package/src/single-select/selection.js +60 -0
- package/src/single-select/single-select.e2e.stories.js +376 -0
- package/src/single-select/single-select.js +146 -0
- package/src/single-select/single-select.prod.stories.js +358 -0
- package/src/single-select-field/__tests__/single-select-field.test.js +29 -0
- package/src/single-select-field/features/accepts_help_text/index.js +9 -0
- package/src/single-select-field/features/accepts_help_text.feature +5 -0
- package/src/single-select-field/features/accepts_label/index.js +9 -0
- package/src/single-select-field/features/accepts_label.feature +5 -0
- package/src/single-select-field/features/accepts_validation_text/index.js +9 -0
- package/src/single-select-field/features/accepts_validation_text.feature +5 -0
- package/src/single-select-field/features/can_be_required/index.js +11 -0
- package/src/single-select-field/features/can_be_required.feature +5 -0
- package/src/single-select-field/features/has_default_clear_text/index.js +16 -0
- package/src/single-select-field/features/has_default_clear_text.feature +6 -0
- package/src/single-select-field/features/has_default_empty_text/index.js +13 -0
- package/src/single-select-field/features/has_default_empty_text.feature +6 -0
- package/src/single-select-field/features/has_default_filter_nomatch_text/index.js +17 -0
- package/src/single-select-field/features/has_default_filter_nomatch_text.feature +7 -0
- package/src/single-select-field/features/has_default_filter_placeholder/index.js +15 -0
- package/src/single-select-field/features/has_default_filter_placeholder.feature +6 -0
- package/src/single-select-field/features/has_default_loading_text/index.js +13 -0
- package/src/single-select-field/features/has_default_loading_text.feature +6 -0
- package/src/single-select-field/index.js +1 -0
- package/src/single-select-field/single-select-field.e2e.stories.js +45 -0
- package/src/single-select-field/single-select-field.js +178 -0
- package/src/single-select-field/single-select-field.prod.stories.js +146 -0
- package/src/single-select-option/index.js +1 -0
- package/src/single-select-option/single-select-option.js +84 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Feature: Filtering the MultiSelect options
|
|
2
|
+
|
|
3
|
+
Scenario: The user enters a filter string to filter the options
|
|
4
|
+
Given a filterable MultiSelect with options is rendered
|
|
5
|
+
And the MultiSelect is open
|
|
6
|
+
When the user enters a filter string
|
|
7
|
+
Then the matching options are displayed
|
|
8
|
+
|
|
9
|
+
Scenario: The user enters a filter string that doesn't match any options
|
|
10
|
+
Given a filterable MultiSelect with options is rendered
|
|
11
|
+
And the MultiSelect is open
|
|
12
|
+
When the user enters a filter string that doesn't match any options
|
|
13
|
+
Then the no match text is displayed
|
|
14
|
+
And the options are not rendered
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Given, When } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('a MultiSelect with options is rendered', () => {
|
|
4
|
+
cy.visitStory('MultiSelect', 'With options')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Given('the MultiSelect is closed', () => {
|
|
8
|
+
cy.contains('option one').should('not.exist')
|
|
9
|
+
cy.contains('option two').should('not.exist')
|
|
10
|
+
cy.contains('option three').should('not.exist')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
Given('the MultiSelect is focused', () => {
|
|
14
|
+
cy.get('[data-test="dhis2-uicore-select-input"]').focus()
|
|
15
|
+
cy.focused().should('have.attr', 'data-test', 'dhis2-uicore-select-input')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
When('the down arrowkey is pressed on the focused element', () => {
|
|
19
|
+
cy.focused().type('{downarrow}')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
When('the spacebar is pressed on the focused element', () => {
|
|
23
|
+
cy.focused().type(' ')
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
When('the up arrowkey is pressed on the focused element', () => {
|
|
27
|
+
cy.focused().type('{uparrow}')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
When('the escape key is pressed on the focused element', () => {
|
|
31
|
+
cy.focused().type('{esc}')
|
|
32
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Feature: Opening and closing the MultiSelect
|
|
2
|
+
|
|
3
|
+
Scenario: The user clicks the MultiSelect input to display the options
|
|
4
|
+
Given a MultiSelect with options is rendered
|
|
5
|
+
And the MultiSelect is closed
|
|
6
|
+
When the MultiSelect input is clicked
|
|
7
|
+
Then the options are displayed
|
|
8
|
+
|
|
9
|
+
Scenario: The user presses the down arrowkey to display the options
|
|
10
|
+
Given a MultiSelect with options is rendered
|
|
11
|
+
And the MultiSelect is closed
|
|
12
|
+
And the MultiSelect is focused
|
|
13
|
+
When the down arrowkey is pressed on the focused element
|
|
14
|
+
Then the options are displayed
|
|
15
|
+
|
|
16
|
+
Scenario: The user presses the up arrowkey to display the options
|
|
17
|
+
Given a MultiSelect with options is rendered
|
|
18
|
+
And the MultiSelect is closed
|
|
19
|
+
And the MultiSelect is focused
|
|
20
|
+
When the up arrowkey is pressed on the focused element
|
|
21
|
+
Then the options are displayed
|
|
22
|
+
|
|
23
|
+
Scenario: The user presses the spacebar to display the options
|
|
24
|
+
Given a MultiSelect with options is rendered
|
|
25
|
+
And the MultiSelect is closed
|
|
26
|
+
And the MultiSelect is focused
|
|
27
|
+
When the spacebar is pressed on the focused element
|
|
28
|
+
Then the options are displayed
|
|
29
|
+
|
|
30
|
+
Scenario: The user clicks the backdrop layer to hide the options
|
|
31
|
+
Given a MultiSelect with options is rendered
|
|
32
|
+
And the MultiSelect is open
|
|
33
|
+
When the user clicks the backdrop layer
|
|
34
|
+
Then the options are not rendered
|
|
35
|
+
|
|
36
|
+
Scenario: The user presses the escape key to hide the options
|
|
37
|
+
Given a MultiSelect with options is rendered
|
|
38
|
+
And the MultiSelect is open
|
|
39
|
+
And the MultiSelect is focused
|
|
40
|
+
When the escape key is pressed on the focused element
|
|
41
|
+
Then the options are not rendered
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('a MultiSelect with options and onChange handler is rendered', () => {
|
|
4
|
+
cy.visitStory('MultiSelect', 'With options and on change')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Given(
|
|
8
|
+
'a MultiSelect with options, a selection and onChange handler is rendered',
|
|
9
|
+
() => {
|
|
10
|
+
cy.visitStory('MultiSelect', 'With options, a selection and on change')
|
|
11
|
+
}
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
Given('a MultiSelect is rendered to which options can be added', () => {
|
|
15
|
+
cy.visitStory('MultiSelect', 'With options that can be added to the input')
|
|
16
|
+
cy.get('[data-test="dhis2-uicore-multiselect"]').should('exist')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
Given('the MultiSelect is open', () => {
|
|
20
|
+
cy.get('[data-test="dhis2-uicore-select-input"]').click()
|
|
21
|
+
|
|
22
|
+
cy.contains('option one').should('be.visible')
|
|
23
|
+
cy.contains('option two').should('be.visible')
|
|
24
|
+
cy.contains('option three').should('be.visible')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
When('the MultiSelect input is clicked', () => {
|
|
28
|
+
cy.get('[data-test="dhis2-uicore-select-input"]').click()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
When('the user clicks the backdrop layer', () => {
|
|
32
|
+
cy.get('[data-test="dhis2-uicore-layer"]').click()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
Then('the options are not rendered', () => {
|
|
36
|
+
cy.contains('option one').should('not.exist')
|
|
37
|
+
cy.contains('option two').should('not.exist')
|
|
38
|
+
cy.contains('option three').should('not.exist')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
Then('the options are displayed', () => {
|
|
42
|
+
cy.contains('option one').should('be.visible')
|
|
43
|
+
cy.contains('option two').should('be.visible')
|
|
44
|
+
cy.contains('option three').should('be.visible')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
Then('the MultiSelect has focus', () => {
|
|
48
|
+
cy.focused().should('have.attr', 'data-test', 'dhis2-uicore-select-input')
|
|
49
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given(
|
|
4
|
+
'a MultiSelect with options with a duplicate value and this value is selected',
|
|
5
|
+
() => {
|
|
6
|
+
cy.visitStory('MultiSelect', 'With duplicate selected option values')
|
|
7
|
+
}
|
|
8
|
+
)
|
|
9
|
+
Then(
|
|
10
|
+
'the first option with the selected value is displayed in the input',
|
|
11
|
+
() => {
|
|
12
|
+
cy.get('[data-test="dhis2-uicore-select-input"]').should(
|
|
13
|
+
'contain',
|
|
14
|
+
'option one'
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
)
|
|
18
|
+
Then('both options are highlighted in the dropdown', () => {
|
|
19
|
+
cy.get('input[name="option one"]').should('have.attr', 'checked')
|
|
20
|
+
cy.get('input[name="option one a"]').should('have.attr', 'checked')
|
|
21
|
+
})
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Feature: Duplicate option values result in a conflict between the input and dropdown UI
|
|
2
|
+
|
|
3
|
+
Scenario: The MultiSelect has options with a duplicate value and this value is selected
|
|
4
|
+
Given a MultiSelect with options with a duplicate value and this value is selected
|
|
5
|
+
And the MultiSelect is open
|
|
6
|
+
Then the first option with the selected value is displayed in the input
|
|
7
|
+
But both options are highlighted in the dropdown
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('a MultiSelect with hidden sibling elements', () => {
|
|
4
|
+
cy.visitStory('MultiSelect', 'Menu width changing')
|
|
5
|
+
cy.get('[data-test="dhis2-uicore-multiselect"]').then(($el) => {
|
|
6
|
+
cy.wrap($el.outerWidth()).as('originalWidth')
|
|
7
|
+
})
|
|
8
|
+
})
|
|
9
|
+
When('the button is clicked', () => {
|
|
10
|
+
cy.get('[data-test="dhis2-uicore-button"]').click()
|
|
11
|
+
})
|
|
12
|
+
Then('the siblings are displayed', () => {
|
|
13
|
+
cy.get('.toggler').should('exist').and('have.length', 2)
|
|
14
|
+
})
|
|
15
|
+
Then('the menu width has decreased', () => {
|
|
16
|
+
cy.get('[data-test="dhis2-uicore-multiselect"]').then(($el) => {
|
|
17
|
+
const newWidth = $el.outerWidth()
|
|
18
|
+
cy.get('@originalWidth').should('be.greaterThan', newWidth)
|
|
19
|
+
})
|
|
20
|
+
})
|
|
21
|
+
When('the MultiSelect menu is open', () => {
|
|
22
|
+
cy.get('[data-test="dhis2-uicore-select-menu-menuwrapper"]').should(
|
|
23
|
+
'be.visible'
|
|
24
|
+
)
|
|
25
|
+
})
|
|
26
|
+
Then('the MultiSelect input is left aligned with the menu', () => {
|
|
27
|
+
const selectDataTest = '[data-test="dhis2-uicore-multiselect"]'
|
|
28
|
+
const menuDataTest = '[data-test="dhis2-uicore-select-menu-menuwrapper"]'
|
|
29
|
+
|
|
30
|
+
cy.getAll(selectDataTest, menuDataTest).should(([inputs, menus]) => {
|
|
31
|
+
expect(inputs.length).to.equal(1)
|
|
32
|
+
expect(menus.length).to.equal(1)
|
|
33
|
+
|
|
34
|
+
const $input = inputs[0]
|
|
35
|
+
const $menu = menus[0]
|
|
36
|
+
|
|
37
|
+
const inputRect = $input.getBoundingClientRect()
|
|
38
|
+
const menuRect = $menu.getBoundingClientRect()
|
|
39
|
+
|
|
40
|
+
expect(Math.round(inputRect.left)).to.equal(Math.round(menuRect.left))
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
When('the MultiSelect input and menu have the same width', () => {
|
|
44
|
+
const inputSelector = '[data-test="dhis2-uicore-select"]'
|
|
45
|
+
const menuSelector = '[data-test="dhis2-uicore-select-menu-menuwrapper"]'
|
|
46
|
+
|
|
47
|
+
cy.getAll(inputSelector, menuSelector).should(([$input, $menu]) => {
|
|
48
|
+
const inputWidth = Math.round($input.outerWidth())
|
|
49
|
+
const menuWidth = Math.round($menu.outerWidth())
|
|
50
|
+
|
|
51
|
+
expect(inputWidth).to.equal(menuWidth)
|
|
52
|
+
})
|
|
53
|
+
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Feature: The menu always has the same size as the input
|
|
2
|
+
|
|
3
|
+
Scenario: The MultiSelect input changes width while the menu is closed
|
|
4
|
+
Given a MultiSelect with hidden sibling elements
|
|
5
|
+
When the button is clicked
|
|
6
|
+
Then the siblings are displayed
|
|
7
|
+
And the menu width has decreased
|
|
8
|
+
When the MultiSelect input is clicked
|
|
9
|
+
Then the MultiSelect menu is open
|
|
10
|
+
And the MultiSelect input is left aligned with the menu
|
|
11
|
+
And the MultiSelect input and menu have the same width
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Given, Then, When } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given(
|
|
4
|
+
'there is enough space below the anchor to fit the MultiSelect menu',
|
|
5
|
+
() => {
|
|
6
|
+
cy.visitStory('MultiSelect', 'Default position')
|
|
7
|
+
}
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
Given(
|
|
11
|
+
'there is not enough space below the anchor to fit the MultiSelect menu',
|
|
12
|
+
() => {
|
|
13
|
+
cy.visitStory('MultiSelect', 'Flipped position')
|
|
14
|
+
}
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
Given(
|
|
18
|
+
'there is not enough space above or below the anchor to fit the MultiSelect menu',
|
|
19
|
+
() => {
|
|
20
|
+
cy.visitStory('MultiSelect', 'Shifted into view')
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
Given('the input is empty', () => {
|
|
25
|
+
cy.get('[data-test="dhis2-uicore-select-input"]')
|
|
26
|
+
.should('exist')
|
|
27
|
+
.should('have.length', 1)
|
|
28
|
+
.then((inputs) => {
|
|
29
|
+
const $input = inputs[0]
|
|
30
|
+
const inputRect = $input.getBoundingClientRect()
|
|
31
|
+
|
|
32
|
+
return inputRect.height
|
|
33
|
+
})
|
|
34
|
+
.as('emptyInputHeight')
|
|
35
|
+
|
|
36
|
+
cy.get('[data-test="dhis2-uicore-select-input"] .root').should('be.empty')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
When('the MultiSelect is clicked', () => {
|
|
40
|
+
cy.get('[data-test="dhis2-uicore-multiselect"]').click()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
When('the window is scrolled down', () => {
|
|
44
|
+
cy.scrollTo(0, 800)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
When('the window is resized to a greater width', () => {
|
|
48
|
+
cy.viewport(1200, 660)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
When('an option is clicked', () => {
|
|
52
|
+
cy.contains('option one').click()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
Then('the Input remains the same height', () => {
|
|
56
|
+
const emptyInputHeight = '@emptyInputHeight'
|
|
57
|
+
const inputDataTest = '[data-test="dhis2-uicore-select-input"]'
|
|
58
|
+
|
|
59
|
+
cy.getAll(emptyInputHeight, inputDataTest).should(
|
|
60
|
+
([emptyInputHeight, inputs]) => {
|
|
61
|
+
expect(inputs.length).to.equal(1)
|
|
62
|
+
|
|
63
|
+
const $input = inputs[0]
|
|
64
|
+
const inputRect = $input.getBoundingClientRect()
|
|
65
|
+
|
|
66
|
+
expect(inputRect.height).to.equal(emptyInputHeight)
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
Then('the top of the menu is aligned with the bottom of the input', () => {
|
|
72
|
+
const selectDataTest = '[data-test="dhis2-uicore-multiselect"]'
|
|
73
|
+
const menuDataTest = '[data-test="dhis2-uicore-select-menu-menuwrapper"]'
|
|
74
|
+
|
|
75
|
+
cy.getAll(selectDataTest, menuDataTest).should(([selects, menus]) => {
|
|
76
|
+
expect(selects.length).to.equal(1)
|
|
77
|
+
expect(menus.length).to.equal(1)
|
|
78
|
+
|
|
79
|
+
const $select = selects[0]
|
|
80
|
+
const $menu = menus[0]
|
|
81
|
+
|
|
82
|
+
const selectRect = $select.getBoundingClientRect()
|
|
83
|
+
const menuRect = $menu.getBoundingClientRect()
|
|
84
|
+
|
|
85
|
+
expect(menuRect.top).to.be.closeTo(selectRect.bottom, 1)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
Then('the bottom of the menu is aligned with the top of the input', () => {
|
|
90
|
+
const selectDataTest = '[data-test="dhis2-uicore-multiselect"]'
|
|
91
|
+
const menuDataTest = '[data-test="dhis2-uicore-select-menu-menuwrapper"]'
|
|
92
|
+
|
|
93
|
+
cy.getAll(selectDataTest, menuDataTest).should(([selects, menus]) => {
|
|
94
|
+
expect(selects.length).to.equal(1)
|
|
95
|
+
expect(menus.length).to.equal(1)
|
|
96
|
+
|
|
97
|
+
const $select = selects[0]
|
|
98
|
+
const $menu = menus[0]
|
|
99
|
+
|
|
100
|
+
const selectRect = $select.getBoundingClientRect()
|
|
101
|
+
const menuRect = $menu.getBoundingClientRect()
|
|
102
|
+
|
|
103
|
+
expect(selectRect.top).to.be.closeTo(menuRect.bottom, 1)
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
Then('it is rendered on top of the MultiSelect', () => {
|
|
108
|
+
const selectDataTest = '[data-test="dhis2-uicore-multiselect"]'
|
|
109
|
+
const menuDataTest = '[data-test="dhis2-uicore-select-menu-menuwrapper"]'
|
|
110
|
+
|
|
111
|
+
cy.getAll(selectDataTest, menuDataTest).should(([selects, menus]) => {
|
|
112
|
+
expect(selects.length).to.equal(1)
|
|
113
|
+
expect(menus.length).to.equal(1)
|
|
114
|
+
|
|
115
|
+
const $select = selects[0]
|
|
116
|
+
const $menu = menus[0]
|
|
117
|
+
|
|
118
|
+
const selectRect = $select.getBoundingClientRect()
|
|
119
|
+
const menuRect = $menu.getBoundingClientRect()
|
|
120
|
+
|
|
121
|
+
expect(selectRect.top).to.be.greaterThan(menuRect.top)
|
|
122
|
+
expect(menuRect.bottom).to.be.greaterThan(selectRect.bottom)
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
Then('the left of the Menu is aligned with the left of the Input', () => {
|
|
127
|
+
const selectDataTest = '[data-test="dhis2-uicore-multiselect"]'
|
|
128
|
+
const menuDataTest = '[data-test="dhis2-uicore-select-menu-menuwrapper"]'
|
|
129
|
+
|
|
130
|
+
cy.getAll(selectDataTest, menuDataTest).should(([selects, menus]) => {
|
|
131
|
+
expect(selects.length).to.equal(1)
|
|
132
|
+
expect(menus.length).to.equal(1)
|
|
133
|
+
|
|
134
|
+
const $select = selects[0]
|
|
135
|
+
const $menu = menus[0]
|
|
136
|
+
|
|
137
|
+
const selectRect = $select.getBoundingClientRect()
|
|
138
|
+
const menuRect = $menu.getBoundingClientRect()
|
|
139
|
+
|
|
140
|
+
expect(selectRect.left).to.be.closeTo(menuRect.left, 1)
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
Then('the Menu and the Input have an equal width', () => {
|
|
145
|
+
const inputDataTest = '[data-test="dhis2-uicore-multiselect"] .root-input'
|
|
146
|
+
const menuDataTest = '[data-test="dhis2-uicore-select-menu-menuwrapper"]'
|
|
147
|
+
|
|
148
|
+
cy.getAll(inputDataTest, menuDataTest).should(([inputs, menus]) => {
|
|
149
|
+
expect(inputs.length).to.equal(1)
|
|
150
|
+
expect(menus.length).to.equal(1)
|
|
151
|
+
|
|
152
|
+
const $input = inputs[0]
|
|
153
|
+
const $menu = menus[0]
|
|
154
|
+
|
|
155
|
+
const inputRect = $input.getBoundingClientRect()
|
|
156
|
+
const menuRect = $menu.getBoundingClientRect()
|
|
157
|
+
|
|
158
|
+
expect(inputRect.width).to.be.closeTo(menuRect.width, 1)
|
|
159
|
+
})
|
|
160
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Feature: Position of MultiSelect menu dropdown
|
|
2
|
+
|
|
3
|
+
Scenario: Default rendering
|
|
4
|
+
Given there is enough space below the anchor to fit the MultiSelect menu
|
|
5
|
+
When the MultiSelect is clicked
|
|
6
|
+
Then the top of the menu is aligned with the bottom of the input
|
|
7
|
+
And the left of the Menu is aligned with the left of the Input
|
|
8
|
+
|
|
9
|
+
Scenario: Flipped rendering when insufficient space below
|
|
10
|
+
Given there is not enough space below the anchor to fit the MultiSelect menu
|
|
11
|
+
When the MultiSelect is clicked
|
|
12
|
+
Then the bottom of the menu is aligned with the top of the input
|
|
13
|
+
And the left of the Menu is aligned with the left of the Input
|
|
14
|
+
|
|
15
|
+
Scenario: Shifting into view when insufficient space below and above
|
|
16
|
+
Given there is not enough space above or below the anchor to fit the MultiSelect menu
|
|
17
|
+
When the MultiSelect is clicked
|
|
18
|
+
Then it is rendered on top of the MultiSelect
|
|
19
|
+
And the left of the Menu is aligned with the left of the Input
|
|
20
|
+
|
|
21
|
+
Scenario: Staying in position when the window is scrolled
|
|
22
|
+
Given there is enough space below the anchor to fit the MultiSelect menu
|
|
23
|
+
When the MultiSelect is clicked
|
|
24
|
+
And the window is scrolled down
|
|
25
|
+
Then the top of the menu is aligned with the bottom of the input
|
|
26
|
+
And the left of the Menu is aligned with the left of the Input
|
|
27
|
+
|
|
28
|
+
Scenario: Adusting the menu width when the window resizes
|
|
29
|
+
Given there is enough space below the anchor to fit the MultiSelect menu
|
|
30
|
+
When the MultiSelect is clicked
|
|
31
|
+
Then the left of the Menu is aligned with the left of the Input
|
|
32
|
+
And the Menu and the Input have an equal width
|
|
33
|
+
When the window is resized to a greater width
|
|
34
|
+
Then the left of the Menu is aligned with the left of the Input
|
|
35
|
+
And the Menu and the Input have an equal width
|
|
36
|
+
|
|
37
|
+
Scenario: Positioning the menu when an option is selected
|
|
38
|
+
Given a MultiSelect is rendered to which options can be added
|
|
39
|
+
And the input is empty
|
|
40
|
+
When the MultiSelect is clicked
|
|
41
|
+
Then the top of the menu is aligned with the bottom of the input
|
|
42
|
+
And the left of the Menu is aligned with the left of the Input
|
|
43
|
+
When an option is clicked
|
|
44
|
+
Then the Input remains the same height
|
|
45
|
+
And the top of the menu is aligned with the bottom of the input
|
|
46
|
+
And the left of the Menu is aligned with the left of the Input
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
|
|
2
|
+
|
|
3
|
+
Given('a MultiSelect with options and a selection is rendered', () => {
|
|
4
|
+
cy.visitStory('MultiSelect', 'With options and a selection')
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
Given('a MultiSelect with options and multiple selections is rendered', () => {
|
|
8
|
+
cy.visitStory('MultiSelect', 'With options and multiple selections')
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
Then('the selection is displayed', () => {
|
|
12
|
+
cy.contains('option one').should('be.visible')
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
Then('the selections are displayed', () => {
|
|
16
|
+
cy.contains('option one').should('be.visible')
|
|
17
|
+
cy.contains('option two').should('be.visible')
|
|
18
|
+
})
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Feature: Show current selections
|
|
2
|
+
|
|
3
|
+
Scenario: The multiselect has a single selection
|
|
4
|
+
Given a MultiSelect with options and a selection is rendered
|
|
5
|
+
Then the selection is displayed
|
|
6
|
+
|
|
7
|
+
Scenario: The multiselect has multiple selections
|
|
8
|
+
Given a MultiSelect with options and multiple selections is rendered
|
|
9
|
+
Then the selections are displayed
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { FilterableMenu as CommonFilterableMenu } from '../select/index.js'
|
|
4
|
+
import { Menu } from './menu.js'
|
|
5
|
+
|
|
6
|
+
const FilterableMenu = ({
|
|
7
|
+
dataTest,
|
|
8
|
+
options,
|
|
9
|
+
onChange,
|
|
10
|
+
selected,
|
|
11
|
+
empty,
|
|
12
|
+
handleClose,
|
|
13
|
+
handleFocusInput,
|
|
14
|
+
placeholder,
|
|
15
|
+
noMatchText,
|
|
16
|
+
}) => (
|
|
17
|
+
<CommonFilterableMenu
|
|
18
|
+
dataTest={dataTest}
|
|
19
|
+
options={options}
|
|
20
|
+
onChange={onChange}
|
|
21
|
+
selected={selected}
|
|
22
|
+
empty={empty}
|
|
23
|
+
handleClose={handleClose}
|
|
24
|
+
handleFocusInput={handleFocusInput}
|
|
25
|
+
placeholder={placeholder}
|
|
26
|
+
noMatchText={noMatchText}
|
|
27
|
+
Menu={Menu}
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
FilterableMenu.propTypes = {
|
|
32
|
+
dataTest: PropTypes.string.isRequired,
|
|
33
|
+
noMatchText: PropTypes.string.isRequired,
|
|
34
|
+
empty: PropTypes.node,
|
|
35
|
+
handleClose: PropTypes.func,
|
|
36
|
+
handleFocusInput: PropTypes.func,
|
|
37
|
+
options: PropTypes.node,
|
|
38
|
+
placeholder: PropTypes.string,
|
|
39
|
+
selected: PropTypes.arrayOf(PropTypes.string),
|
|
40
|
+
onChange: PropTypes.func,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { FilterableMenu }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MultiSelect } from './multi-select.js'
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { requiredIf } from '@dhis2/prop-types'
|
|
2
|
+
import { colors } from '@dhis2/ui-constants'
|
|
3
|
+
import cx from 'classnames'
|
|
4
|
+
import PropTypes from 'prop-types'
|
|
5
|
+
import React from 'react'
|
|
6
|
+
import i18n from '../locales/index.js'
|
|
7
|
+
import {
|
|
8
|
+
InputClearButton,
|
|
9
|
+
InputPlaceholder,
|
|
10
|
+
InputPrefix,
|
|
11
|
+
} from '../select/index.js'
|
|
12
|
+
import { SelectionList } from './selection-list.js'
|
|
13
|
+
|
|
14
|
+
const Input = ({
|
|
15
|
+
selected,
|
|
16
|
+
onChange,
|
|
17
|
+
clearable,
|
|
18
|
+
clearText,
|
|
19
|
+
placeholder,
|
|
20
|
+
dataTest,
|
|
21
|
+
prefix,
|
|
22
|
+
options,
|
|
23
|
+
className,
|
|
24
|
+
disabled,
|
|
25
|
+
inputMaxHeight = '100px',
|
|
26
|
+
collapseSelectionAfter,
|
|
27
|
+
}) => {
|
|
28
|
+
const hasSelection = selected.length > 0
|
|
29
|
+
const shouldCollapse =
|
|
30
|
+
hasSelection &&
|
|
31
|
+
typeof collapseSelectionAfter === 'number' &&
|
|
32
|
+
selected.length > collapseSelectionAfter
|
|
33
|
+
const onClear = (e) => {
|
|
34
|
+
const data = { selected: [] }
|
|
35
|
+
|
|
36
|
+
e.stopPropagation()
|
|
37
|
+
onChange(data, e)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div className={cx('root', className)}>
|
|
42
|
+
<InputPrefix prefix={prefix} dataTest={`${dataTest}-prefix`} />
|
|
43
|
+
{!hasSelection && !prefix && (
|
|
44
|
+
<InputPlaceholder
|
|
45
|
+
placeholder={placeholder}
|
|
46
|
+
dataTest={`${dataTest}-placeholder`}
|
|
47
|
+
/>
|
|
48
|
+
)}
|
|
49
|
+
{hasSelection && shouldCollapse && (
|
|
50
|
+
<span
|
|
51
|
+
className="collapsed-selection-text"
|
|
52
|
+
data-test={`${dataTest}-selection-count`}
|
|
53
|
+
>
|
|
54
|
+
{i18n.t('{{count}} selected', { count: selected.length })}
|
|
55
|
+
</span>
|
|
56
|
+
)}
|
|
57
|
+
{hasSelection && !shouldCollapse && (
|
|
58
|
+
<div className="root-input">
|
|
59
|
+
{/* the wrapper div above is necessary to enforce wrapping on overflow */}
|
|
60
|
+
<SelectionList
|
|
61
|
+
selected={selected}
|
|
62
|
+
onChange={onChange}
|
|
63
|
+
options={options}
|
|
64
|
+
disabled={disabled}
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
)}
|
|
68
|
+
{hasSelection && clearable && !disabled && (
|
|
69
|
+
<div className="root-right">
|
|
70
|
+
<InputClearButton
|
|
71
|
+
onClear={onClear}
|
|
72
|
+
clearText={clearText}
|
|
73
|
+
dataTest={`${dataTest}-clear`}
|
|
74
|
+
/>
|
|
75
|
+
</div>
|
|
76
|
+
)}
|
|
77
|
+
|
|
78
|
+
<style jsx>{`
|
|
79
|
+
.root {
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
color: ${colors.grey900};
|
|
83
|
+
font-size: 14px;
|
|
84
|
+
line-height: 16px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.root-input {
|
|
88
|
+
overflow-y: auto;
|
|
89
|
+
flex: 1;
|
|
90
|
+
display: flex;
|
|
91
|
+
flex-flow: wrap;
|
|
92
|
+
gap: 4px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.root-right {
|
|
96
|
+
margin-inline-start: auto;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.collapsed-selection-text {
|
|
100
|
+
flex: 1;
|
|
101
|
+
user-select: none;
|
|
102
|
+
}
|
|
103
|
+
`}</style>
|
|
104
|
+
|
|
105
|
+
<style jsx>{`
|
|
106
|
+
.root-input {
|
|
107
|
+
max-height: ${inputMaxHeight};
|
|
108
|
+
}
|
|
109
|
+
`}</style>
|
|
110
|
+
</div>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Input.propTypes = {
|
|
115
|
+
dataTest: PropTypes.string.isRequired,
|
|
116
|
+
className: PropTypes.string,
|
|
117
|
+
clearText: requiredIf((props) => props.clearable, PropTypes.string),
|
|
118
|
+
clearable: PropTypes.bool,
|
|
119
|
+
collapseSelectionAfter: PropTypes.number,
|
|
120
|
+
disabled: PropTypes.bool,
|
|
121
|
+
inputMaxHeight: PropTypes.string,
|
|
122
|
+
options: PropTypes.node,
|
|
123
|
+
placeholder: PropTypes.string,
|
|
124
|
+
prefix: PropTypes.string,
|
|
125
|
+
selected: PropTypes.arrayOf(PropTypes.string),
|
|
126
|
+
onChange: PropTypes.func,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export { Input }
|