@jetbrains/ring-ui 4.1.0-beta.9 → 4.1.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/CHANGELOG.md +13 -0
- package/README.md +17 -15
- package/babel.config.js +3 -2
- package/components/alert/alert.js +9 -3
- package/components/alert/container.css +1 -1
- package/components/alert-service/alert-service.examples.css +18 -0
- package/components/alert-service/alert-service.examples.js +21 -0
- package/components/alert-service/alert-service.js +10 -3
- package/components/analytics/analytics__fus-plugin.js +1 -1
- package/components/auth/auth.test.js +14 -7
- package/components/auth/auth__core.js +64 -33
- package/components/auth-dialog/auth-dialog.js +1 -0
- package/components/avatar/avatar.css +4 -1
- package/components/avatar/avatar.examples.js +3 -2
- package/components/avatar/avatar.js +31 -6
- package/components/avatar/fallback-avatar.js +136 -0
- package/components/avatar-editor-ng/avatar-editor-ng.css +2 -2
- package/components/avatar-editor-ng/avatar-editor-ng.js +2 -1
- package/components/avatar-editor-ng/{avatar-editor-ng.html → avatar-editor-ng__template.js} +2 -2
- package/components/button/button.css +2 -2
- package/components/button/button.js +4 -1
- package/components/button-group/button-group.js +1 -1
- package/components/button-group/caption.js +1 -1
- package/components/button-ng/button-ng.js +1 -1
- package/components/button-set-ng/button-set-ng.js +3 -1
- package/components/checkbox/checkbox.css +1 -1
- package/components/code/code.js +1 -1
- package/components/confirm/confirm.js +1 -0
- package/components/confirm-service/confirm-service.js +5 -5
- package/components/content-layout/content-layout.css +1 -1
- package/components/data-list/data-list.css +1 -1
- package/components/date-picker/date-input.js +5 -4
- package/components/date-picker/date-picker.css +34 -22
- package/components/date-picker/date-picker.js +16 -14
- package/components/date-picker/date-popup.js +22 -7
- package/components/date-picker/month-names.js +8 -5
- package/components/date-picker/month.js +6 -2
- package/components/date-picker/weekdays.js +10 -2
- package/components/dialog/dialog.examples.js +3 -1
- package/components/dialog/dialog.js +5 -2
- package/components/dialog/dialog.test.js +1 -1
- package/components/dialog/dialog__body-scroll-preventer.js +2 -2
- package/components/dialog-ng/dialog-ng.js +7 -8
- package/components/dialog-ng/{dialog-ng.html → dialog-ng__template.js} +2 -2
- package/components/dropdown/dropdown.examples.js +36 -1
- package/components/dropdown-menu/dropdown-menu.examples.js +47 -0
- package/components/dropdown-menu/dropdown-menu.js +117 -0
- package/components/dropdown-menu/dropdown-menu.test.js +76 -0
- package/components/error-bubble/error-bubble-legacy.css +1 -1
- package/components/error-bubble/error-bubble.css +1 -1
- package/components/error-bubble/error-bubble.examples.js +1 -1
- package/components/error-page/error-page.css +2 -2
- package/components/footer-ng/footer-ng.js +13 -3
- package/components/form/form.css +2 -2
- package/components/form-ng/form-ng.js +3 -1
- package/components/global/global.css +1 -1
- package/components/global/theme.js +1 -1
- package/components/global/variables.css +8 -1
- package/components/grid/grid.css +10 -9
- package/components/header/header.css +1 -1
- package/components/header/header.examples.js +7 -8
- package/components/header/profile.js +10 -11
- package/components/http/http.js +1 -1
- package/components/icon/icon.css +5 -4
- package/components/island/island.css +4 -3
- package/components/island-legacy/island-legacy.css +3 -1
- package/components/list/list.js +6 -1
- package/components/list/list__custom.js +9 -3
- package/components/list/list__item.js +8 -2
- package/components/list/list__link.js +2 -1
- package/components/loader-inline/loader-inline.css +1 -1
- package/components/loader-screen/loader-screen.css +1 -1
- package/components/message/message.css +1 -1
- package/components/message/message.examples.js +8 -5
- package/components/pager/pager.js +5 -3
- package/components/permissions/permissions.js +1 -1
- package/components/progress-bar/progress-bar.css +1 -1
- package/components/progress-bar/progress-bar.examples.js +3 -3
- package/components/progress-bar/progress-bar.js +5 -2
- package/components/progress-bar/progress-bar.test.js +12 -13
- package/components/progress-bar-ng/progress-bar-ng.examples.js +3 -3
- package/components/query-assist/query-assist.css +13 -3
- package/components/query-assist/query-assist.examples.js +3 -1
- package/components/query-assist/query-assist.js +56 -12
- package/components/query-assist/query-assist.test.js +37 -5
- package/components/save-field-ng/save-field-ng.css +0 -3
- package/components/save-field-ng/save-field-ng.js +3 -1
- package/components/save-field-ng/{save-field-ng.html → save-field-ng__template.js} +2 -2
- package/components/select/select.css +12 -7
- package/components/select/select.examples.js +13 -0
- package/components/select/select.js +30 -43
- package/components/select/select.test.js +4 -5
- package/components/shortcuts-hint-ng/shortcuts-hint-ng.css +1 -1
- package/components/shortcuts-hint-ng/shortcuts-hint-ng.js +1 -1
- package/components/shortcuts-hint-ng/{shortcuts-hint-ng.html → shortcuts-hint-ng__template.js} +2 -2
- package/components/sidebar/sidebar.css +1 -0
- package/components/sidebar-ng/sidebar-ng.js +6 -2
- package/components/sidebar-ng/{sidebar-ng__button.html → sidebar-ng__button-template.js} +2 -2
- package/components/sidebar-ng/{sidebar-ng.html → sidebar-ng__template.js} +2 -2
- package/components/table/row.js +2 -1
- package/components/table/table.css +2 -1
- package/components/table-legacy/table-legacy.css +2 -2
- package/components/table-legacy/table-legacy__toolbar.css +2 -2
- package/components/table-legacy-ng/table-legacy-ng.js +38 -5
- package/components/table-legacy-ng/table-legacy-ng__pager.js +7 -1
- package/components/tabs/collapsible-tab.js +2 -2
- package/components/tabs/collapsible-tabs.js +4 -8
- package/components/tabs/tab-link.js +4 -2
- package/components/tabs/tabs.css +27 -0
- package/components/tabs-ng/tabs-ng.js +4 -2
- package/components/tabs-ng/{tabs-ng.html → tabs-ng__template.js} +6 -2
- package/components/tag/tag.css +5 -2
- package/components/tag/tag.examples.js +3 -0
- package/components/tag/tag.js +19 -16
- package/components/tags-input/tag-input.examples.js +1 -1
- package/components/tags-input/tags-input.js +5 -2
- package/components/template-ng/template-ng.js +1 -1
- package/components/tooltip/tooltip.js +7 -2
- package/components/user-agreement/user-agreement.css +1 -1
- package/components/user-agreement/user-agreement.examples.js +7 -4
- package/components/user-agreement/user-agreement.js +1 -0
- package/package.json +75 -78
- package/webpack.config.js +14 -10
- package/components/button-set-ng/button-set-ng.html +0 -1
- package/components/footer-ng/footer-ng.html +0 -13
- package/components/form-ng/form-ng__error-bubble.html +0 -3
- package/components/table-legacy-ng/table-legacy-ng.html +0 -4
- package/components/table-legacy-ng/table-legacy-ng__column.html +0 -12
- package/components/table-legacy-ng/table-legacy-ng__header.html +0 -4
- package/components/table-legacy-ng/table-legacy-ng__pager.html +0 -7
- package/components/table-legacy-ng/table-legacy-ng__row.html +0 -12
- package/components/table-legacy-ng/table-legacy-ng__title.html +0 -9
- package/dist/_helpers/_rollupPluginBabelHelpers.js +0 -127
- package/dist/_helpers/anchor.js +0 -33
- package/dist/_helpers/badge.js +0 -3
- package/dist/_helpers/button__classes.js +0 -39
- package/dist/_helpers/caption.js +0 -25
- package/dist/_helpers/card.js +0 -77
- package/dist/_helpers/date-picker.js +0 -3
- package/dist/_helpers/dialog__body-scroll-preventer.js +0 -56
- package/dist/_helpers/grid.js +0 -3
- package/dist/_helpers/header.js +0 -3
- package/dist/_helpers/icon__svg.js +0 -83
- package/dist/_helpers/inject-styles.js +0 -22
- package/dist/_helpers/island.js +0 -3
- package/dist/_helpers/list.js +0 -3
- package/dist/_helpers/query-assist__suggestions.js +0 -95
- package/dist/_helpers/select__filter.js +0 -78
- package/dist/_helpers/services-link.js +0 -42
- package/dist/_helpers/sidebar.js +0 -127
- package/dist/_helpers/table.js +0 -3
- package/dist/_helpers/tabs.js +0 -3
- package/dist/_helpers/title.js +0 -99
- package/dist/alert/alert.js +0 -254
- package/dist/alert/container.js +0 -50
- package/dist/alert-service/alert-service.js +0 -159
- package/dist/analytics/analytics.js +0 -116
- package/dist/analytics/analytics__custom-plugin.js +0 -127
- package/dist/analytics/analytics__fus-plugin.js +0 -101
- package/dist/analytics/analytics__ga-plugin.js +0 -66
- package/dist/analytics/analytics__plugin-utils.js +0 -79
- package/dist/auth/auth.js +0 -90
- package/dist/auth/auth__core.js +0 -987
- package/dist/auth/background-flow.js +0 -123
- package/dist/auth/down-notification.js +0 -111
- package/dist/auth/iframe-flow.js +0 -147
- package/dist/auth/landing-entry.js +0 -5
- package/dist/auth/landing.js +0 -84
- package/dist/auth/request-builder.js +0 -75
- package/dist/auth/response-parser.js +0 -117
- package/dist/auth/storage.js +0 -279
- package/dist/auth/token-validator.js +0 -176
- package/dist/auth/window-flow.js +0 -133
- package/dist/auth-dialog/auth-dialog.js +0 -132
- package/dist/auth-dialog-service/auth-dialog-service.js +0 -67
- package/dist/avatar/avatar-example-datauri.js +0 -26
- package/dist/avatar/avatar.js +0 -155
- package/dist/badge/badge.js +0 -52
- package/dist/button/button.js +0 -117
- package/dist/button/button__classes.js +0 -5
- package/dist/button-group/button-group.js +0 -30
- package/dist/button-group/caption.js +0 -5
- package/dist/button-set/button-set.js +0 -27
- package/dist/button-toolbar/button-toolbar.js +0 -30
- package/dist/caret/caret.js +0 -264
- package/dist/checkbox/checkbox.js +0 -110
- package/dist/confirm/confirm.js +0 -122
- package/dist/confirm-service/confirm-service.js +0 -112
- package/dist/content-layout/content-layout.js +0 -67
- package/dist/content-layout/sidebar.js +0 -6
- package/dist/contenteditable/contenteditable.js +0 -81
- package/dist/data-list/data-list.js +0 -203
- package/dist/data-list/data-list.mock.js +0 -190
- package/dist/data-list/item.js +0 -225
- package/dist/data-list/selection.js +0 -101
- package/dist/data-list/title.js +0 -16
- package/dist/date-picker/consts.js +0 -70
- package/dist/date-picker/date-input.js +0 -169
- package/dist/date-picker/date-picker.js +0 -356
- package/dist/date-picker/date-popup.js +0 -459
- package/dist/date-picker/day.js +0 -119
- package/dist/date-picker/formats.js +0 -3
- package/dist/date-picker/month-names.js +0 -92
- package/dist/date-picker/month-slider.js +0 -83
- package/dist/date-picker/month.js +0 -48
- package/dist/date-picker/months.js +0 -121
- package/dist/date-picker/weekdays.js +0 -24
- package/dist/date-picker/years.js +0 -109
- package/dist/dialog/dialog.js +0 -197
- package/dist/dialog/dialog__body-scroll-preventer.js +0 -2
- package/dist/dropdown/anchor.js +0 -16
- package/dist/dropdown/dropdown.js +0 -236
- package/dist/error-bubble/error-bubble.js +0 -59
- package/dist/error-message/error-message.js +0 -55
- package/dist/footer/footer.js +0 -127
- package/dist/global/angular-component-factory.js +0 -83
- package/dist/global/compose.js +0 -9
- package/dist/global/composeRefs.js +0 -15
- package/dist/global/conic-gradient.js +0 -37
- package/dist/global/create-stateful-context.js +0 -54
- package/dist/global/data-tests.js +0 -22
- package/dist/global/dom.js +0 -124
- package/dist/global/focus-sensor-hoc.js +0 -147
- package/dist/global/fuzzy-highlight.js +0 -67
- package/dist/global/get-event-key.js +0 -111
- package/dist/global/get-uid.js +0 -15
- package/dist/global/inject-styles.js +0 -17
- package/dist/global/linear-function.js +0 -18
- package/dist/global/listeners.js +0 -42
- package/dist/global/memoize.js +0 -18
- package/dist/global/normalize-indent.js +0 -28
- package/dist/global/promise-with-timeout.js +0 -13
- package/dist/global/radial-gradient-mask.js +0 -49
- package/dist/global/react-dom-renderer.js +0 -45
- package/dist/global/rerender-hoc.js +0 -53
- package/dist/global/ring-angular-component.js +0 -24
- package/dist/global/schedule-raf.js +0 -31
- package/dist/global/sniffer.js +0 -6
- package/dist/global/supports-css.js +0 -20
- package/dist/global/theme.js +0 -56
- package/dist/global/trivial-template-tag.js +0 -15
- package/dist/global/url.js +0 -163
- package/dist/global/variables_dark.js +0 -57
- package/dist/grid/col.js +0 -62
- package/dist/grid/grid.js +0 -35
- package/dist/grid/row.js +0 -66
- package/dist/group/group.js +0 -34
- package/dist/header/header.js +0 -144
- package/dist/header/logo.js +0 -39
- package/dist/header/profile.js +0 -212
- package/dist/header/services-link.js +0 -10
- package/dist/header/services.js +0 -135
- package/dist/header/smart-profile.js +0 -227
- package/dist/header/smart-services.js +0 -159
- package/dist/header/tray-icon.js +0 -45
- package/dist/header/tray.js +0 -33
- package/dist/heading/heading.js +0 -76
- package/dist/http/http.js +0 -216
- package/dist/http/http.mock.js +0 -65
- package/dist/hub-source/hub-source.js +0 -130
- package/dist/hub-source/hub-source__user.js +0 -28
- package/dist/hub-source/hub-source__users-groups.js +0 -62
- package/dist/icon/icon.js +0 -105
- package/dist/icon/icon__constants.js +0 -33
- package/dist/icon/icon__svg.js +0 -6
- package/dist/icon/index.js +0 -9
- package/dist/input/input.js +0 -231
- package/dist/island/adaptive-island-hoc.js +0 -48
- package/dist/island/content.js +0 -158
- package/dist/island/header.js +0 -85
- package/dist/island/island.js +0 -53
- package/dist/island-legacy/content-legacy.js +0 -28
- package/dist/island-legacy/header-legacy.js +0 -30
- package/dist/island-legacy/island-legacy.js +0 -30
- package/dist/link/clickableLink.js +0 -65
- package/dist/link/link.js +0 -118
- package/dist/list/consts.js +0 -26
- package/dist/list/list.js +0 -800
- package/dist/list/list__custom.js +0 -82
- package/dist/list/list__hint.js +0 -26
- package/dist/list/list__item.js +0 -197
- package/dist/list/list__link.js +0 -65
- package/dist/list/list__separator.js +0 -30
- package/dist/list/list__title.js +0 -39
- package/dist/list/list__users-groups-source.js +0 -124
- package/dist/loader/loader.js +0 -72
- package/dist/loader/loader__core.js +0 -272
- package/dist/loader-inline/inject-styles.js +0 -11
- package/dist/loader-inline/loader-inline.js +0 -58
- package/dist/loader-screen/loader-screen.js +0 -46
- package/dist/login-dialog/login-dialog.js +0 -184
- package/dist/login-dialog/service.js +0 -67
- package/dist/message/message.js +0 -232
- package/dist/old-browsers-message/old-browsers-message.js +0 -101
- package/dist/old-browsers-message/old-browsers-message__stop.js +0 -5
- package/dist/old-browsers-message/white-list.js +0 -34
- package/dist/pager/pager.js +0 -352
- package/dist/panel/panel.js +0 -34
- package/dist/permissions/permissions.js +0 -200
- package/dist/permissions/permissions__cache.js +0 -272
- package/dist/popup/popup.consts.js +0 -41
- package/dist/popup/popup.js +0 -389
- package/dist/popup/popup.target.js +0 -27
- package/dist/popup/position.js +0 -280
- package/dist/popup-menu/popup-menu.js +0 -108
- package/dist/progress-bar/progress-bar.js +0 -111
- package/dist/proxy-attrs/proxy-attrs.js +0 -19
- package/dist/query-assist/query-assist.js +0 -1023
- package/dist/query-assist/query-assist__suggestions.js +0 -43
- package/dist/radio/radio.js +0 -39
- package/dist/radio/radio__item.js +0 -82
- package/dist/select/select.js +0 -1335
- package/dist/select/select__filter.js +0 -49
- package/dist/select/select__popup.js +0 -541
- package/dist/shortcuts/core.js +0 -245
- package/dist/shortcuts/shortcut-title.js +0 -51
- package/dist/shortcuts/shortcuts-hoc.js +0 -43
- package/dist/shortcuts/shortcuts.js +0 -72
- package/dist/storage/storage.js +0 -55
- package/dist/storage/storage__fallback.js +0 -214
- package/dist/storage/storage__local.js +0 -150
- package/dist/style.css +0 -1
- package/dist/tab-trap/tab-trap.js +0 -178
- package/dist/table/cell.js +0 -25
- package/dist/table/disable-hover-hoc.js +0 -53
- package/dist/table/header-cell.js +0 -91
- package/dist/table/header.js +0 -189
- package/dist/table/multitable.js +0 -140
- package/dist/table/row-with-focus-sensor.js +0 -79
- package/dist/table/row.js +0 -270
- package/dist/table/selection-adapter.js +0 -14
- package/dist/table/selection-shortcuts-hoc.js +0 -212
- package/dist/table/selection.js +0 -221
- package/dist/table/smart-table.js +0 -113
- package/dist/table/table.js +0 -405
- package/dist/tabs/collapsible-more.js +0 -193
- package/dist/tabs/collapsible-tab.js +0 -90
- package/dist/tabs/collapsible-tabs.js +0 -361
- package/dist/tabs/custom-item.js +0 -13
- package/dist/tabs/dumb-tabs.js +0 -159
- package/dist/tabs/smart-tabs.js +0 -102
- package/dist/tabs/tab-link.js +0 -35
- package/dist/tabs/tab.js +0 -32
- package/dist/tabs/tabs.js +0 -65
- package/dist/tag/tag.js +0 -190
- package/dist/tags-input/tags-input.js +0 -474
- package/dist/tags-list/tags-list.js +0 -94
- package/dist/text/text.js +0 -38
- package/dist/toggle/toggle.js +0 -80
- package/dist/tooltip/tooltip.js +0 -205
- package/dist/user-card/card.js +0 -14
- package/dist/user-card/smart-user-card-tooltip.js +0 -112
- package/dist/user-card/tooltip.js +0 -91
- package/dist/user-card/user-card.js +0 -46
|
@@ -47,7 +47,8 @@ export default class DatePopup extends Component {
|
|
|
47
47
|
hidden: PropTypes.bool,
|
|
48
48
|
fromPlaceholder: PropTypes.string,
|
|
49
49
|
toPlaceholder: PropTypes.string,
|
|
50
|
-
timePlaceholder: PropTypes.string
|
|
50
|
+
timePlaceholder: PropTypes.string,
|
|
51
|
+
locale: PropTypes.object
|
|
51
52
|
};
|
|
52
53
|
|
|
53
54
|
static defaultProps = {
|
|
@@ -77,7 +78,7 @@ export default class DatePopup extends Component {
|
|
|
77
78
|
|
|
78
79
|
componentDidMount() {
|
|
79
80
|
if (this.componentRef.current) {
|
|
80
|
-
this.componentRef.current.addEventListener('wheel', this.handleWheel);
|
|
81
|
+
this.componentRef.current.addEventListener('wheel', this.handleWheel, {passive: true});
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
|
|
@@ -278,15 +279,26 @@ export default class DatePopup extends Component {
|
|
|
278
279
|
handleScroll = scrollDate => this.setState({scrollDate});
|
|
279
280
|
|
|
280
281
|
onClear = e => {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
282
|
+
let changes;
|
|
283
|
+
|
|
284
|
+
if (this.props.range) {
|
|
285
|
+
changes = {
|
|
286
|
+
from: null,
|
|
287
|
+
to: null
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
} else {
|
|
291
|
+
changes = {
|
|
292
|
+
date: null
|
|
293
|
+
};
|
|
294
|
+
}
|
|
284
295
|
|
|
296
|
+
this.select(changes);
|
|
285
297
|
this.props.onClear(e);
|
|
286
298
|
};
|
|
287
299
|
|
|
288
300
|
render() {
|
|
289
|
-
const {range, hidden, withTime, time} = this.props;
|
|
301
|
+
const {range, hidden, withTime, time, locale} = this.props;
|
|
290
302
|
const parsedDate = this.parse(this.props.date, 'date');
|
|
291
303
|
const parsedTo = this.parse(this.props.to, 'to');
|
|
292
304
|
|
|
@@ -380,6 +392,7 @@ export default class DatePopup extends Component {
|
|
|
380
392
|
onInput={this.handleInput}
|
|
381
393
|
onConfirm={this.handleConfirm(name)}
|
|
382
394
|
onClear={onClear}
|
|
395
|
+
locale={locale}
|
|
383
396
|
/>
|
|
384
397
|
);
|
|
385
398
|
})}
|
|
@@ -402,12 +415,13 @@ export default class DatePopup extends Component {
|
|
|
402
415
|
onInput={this.handleInput}
|
|
403
416
|
onConfirm={this.handleConfirm('time')}
|
|
404
417
|
onClear={clearable && this.onClear || undefined}
|
|
418
|
+
locale={locale}
|
|
405
419
|
/>
|
|
406
420
|
)
|
|
407
421
|
: ('')
|
|
408
422
|
}
|
|
409
423
|
</div>
|
|
410
|
-
<Weekdays/>
|
|
424
|
+
<Weekdays locale={locale}/>
|
|
411
425
|
<div
|
|
412
426
|
className={styles.calendar}
|
|
413
427
|
>
|
|
@@ -415,6 +429,7 @@ export default class DatePopup extends Component {
|
|
|
415
429
|
{...calendarProps}
|
|
416
430
|
onHover={this.hoverHandler}
|
|
417
431
|
onSelect={this.selectHandler}
|
|
432
|
+
locale={locale}
|
|
418
433
|
/>
|
|
419
434
|
<Years {...calendarProps}/>
|
|
420
435
|
</div>
|
|
@@ -21,7 +21,7 @@ class MonthName extends PureComponent {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
render() {
|
|
24
|
-
const {month} = this.props;
|
|
24
|
+
const {month, locale} = this.props;
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
27
|
<button
|
|
@@ -34,7 +34,7 @@ class MonthName extends PureComponent {
|
|
|
34
34
|
)}
|
|
35
35
|
onClick={this.handleClick}
|
|
36
36
|
>
|
|
37
|
-
{format(month, '
|
|
37
|
+
{format(month, 'LLL', {locale})}
|
|
38
38
|
</button>
|
|
39
39
|
);
|
|
40
40
|
}
|
|
@@ -42,11 +42,12 @@ class MonthName extends PureComponent {
|
|
|
42
42
|
|
|
43
43
|
MonthName.propTypes = {
|
|
44
44
|
month: dateType,
|
|
45
|
-
onScrollChange: PropTypes.func
|
|
45
|
+
onScrollChange: PropTypes.func,
|
|
46
|
+
locale: PropTypes.string
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
export default function MonthNames(props) {
|
|
49
|
-
const {scrollDate} = props;
|
|
50
|
+
const {scrollDate, locale} = props;
|
|
50
51
|
const months = [];
|
|
51
52
|
for (let i = 0; i < YEAR; i++) {
|
|
52
53
|
const middleDay = set(scrollDate, {month: i, date: MIDDLE_DAY});
|
|
@@ -73,6 +74,7 @@ export default function MonthNames(props) {
|
|
|
73
74
|
key={+month}
|
|
74
75
|
month={month}
|
|
75
76
|
onScrollChange={props.onScrollChange}
|
|
77
|
+
locale={locale}
|
|
76
78
|
/>
|
|
77
79
|
))}
|
|
78
80
|
{props.currentRange &&
|
|
@@ -97,5 +99,6 @@ export default function MonthNames(props) {
|
|
|
97
99
|
MonthNames.propTypes = {
|
|
98
100
|
scrollDate: dateType,
|
|
99
101
|
onScrollChange: PropTypes.func,
|
|
100
|
-
currentRange: PropTypes.arrayOf(dateType)
|
|
102
|
+
currentRange: PropTypes.arrayOf(dateType),
|
|
103
|
+
locale: PropTypes.string
|
|
101
104
|
};
|
|
@@ -5,6 +5,8 @@ import format from 'date-fns/format';
|
|
|
5
5
|
import getDay from 'date-fns/getDay';
|
|
6
6
|
import setDay from 'date-fns/setDay';
|
|
7
7
|
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
|
|
8
10
|
import Day from './day';
|
|
9
11
|
import {dateType, WEEK, weekdays} from './consts';
|
|
10
12
|
import styles from './date-picker.css';
|
|
@@ -12,6 +14,7 @@ import styles from './date-picker.css';
|
|
|
12
14
|
export default function Month(props) {
|
|
13
15
|
const start = props.month;
|
|
14
16
|
const end = endOfMonth(start);
|
|
17
|
+
const {locale} = props;
|
|
15
18
|
|
|
16
19
|
// pad with empty cells starting from last friday
|
|
17
20
|
const weekday = getDay(start);
|
|
@@ -25,7 +28,7 @@ export default function Month(props) {
|
|
|
25
28
|
return (
|
|
26
29
|
<div className={styles.month}>
|
|
27
30
|
<span className={styles.monthTitle}>
|
|
28
|
-
{format(props.month, '
|
|
31
|
+
{format(props.month, 'LLLL', {locale})}
|
|
29
32
|
</span>
|
|
30
33
|
{days.map(date => (
|
|
31
34
|
<Day
|
|
@@ -40,5 +43,6 @@ export default function Month(props) {
|
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
Month.propTypes = {
|
|
43
|
-
month: dateType
|
|
46
|
+
month: dateType,
|
|
47
|
+
locale: PropTypes.string
|
|
44
48
|
};
|
|
@@ -5,13 +5,17 @@ import format from 'date-fns/format';
|
|
|
5
5
|
import setDay from 'date-fns/setDay';
|
|
6
6
|
import startOfDay from 'date-fns/startOfDay';
|
|
7
7
|
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
|
|
8
10
|
import {weekdays} from './consts';
|
|
9
11
|
import styles from './date-picker.css';
|
|
10
12
|
|
|
11
|
-
export default function Weekdays() {
|
|
13
|
+
export default function Weekdays(props) {
|
|
12
14
|
const days = Object.keys(weekdays).
|
|
13
15
|
map(key => startOfDay(setDay(new Date(), weekdays[key])));
|
|
14
16
|
|
|
17
|
+
const {locale} = props;
|
|
18
|
+
|
|
15
19
|
return (
|
|
16
20
|
<div className={styles.weekdays}>
|
|
17
21
|
{days.map(day => (
|
|
@@ -24,9 +28,13 @@ export default function Weekdays() {
|
|
|
24
28
|
)}
|
|
25
29
|
key={+day}
|
|
26
30
|
>
|
|
27
|
-
{format(day, 'EEEEEE')}
|
|
31
|
+
{format(day, 'EEEEEE', {locale})}
|
|
28
32
|
</span>
|
|
29
33
|
))}
|
|
30
34
|
</div>
|
|
31
35
|
);
|
|
32
36
|
}
|
|
37
|
+
|
|
38
|
+
Weekdays.propTypes = {
|
|
39
|
+
locale: PropTypes.string
|
|
40
|
+
};
|
|
@@ -55,6 +55,7 @@ export const basic = ({onAction}) => {
|
|
|
55
55
|
</Group>
|
|
56
56
|
|
|
57
57
|
<Dialog
|
|
58
|
+
label="Dialog"
|
|
58
59
|
show={show}
|
|
59
60
|
onCloseAttempt={this.cancelDialog}
|
|
60
61
|
trapFocus
|
|
@@ -124,6 +125,7 @@ export const withScroll = ({onAction}) => {
|
|
|
124
125
|
</div>
|
|
125
126
|
|
|
126
127
|
<Dialog
|
|
128
|
+
label="Dialog"
|
|
127
129
|
show={this.state.show}
|
|
128
130
|
onCloseAttempt={this.cancelDialog}
|
|
129
131
|
trapFocus
|
|
@@ -167,7 +169,7 @@ export const WithOverflowScrollOnHtml = () => {
|
|
|
167
169
|
<div className="container">
|
|
168
170
|
<div>Scroll down</div>
|
|
169
171
|
<Button className="button" onClick={() => setOpen(true)}>Show dialog</Button>
|
|
170
|
-
<Dialog show={open} onCloseAttempt={() => setOpen(false)}>
|
|
172
|
+
<Dialog label="Dialog" show={open} onCloseAttempt={() => setOpen(false)}>
|
|
171
173
|
<Header>Dialog title</Header>
|
|
172
174
|
</Dialog>
|
|
173
175
|
</div>
|
|
@@ -13,7 +13,7 @@ import Button from '../button/button';
|
|
|
13
13
|
|
|
14
14
|
import {PopupTarget} from '../popup/popup.target';
|
|
15
15
|
|
|
16
|
-
import scrollPreventerFactory from './dialog__body-scroll-preventer';
|
|
16
|
+
import {preventerFactory as scrollPreventerFactory} from './dialog__body-scroll-preventer';
|
|
17
17
|
import styles from './dialog.css';
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -24,6 +24,7 @@ function noop() {}
|
|
|
24
24
|
|
|
25
25
|
export default class Dialog extends PureComponent {
|
|
26
26
|
static propTypes = {
|
|
27
|
+
label: PropTypes.string,
|
|
27
28
|
className: PropTypes.string,
|
|
28
29
|
contentClassName: PropTypes.string,
|
|
29
30
|
children: PropTypes.oneOfType([
|
|
@@ -47,6 +48,7 @@ export default class Dialog extends PureComponent {
|
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
static defaultProps = {
|
|
51
|
+
label: 'Dialog',
|
|
50
52
|
onOverlayClick: noop,
|
|
51
53
|
onEscPress: noop,
|
|
52
54
|
onCloseClick: noop,
|
|
@@ -117,7 +119,7 @@ export default class Dialog extends PureComponent {
|
|
|
117
119
|
render() {
|
|
118
120
|
const {show, showCloseButton, onOverlayClick, onCloseAttempt, onEscPress, onCloseClick,
|
|
119
121
|
children, className, contentClassName, trapFocus, 'data-test': dataTest, closeButtonInside,
|
|
120
|
-
portalTarget, ...restProps} = this.props;
|
|
122
|
+
portalTarget, label, ...restProps} = this.props;
|
|
121
123
|
const classes = classNames(styles.container, className);
|
|
122
124
|
const shortcutsMap = this.getShortcutsMap();
|
|
123
125
|
|
|
@@ -150,6 +152,7 @@ export default class Dialog extends PureComponent {
|
|
|
150
152
|
className={classNames(styles.content, contentClassName)}
|
|
151
153
|
data-test="ring-dialog"
|
|
152
154
|
role="dialog"
|
|
155
|
+
aria-label={label}
|
|
153
156
|
>
|
|
154
157
|
{children}
|
|
155
158
|
{showCloseButton &&
|
|
@@ -6,7 +6,7 @@ import styles from './dialog.css';
|
|
|
6
6
|
|
|
7
7
|
describe('Dialog', () => {
|
|
8
8
|
const children = <div/>;
|
|
9
|
-
const mountDialog = props => mount(<Dialog {...props} trapFocus={false}/>);
|
|
9
|
+
const mountDialog = props => mount(<Dialog label="Dialog" {...props} trapFocus={false}/>);
|
|
10
10
|
|
|
11
11
|
it('should create component', () => {
|
|
12
12
|
mountDialog({show: true, children}).should.have.type(Dialog);
|
|
@@ -47,7 +47,7 @@ const reset = key => {
|
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
const preventerFactory = key => {
|
|
50
|
+
export const preventerFactory = key => {
|
|
51
51
|
const preventerKey = key || Math.random();
|
|
52
52
|
|
|
53
53
|
return {
|
|
@@ -56,4 +56,4 @@ const preventerFactory = key => {
|
|
|
56
56
|
};
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
-
export default preventerFactory;
|
|
59
|
+
export default preventerFactory('default-preventer');
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import angular from 'angular';
|
|
2
2
|
|
|
3
|
-
import angularSanitize from 'angular-sanitize';
|
|
4
|
-
|
|
5
3
|
import {createFocusTrap} from 'focus-trap';
|
|
6
4
|
|
|
7
5
|
import {getRect, getStyles} from '../global/dom';
|
|
@@ -10,12 +8,13 @@ import shortcuts from '../shortcuts/core';
|
|
|
10
8
|
import RingButton from '../button-ng/button-ng';
|
|
11
9
|
import PromisedClickNg from '../promised-click-ng/promised-click-ng';
|
|
12
10
|
import rgCompilerModuleName from '../compiler-ng/compiler-ng';
|
|
13
|
-
import scrollPreventerFactory from '../dialog/dialog__body-scroll-preventer';
|
|
11
|
+
import {preventerFactory as scrollPreventerFactory} from '../dialog/dialog__body-scroll-preventer';
|
|
14
12
|
import '../form/form.css';
|
|
15
13
|
import dialogStyles from '../dialog/dialog.css';
|
|
16
14
|
import islandStyles from '../island/island.css';
|
|
17
15
|
|
|
18
16
|
import styles from './dialog-ng.css';
|
|
17
|
+
import dialogTemplate from './dialog-ng__template';
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
20
|
* @name Dialog Ng
|
|
@@ -23,12 +22,12 @@ import styles from './dialog-ng.css';
|
|
|
23
22
|
|
|
24
23
|
const angularModule = angular.module(
|
|
25
24
|
'Ring.dialog',
|
|
26
|
-
[
|
|
25
|
+
[RingButton, PromisedClickNg, rgCompilerModuleName]
|
|
27
26
|
);
|
|
28
27
|
|
|
29
28
|
class DialogController extends RingAngularComponent {
|
|
30
29
|
static $inject = ['$scope', '$q', 'dialog', '$element', 'dialogInSidebar', '$compile',
|
|
31
|
-
'$injector', '$controller', 'rgCompiler'];
|
|
30
|
+
'$injector', '$controller', 'rgCompiler', '$sce'];
|
|
32
31
|
|
|
33
32
|
constructor(...args) {
|
|
34
33
|
super(...args);
|
|
@@ -273,7 +272,7 @@ class DialogController extends RingAngularComponent {
|
|
|
273
272
|
}];
|
|
274
273
|
this.serverErrorFields.push(errorField);
|
|
275
274
|
} else {
|
|
276
|
-
this.error = this.getErrorMessage(errorResponse);
|
|
275
|
+
this.error = this.$inject.$sce.trustAsHtml(this.getErrorMessage(errorResponse));
|
|
277
276
|
}
|
|
278
277
|
};
|
|
279
278
|
|
|
@@ -365,7 +364,7 @@ class DialogService extends RingAngularComponent {
|
|
|
365
364
|
|
|
366
365
|
unregister = () => {
|
|
367
366
|
Reflect.deleteProperty(this, 'ctrl');
|
|
368
|
-
}
|
|
367
|
+
};
|
|
369
368
|
}
|
|
370
369
|
|
|
371
370
|
class DialogInSidebarService extends DialogService {
|
|
@@ -491,7 +490,7 @@ function rgDialogDirective($timeout) {
|
|
|
491
490
|
active: '=?'
|
|
492
491
|
},
|
|
493
492
|
replace: true,
|
|
494
|
-
template:
|
|
493
|
+
template: dialogTemplate,
|
|
495
494
|
controllerAs: 'dialog',
|
|
496
495
|
link
|
|
497
496
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
export default `<div
|
|
2
2
|
ng-show="dialog.active"
|
|
3
3
|
ng-class="[!dialog.inSidebar && dialog.dialogStyles.container]"
|
|
4
4
|
ng-click="dialog.handleClick($event)"
|
|
@@ -66,4 +66,4 @@
|
|
|
66
66
|
<div tabindex="-1" ng-show="false" data-anchor="focus-trap-fallback"></div>
|
|
67
67
|
</div>
|
|
68
68
|
</div>
|
|
69
|
-
</div
|
|
69
|
+
</div>`;
|
|
@@ -3,12 +3,14 @@ import chevronDownIcon from '@jetbrains/icons/chevron-down';
|
|
|
3
3
|
|
|
4
4
|
import reactDecorator from '../../.storybook/react-decorator';
|
|
5
5
|
|
|
6
|
+
import {ActiveItemContext} from '../list/list';
|
|
7
|
+
|
|
6
8
|
import Popup from '@jetbrains/ring-ui/components/popup/popup';
|
|
7
9
|
import PopupMenu from '@jetbrains/ring-ui/components/popup-menu/popup-menu';
|
|
8
10
|
import Button from '@jetbrains/ring-ui/components/button/button';
|
|
9
11
|
import Link from '@jetbrains/ring-ui/components/link/link';
|
|
10
12
|
import {Input} from '@jetbrains/ring-ui/components/input/input';
|
|
11
|
-
|
|
13
|
+
import getUID from '@jetbrains/ring-ui/components/global/get-uid';
|
|
12
14
|
import Dropdown from '@jetbrains/ring-ui/components/dropdown/dropdown';
|
|
13
15
|
|
|
14
16
|
export default {
|
|
@@ -45,6 +47,39 @@ export const withCustomAnchorAndPopup = () => (
|
|
|
45
47
|
</Dropdown>
|
|
46
48
|
);
|
|
47
49
|
|
|
50
|
+
export const withCustomAnchorAndPopupAndContentAccessibilityHandling = () => {
|
|
51
|
+
const listId = getUID('popup-menu-list-id');
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<ActiveItemContext.Provider>
|
|
55
|
+
<Dropdown anchor={({active}) => (
|
|
56
|
+
<ActiveItemContext.ValueContext.Consumer>
|
|
57
|
+
{activeItemId => {
|
|
58
|
+
const anchorAriaProps = active && activeItemId
|
|
59
|
+
? {'aria-owns': listId, 'aria-activedescendant': activeItemId}
|
|
60
|
+
: {};
|
|
61
|
+
return (
|
|
62
|
+
<Button
|
|
63
|
+
{...anchorAriaProps}
|
|
64
|
+
delayed
|
|
65
|
+
>Edit</Button>
|
|
66
|
+
);
|
|
67
|
+
}}
|
|
68
|
+
</ActiveItemContext.ValueContext.Consumer>
|
|
69
|
+
)}
|
|
70
|
+
>
|
|
71
|
+
<PopupMenu
|
|
72
|
+
id={listId}
|
|
73
|
+
ariaLabel="My options menu"
|
|
74
|
+
closeOnSelect
|
|
75
|
+
activateFirstItem
|
|
76
|
+
data={['Cut', 'Copy', 'Paste'].map(label => ({label, key: label.toLowerCase()}))}
|
|
77
|
+
/>
|
|
78
|
+
</Dropdown>
|
|
79
|
+
</ActiveItemContext.Provider>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
48
83
|
withCustomAnchorAndPopup.storyName = 'with custom anchor and popup';
|
|
49
84
|
|
|
50
85
|
export const withActiveClassName = () => (
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import reactDecorator from '../../.storybook/react-decorator';
|
|
4
|
+
|
|
5
|
+
import DropdownMenu from '@jetbrains/ring-ui/components/dropdown-menu/dropdown-menu';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
title: 'Components/DropdownMenu',
|
|
9
|
+
decorators: [reactDecorator()],
|
|
10
|
+
|
|
11
|
+
parameters: {
|
|
12
|
+
notes: 'Displays a menu in a dropdown.',
|
|
13
|
+
hermione: {
|
|
14
|
+
actions: [
|
|
15
|
+
{type: 'click', selector: '[data-test~=ring-dropdown]'},
|
|
16
|
+
{
|
|
17
|
+
type: 'capture',
|
|
18
|
+
name: 'dropdown',
|
|
19
|
+
selector: ['[data-test~=ring-dropdown]', '[data-test~=ring-popup]']
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
a11y: {element: '*[data-test~=ring-dropdown]'}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const basic = () => {
|
|
28
|
+
const data = [
|
|
29
|
+
{label: 'Item'},
|
|
30
|
+
{label: 'Link to jetbrains.com', href: 'http://www.jetbrains.com'},
|
|
31
|
+
{rgItemType: DropdownMenu.ListProps.Type.SEPARATOR},
|
|
32
|
+
{rgItemType: DropdownMenu.ListProps.Type.LINK, label: 'Link Item'},
|
|
33
|
+
{
|
|
34
|
+
rgItemType: DropdownMenu.ListProps.Type.LINK,
|
|
35
|
+
label: 'Link Item With Additional Class',
|
|
36
|
+
className: 'test'
|
|
37
|
+
},
|
|
38
|
+
{rgItemType: DropdownMenu.ListProps.Type.SEPARATOR, description: 'Separator With Description'},
|
|
39
|
+
{rgItemType: DropdownMenu.ListProps.Type.TITLE, label: 'Title'},
|
|
40
|
+
{rgItemType: DropdownMenu.ListProps.Type.ITEM, label: '1 Element in group'},
|
|
41
|
+
{rgItemType: DropdownMenu.ListProps.Type.ITEM, label: '2 Element in group'}
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
return <DropdownMenu data={data} anchor={'Click me!'}/>;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
basic.storyName = 'DropdownMenu';
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import React, {useMemo, cloneElement} from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import List, {ActiveItemContext} from '../list/list';
|
|
5
|
+
import Dropdown from '../dropdown/dropdown';
|
|
6
|
+
import PopupMenu from '../popup-menu/popup-menu';
|
|
7
|
+
import getUID from '../global/get-uid';
|
|
8
|
+
import Anchor from '../dropdown/anchor';
|
|
9
|
+
|
|
10
|
+
const {children, ...dropdownPropTypes} = Dropdown.propTypes || {};
|
|
11
|
+
const {
|
|
12
|
+
id: idPropType,
|
|
13
|
+
data: dataPropType,
|
|
14
|
+
ariaLabel: ariaLabelPropType,
|
|
15
|
+
onSelect: onSelectPropType
|
|
16
|
+
} = PopupMenu.propTypes || {};
|
|
17
|
+
|
|
18
|
+
const defaultAriaLabel = 'Dropdown menu';
|
|
19
|
+
|
|
20
|
+
function DropdownAnchorWrapper({anchor, pinned, active, activeListItemId, listId, ...restProps}) {
|
|
21
|
+
const anchorAriaProps = useMemo(() => ({
|
|
22
|
+
...(listId ? {'aria-haspopup': 'true'} : {}),
|
|
23
|
+
...(activeListItemId ? {'aria-activedescendant': activeListItemId, 'aria-owns': listId} : {}),
|
|
24
|
+
...(active ? {'aria-expanded': 'true'} : {})
|
|
25
|
+
}), [active, activeListItemId, listId]);
|
|
26
|
+
|
|
27
|
+
const anchorProps = useMemo(
|
|
28
|
+
() => ({active, pinned, ...restProps, ...anchorAriaProps}),
|
|
29
|
+
[pinned, active, restProps, anchorAriaProps]
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const anchorComponentProps = useMemo(
|
|
33
|
+
() => ({...anchorProps, pinned: `${anchorProps.pinned}`}),
|
|
34
|
+
[anchorProps]
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
if (typeof anchor === 'string') {
|
|
38
|
+
return (
|
|
39
|
+
<Anchor
|
|
40
|
+
{...anchorComponentProps}
|
|
41
|
+
>{anchor}</Anchor>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
if (typeof anchor === 'function') {
|
|
45
|
+
return anchor(({active, pinned, ...restProps}), anchorAriaProps);
|
|
46
|
+
}
|
|
47
|
+
if (!Array.isArray(anchor)) {
|
|
48
|
+
return cloneElement(
|
|
49
|
+
anchor,
|
|
50
|
+
typeof anchor.type === 'string' ? anchorAriaProps : anchorComponentProps
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return (
|
|
54
|
+
<div {...anchorAriaProps}>{anchor}</div>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
DropdownAnchorWrapper.propTypes = {
|
|
59
|
+
anchor: PropTypes.oneOfType([PropTypes.node, PropTypes.string, PropTypes.func]).isRequired,
|
|
60
|
+
pinned: PropTypes.bool,
|
|
61
|
+
active: PropTypes.bool,
|
|
62
|
+
activeListItemId: PropTypes.string,
|
|
63
|
+
listId: PropTypes.string
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const DropdownMenu = React.forwardRef(function DropdownMenu(
|
|
67
|
+
{id, anchor, ariaLabel, data, onSelect, menuProps, ...restDropdownProps},
|
|
68
|
+
forwardedRef
|
|
69
|
+
) {
|
|
70
|
+
const listId = useMemo(() => id || getUID('dropdown-menu-list'), [id]);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<ActiveItemContext.Provider>
|
|
74
|
+
<Dropdown
|
|
75
|
+
anchor={({pinned, active, ...restAnchorProps}) => (
|
|
76
|
+
<ActiveItemContext.ValueContext.Consumer>
|
|
77
|
+
{activeItemId => (
|
|
78
|
+
<DropdownAnchorWrapper
|
|
79
|
+
anchor={anchor}
|
|
80
|
+
pinned={pinned}
|
|
81
|
+
active={active}
|
|
82
|
+
activeListItemId={activeItemId}
|
|
83
|
+
listId={listId}
|
|
84
|
+
{...restAnchorProps}
|
|
85
|
+
/>
|
|
86
|
+
)}
|
|
87
|
+
</ActiveItemContext.ValueContext.Consumer>
|
|
88
|
+
)}
|
|
89
|
+
{...restDropdownProps}
|
|
90
|
+
>
|
|
91
|
+
<PopupMenu
|
|
92
|
+
ref={forwardedRef}
|
|
93
|
+
id={listId}
|
|
94
|
+
ariaLabel={ariaLabel || defaultAriaLabel}
|
|
95
|
+
closeOnSelect
|
|
96
|
+
activateFirstItem
|
|
97
|
+
data={data}
|
|
98
|
+
onSelect={onSelect}
|
|
99
|
+
{...menuProps}
|
|
100
|
+
/>
|
|
101
|
+
</Dropdown>
|
|
102
|
+
</ActiveItemContext.Provider>
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
DropdownMenu.propTypes = {
|
|
107
|
+
id: idPropType,
|
|
108
|
+
data: dataPropType,
|
|
109
|
+
ariaLabel: ariaLabelPropType,
|
|
110
|
+
onSelect: onSelectPropType,
|
|
111
|
+
menuProps: PropTypes.object,
|
|
112
|
+
...dropdownPropTypes
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
DropdownMenu.ListProps = List.ListProps;
|
|
116
|
+
|
|
117
|
+
export default DropdownMenu;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {shallow, mount} from 'enzyme';
|
|
3
|
+
|
|
4
|
+
import PopupMenu from '../popup-menu/popup-menu';
|
|
5
|
+
import Anchor from '../dropdown/anchor';
|
|
6
|
+
|
|
7
|
+
import DropdownMenu from './dropdown-menu';
|
|
8
|
+
|
|
9
|
+
const waitForCondition = (condition, rejectMessage) => new Promise((resolve, reject) => {
|
|
10
|
+
const interval = 10;
|
|
11
|
+
const maxWaitingTime = 2000;
|
|
12
|
+
let remainingTime = maxWaitingTime;
|
|
13
|
+
|
|
14
|
+
const intervalId = setInterval(() => {
|
|
15
|
+
if (condition()) {
|
|
16
|
+
clearInterval(intervalId);
|
|
17
|
+
resolve();
|
|
18
|
+
} else if (remainingTime < 0) {
|
|
19
|
+
clearInterval(intervalId);
|
|
20
|
+
reject(new Error(rejectMessage));
|
|
21
|
+
} else {
|
|
22
|
+
remainingTime -= interval;
|
|
23
|
+
}
|
|
24
|
+
}, interval);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('Dropdown Menu', () => {
|
|
28
|
+
const shallowDropdownMenu = props => shallow(<DropdownMenu id="test-list-id" {...props}/>);
|
|
29
|
+
const mountDropdownMenu = props => mount(<DropdownMenu id="test-list-id" {...props}/>);
|
|
30
|
+
|
|
31
|
+
const mountAndWaitForMenuContent = async props => {
|
|
32
|
+
const wrapper = mountDropdownMenu(props);
|
|
33
|
+
|
|
34
|
+
wrapper.find('button').getDOMNode().click();
|
|
35
|
+
await waitForCondition(
|
|
36
|
+
() => !!wrapper.find(PopupMenu).length,
|
|
37
|
+
'List was not rendered in a dropdown menu'
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return wrapper;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
it('should create component', () => {
|
|
44
|
+
shallowDropdownMenu({anchor: 'Anchor text'}).should.exist;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should open List', async () => {
|
|
48
|
+
const wrapper = await mountAndWaitForMenuContent({anchor: 'Anchor text'});
|
|
49
|
+
|
|
50
|
+
const list = wrapper.find(PopupMenu).instance().list;
|
|
51
|
+
list.should.exist;
|
|
52
|
+
|
|
53
|
+
//We need it to maintain compatibility between Dropdown Menu and List
|
|
54
|
+
list.props.data.length.should.equal(0);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should pass params to List', async () => {
|
|
58
|
+
const wrapper = await mountAndWaitForMenuContent({
|
|
59
|
+
anchor: 'Anchor text',
|
|
60
|
+
data: [{key: 'key1'}]
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
shallow(wrapper.find(PopupMenu).instance().list.renderItem({index: 1})).should.exist;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should add accessibility attributes to anchor', async () => {
|
|
67
|
+
const wrapper = await mountAndWaitForMenuContent({
|
|
68
|
+
anchor: 'Anchor text',
|
|
69
|
+
data: [{key: 'key1'}, {key: 'key2'}]
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const anchorProps = wrapper.update().find(Anchor).props();
|
|
73
|
+
anchorProps['aria-owns'].should.equal('test-list-id');
|
|
74
|
+
anchorProps['aria-activedescendant'].should.contain(':key1');
|
|
75
|
+
});
|
|
76
|
+
});
|