@jetbrains/ring-ui 4.1.0-beta.13 → 4.1.0-beta.17
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 +14 -13
- package/components/alert/container.css +1 -1
- package/components/auth/auth.test.js +14 -7
- package/components/auth/auth__core.js +12 -6
- 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-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/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 +10 -6
- package/components/date-picker/date-picker.js +16 -14
- package/components/date-picker/date-popup.js +8 -4
- 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-ng/dialog-ng.js +6 -7
- 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-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/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/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/pager/pager.js +5 -3
- package/components/permissions/permissions.js +1 -1
- package/components/progress-bar/progress-bar.css +1 -1
- package/components/query-assist/query-assist.css +1 -1
- 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 +4 -0
- package/components/select/select.examples.js +13 -0
- package/components/select/select.js +6 -6
- 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/table.css +2 -1
- package/components/table-legacy/table-legacy.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-ng/tabs-ng.js +3 -1
- package/components/tabs-ng/{tabs-ng.html → tabs-ng__template.js} +2 -2
- package/components/tag/tag.css +5 -2
- 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/dist/_helpers/button-group.js +3 -0
- package/dist/_helpers/button-set.js +3 -0
- package/dist/_helpers/button-toolbar.js +3 -0
- package/dist/_helpers/button__classes.js +1 -1
- package/dist/_helpers/checkbox.js +3 -0
- package/dist/_helpers/date-picker.js +1 -1
- package/dist/_helpers/error-message.js +3 -0
- package/dist/_helpers/footer.js +121 -0
- package/dist/_helpers/grid.js +1 -1
- package/dist/_helpers/group.js +3 -0
- package/dist/_helpers/header.js +1 -1
- package/dist/_helpers/icon.js +3 -0
- package/dist/_helpers/inject-styles.js +1 -1
- package/dist/_helpers/input.js +3 -0
- package/dist/_helpers/island.js +1 -1
- package/dist/_helpers/link.js +3 -0
- package/dist/_helpers/loader-screen.js +3 -0
- package/dist/_helpers/panel.js +3 -0
- package/dist/_helpers/query-assist__suggestions.js +1 -1
- package/dist/_helpers/radio.js +3 -0
- package/dist/_helpers/sidebar.js +1 -1
- package/dist/_helpers/table.js +1 -1
- package/dist/_helpers/tabs.js +1 -1
- package/dist/_helpers/title.js +1 -1
- package/dist/alert/alert.js +3 -3
- package/dist/alert/container.js +2 -2
- package/dist/alert-service/alert-service.js +3 -2
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/analytics__custom-plugin.js +1 -1
- package/dist/analytics/analytics__fus-plugin.js +1 -1
- package/dist/analytics/analytics__ga-plugin.js +1 -1
- package/dist/analytics/analytics__plugin-utils.js +1 -1
- package/dist/analytics-ng/analytics-ng.js +94 -0
- package/dist/auth/auth.js +4 -1
- package/dist/auth/auth__core.js +15 -9
- package/dist/auth/background-flow.js +1 -2
- package/dist/auth/down-notification.js +5 -2
- package/dist/auth/iframe-flow.js +5 -2
- package/dist/auth/landing-entry.js +1 -1
- package/dist/auth/landing.js +5 -2
- package/dist/auth/request-builder.js +1 -1
- package/dist/auth/response-parser.js +1 -1
- package/dist/auth/storage.js +3 -2
- package/dist/auth/token-validator.js +1 -1
- package/dist/auth/window-flow.js +1 -1
- package/dist/auth-dialog/auth-dialog.js +4 -3
- package/dist/auth-dialog-service/auth-dialog-service.js +3 -2
- package/dist/auth-ng/auth-ng.js +203 -0
- package/dist/auth-ng/auth-ng.mock.js +33 -0
- package/dist/autofocus-ng/autofocus-ng.js +50 -0
- package/dist/avatar/avatar.js +19 -7
- package/dist/avatar/fallback-avatar.js +141 -0
- package/dist/avatar-editor-ng/avatar-editor-ng.js +164 -0
- package/dist/avatar-editor-ng/avatar-editor-ng__template.js +30 -0
- package/dist/avatar-ng/avatar-ng.js +18 -0
- package/dist/badge/badge.js +1 -1
- package/dist/badge-ng/badge-ng.js +16 -0
- package/dist/breadcrumb-ng/breadcrumb-ng.js +61 -0
- package/dist/button/button.js +3 -2
- package/dist/button-group/button-group.js +3 -3
- package/dist/button-group/caption.js +24 -5
- package/dist/button-group-ng/button-group-ng.js +38 -0
- package/dist/button-ng/button-ng.js +223 -0
- package/dist/button-set/button-set.js +2 -3
- package/dist/button-set-ng/button-set-ng.js +19 -0
- package/dist/button-toolbar/button-toolbar.js +2 -3
- package/dist/button-toolbar-ng/button-toolbar-ng.js +23 -0
- package/dist/caret/caret.js +1 -1
- package/dist/checkbox/checkbox.js +4 -4
- package/dist/checkbox-ng/checkbox-ng.js +55 -0
- package/dist/code/code.js +136 -0
- package/dist/compiler-ng/compiler-ng.js +53 -0
- package/dist/confirm/confirm.js +4 -2
- package/dist/confirm-ng/confirm-ng.js +66 -0
- package/dist/confirm-service/confirm-service.js +4 -3
- package/dist/content-layout/content-layout.js +1 -1
- package/dist/contenteditable/contenteditable.js +1 -1
- package/dist/data-list/data-list.js +6 -3
- package/dist/data-list/data-list.mock.js +2 -2
- package/dist/data-list/item.js +5 -3
- package/dist/data-list/selection.js +1 -1
- package/dist/data-list/title.js +3 -1
- package/dist/data-list-ng/data-list-ng.js +59 -0
- package/dist/date-picker/consts.js +1 -2
- package/dist/date-picker/date-input.js +10 -6
- package/dist/date-picker/date-picker.js +28 -16
- package/dist/date-picker/date-popup.js +20 -9
- package/dist/date-picker/day.js +1 -1
- package/dist/date-picker/formats.js +1 -1
- package/dist/date-picker/month-names.js +14 -7
- package/dist/date-picker/month-slider.js +1 -1
- package/dist/date-picker/month.js +12 -6
- package/dist/date-picker/months.js +1 -1
- package/dist/date-picker/weekdays.js +12 -4
- package/dist/date-picker/years.js +1 -1
- package/dist/dialog/dialog.js +3 -2
- package/dist/dialog-ng/dialog-ng.js +601 -0
- package/dist/dialog-ng/dialog-ng__template.js +71 -0
- package/dist/docked-panel-ng/docked-panel-ng.js +170 -0
- package/dist/dropdown/anchor.js +2 -1
- package/dist/dropdown/dropdown.js +3 -2
- package/dist/dropdown-menu/dropdown-menu.js +175 -0
- package/dist/error-bubble/error-bubble.js +2 -2
- package/dist/error-message/error-message.js +4 -4
- package/dist/error-message-ng/error-message-ng.js +53 -0
- package/dist/footer/footer.js +6 -122
- package/dist/footer-ng/footer-ng.js +75 -0
- package/dist/form-ng/form-ng.js +169 -0
- package/dist/global/angular-component-factory.js +1 -2
- package/dist/global/compose.js +1 -1
- package/dist/global/composeRefs.js +1 -1
- package/dist/global/conic-gradient.js +1 -2
- package/dist/global/create-stateful-context.js +1 -1
- package/dist/global/data-tests.js +1 -1
- package/dist/global/focus-sensor-hoc.js +1 -1
- package/dist/global/fuzzy-highlight.js +1 -1
- package/dist/global/get-event-key.js +1 -1
- package/dist/global/get-uid.js +1 -1
- package/dist/global/linear-function.js +1 -2
- package/dist/global/listeners.js +1 -1
- package/dist/global/memoize.js +1 -1
- package/dist/global/normalize-indent.js +1 -1
- package/dist/global/promise-with-timeout.js +1 -1
- package/dist/global/radial-gradient-mask.js +1 -1
- package/dist/global/react-dom-renderer.js +1 -1
- package/dist/global/rerender-hoc.js +1 -1
- package/dist/global/ring-angular-component.js +1 -1
- package/dist/global/schedule-raf.js +1 -1
- package/dist/global/sniffer.js +1 -1
- package/dist/global/supports-css.js +1 -1
- package/dist/global/theme.js +1 -2
- package/dist/global/trivial-template-tag.js +1 -1
- package/dist/global/variables_dark.js +1 -1
- package/dist/grid/col.js +1 -1
- package/dist/grid/row.js +1 -1
- package/dist/group/group.js +2 -3
- package/dist/group-ng/group-ng.js +11 -0
- package/dist/header/header.js +24 -19
- package/dist/header/logo.js +3 -2
- package/dist/header/profile.js +31 -25
- package/dist/header/services-link.js +1 -0
- package/dist/header/services.js +4 -2
- package/dist/header/smart-profile.js +22 -16
- package/dist/header/smart-services.js +5 -2
- package/dist/header/tray-icon.js +3 -2
- package/dist/header/tray.js +1 -1
- package/dist/heading/heading.js +2 -3
- package/dist/http/http.js +1 -2
- package/dist/http/http.mock.js +1 -1
- package/dist/hub-source/hub-source.js +1 -1
- package/dist/hub-source/hub-source__users-groups.js +1 -1
- package/dist/icon/icon.js +3 -2
- package/dist/icon/icon__svg.js +81 -6
- package/dist/icon/index.js +2 -1
- package/dist/icon-ng/icon-ng.js +89 -0
- package/dist/input/input.js +4 -5
- package/dist/input-ng/input-ng.js +166 -0
- package/dist/island/adaptive-island-hoc.js +1 -2
- package/dist/island/content.js +1 -1
- package/dist/island/header.js +1 -1
- package/dist/island/island.js +1 -2
- package/dist/island-legacy/content-legacy.js +1 -1
- package/dist/island-legacy/header-legacy.js +1 -1
- package/dist/island-legacy/island-legacy.js +1 -1
- package/dist/island-ng/island-content-ng.js +56 -0
- package/dist/island-ng/island-header-ng.js +32 -0
- package/dist/island-ng/island-ng-class-fixer.js +9 -0
- package/dist/island-ng/island-ng.js +31 -0
- package/dist/link/clickableLink.js +1 -1
- package/dist/link/link.js +2 -4
- package/dist/link-ng/link-ng.js +25 -0
- package/dist/list/list.js +13 -5
- package/dist/list/list__custom.js +8 -3
- package/dist/list/list__hint.js +1 -1
- package/dist/list/list__item.js +15 -6
- package/dist/list/list__link.js +2 -1
- package/dist/list/list__separator.js +1 -1
- package/dist/list/list__title.js +1 -1
- package/dist/list/list__users-groups-source.js +6 -2
- package/dist/loader/loader.js +1 -1
- package/dist/loader/loader__core.js +1 -1
- package/dist/loader-inline/loader-inline.js +1 -1
- package/dist/loader-inline-ng/loader-inline-ng.js +42 -0
- package/dist/loader-ng/loader-ng.js +43 -0
- package/dist/loader-screen/loader-screen.js +2 -3
- package/dist/loader-screen-ng/loader-screen-ng.js +99 -0
- package/dist/login-dialog/login-dialog.js +4 -2
- package/dist/login-dialog/service.js +4 -2
- package/dist/markdown/code.js +30 -0
- package/dist/markdown/heading.js +23 -0
- package/dist/markdown/link.js +30 -0
- package/dist/markdown/markdown.js +73 -0
- package/dist/message/message.js +4 -3
- package/dist/message-bundle-ng/message-bundle-ng.js +111 -0
- package/dist/pager/pager.js +16 -7
- package/dist/pager-ng/pager-ng.js +96 -0
- package/dist/panel/panel.js +2 -3
- package/dist/panel-ng/panel-ng.js +16 -0
- package/dist/permissions/permissions.js +1 -1
- package/dist/permissions/permissions__cache.js +1 -1
- package/dist/permissions-ng/permissions-ng.js +274 -0
- package/dist/place-under-ng/place-under-ng.js +157 -0
- package/dist/popup/popup.js +2 -3
- package/dist/popup/position.js +1 -2
- package/dist/popup-menu/popup-menu.js +6 -3
- package/dist/progress-bar/progress-bar.js +2 -2
- package/dist/progress-bar-ng/progress-bar-ng.js +15 -0
- package/dist/promised-click-ng/promised-click-ng.js +126 -0
- package/dist/proxy-attrs/proxy-attrs.js +1 -1
- package/dist/query-assist/query-assist.js +6 -3
- package/dist/query-assist/query-assist__suggestions.js +5 -1
- package/dist/query-assist-ng/query-assist-ng.js +82 -0
- package/dist/radio/radio.js +2 -1
- package/dist/radio/radio__item.js +2 -4
- package/dist/radio-ng/radio-ng.js +63 -0
- package/dist/save-field-ng/save-field-ng.js +335 -0
- package/dist/save-field-ng/save-field-ng__template.js +34 -0
- package/dist/select/select.js +13 -11
- package/dist/select/select__filter.js +6 -1
- package/dist/select/select__popup.js +7 -2
- package/dist/select-ng/select-ng.js +621 -0
- package/dist/select-ng/select-ng__lazy.js +150 -0
- package/dist/select-ng/select-ng__options.js +145 -0
- package/dist/shortcuts/core.js +2 -2
- package/dist/shortcuts/shortcuts-hoc.js +1 -1
- package/dist/shortcuts/shortcuts.js +6 -6
- package/dist/shortcuts-hint-ng/shortcuts-hint-ng.js +120 -0
- package/dist/shortcuts-hint-ng/shortcuts-hint-ng__template.js +50 -0
- package/dist/shortcuts-ng/shortcuts-ng.js +261 -0
- package/dist/sidebar-ng/sidebar-ng.js +111 -0
- package/dist/sidebar-ng/sidebar-ng__button-template.js +20 -0
- package/dist/sidebar-ng/sidebar-ng__template.js +12 -0
- package/dist/storage/storage.js +3 -2
- package/dist/storage/storage__fallback.js +1 -1
- package/dist/storage/storage__local.js +3 -2
- package/dist/style.css +1 -1
- package/dist/tab-trap/tab-trap.js +1 -2
- package/dist/table/cell.js +1 -1
- package/dist/table/disable-hover-hoc.js +1 -1
- package/dist/table/header-cell.js +3 -2
- package/dist/table/header.js +4 -2
- package/dist/table/multitable.js +1 -1
- package/dist/table/row-with-focus-sensor.js +4 -2
- package/dist/table/row.js +4 -2
- package/dist/table/selection-adapter.js +1 -1
- package/dist/table/selection-shortcuts-hoc.js +1 -1
- package/dist/table/selection.js +1 -1
- package/dist/table/smart-table.js +4 -2
- package/dist/table/table.js +4 -3
- package/dist/table-legacy-ng/table-legacy-ng.js +501 -0
- package/dist/table-legacy-ng/table-legacy-ng__pager.js +122 -0
- package/dist/table-legacy-ng/table-legacy-ng__selection-navigate-actions.js +123 -0
- package/dist/table-legacy-ng/table-legacy-ng__selection.js +179 -0
- package/dist/table-legacy-ng/table-legacy-ng__toolbar.js +56 -0
- package/dist/table-ng/smart-table-ng.js +65 -0
- package/dist/table-ng/table-ng.js +64 -0
- package/dist/tabs/collapsible-more.js +5 -1
- package/dist/tabs/collapsible-tab.js +2 -1
- package/dist/tabs/collapsible-tabs.js +6 -3
- package/dist/tabs/dumb-tabs.js +6 -2
- package/dist/tabs/smart-tabs.js +6 -2
- package/dist/tabs/tab-link.js +2 -1
- package/dist/tabs/tab.js +1 -1
- package/dist/tabs/tabs.js +5 -1
- package/dist/tabs-ng/tabs-ng.js +193 -0
- package/dist/tabs-ng/tabs-ng__template.js +40 -0
- package/dist/tag/tag.js +4 -3
- package/dist/tags-input/tags-input.js +12 -8
- package/dist/tags-input-ng/tags-input-ng.js +89 -0
- package/dist/tags-list/tags-list.js +3 -2
- package/dist/template-ng/template-ng.js +70 -0
- package/dist/text/text.js +1 -1
- package/dist/theme-ng/theme-ng.js +44 -0
- package/dist/title-ng/title-ng.js +114 -0
- package/dist/toggle/toggle.js +2 -3
- package/dist/toggle-ng/toggle-ng.js +16 -0
- package/dist/tooltip/tooltip.js +8 -4
- package/dist/tooltip-ng/tooltip-ng.js +98 -0
- package/dist/user-agreement/service.js +409 -0
- package/dist/user-agreement/toolbox.eula.js +162 -0
- package/dist/user-agreement/user-agreement.js +167 -0
- package/dist/user-card/card.js +3 -0
- package/dist/user-card/smart-user-card-tooltip.js +5 -2
- package/dist/user-card/tooltip.js +5 -2
- package/dist/user-card/user-card.js +5 -2
- package/dist/user-card-ng/user-card-ng.js +59 -0
- package/package.json +62 -64
- package/webpack.config.js +10 -8
- 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/caption.js +0 -25
- package/dist/_helpers/icon__svg.js +0 -82
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
position: absolute;
|
|
97
97
|
right: unit;
|
|
98
98
|
|
|
99
|
-
content:
|
|
99
|
+
content: "—";
|
|
100
100
|
|
|
101
101
|
line-height: calc(4 * unit - 2px);
|
|
102
102
|
}
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
position: absolute;
|
|
124
124
|
left: calc(-1 * unit);
|
|
125
125
|
|
|
126
|
-
content:
|
|
126
|
+
content: ",";
|
|
127
127
|
|
|
128
128
|
line-height: calc(4 * unit - 3px);
|
|
129
129
|
}
|
|
@@ -198,6 +198,8 @@
|
|
|
198
198
|
|
|
199
199
|
text-align: left;
|
|
200
200
|
|
|
201
|
+
text-transform: capitalize;
|
|
202
|
+
|
|
201
203
|
font-weight: bold;
|
|
202
204
|
|
|
203
205
|
@supports (flex-basis: 1px) {
|
|
@@ -282,7 +284,7 @@
|
|
|
282
284
|
width: calc(unit * 2);
|
|
283
285
|
height: 100%;
|
|
284
286
|
|
|
285
|
-
content:
|
|
287
|
+
content: "";
|
|
286
288
|
transition: background-color var(--ring-ease);
|
|
287
289
|
}
|
|
288
290
|
|
|
@@ -325,7 +327,7 @@
|
|
|
325
327
|
width: calc(unit * 23);
|
|
326
328
|
height: calc(unit * 8);
|
|
327
329
|
|
|
328
|
-
content:
|
|
330
|
+
content: "";
|
|
329
331
|
transition: background-color var(--ring-ease);
|
|
330
332
|
}
|
|
331
333
|
|
|
@@ -357,7 +359,7 @@
|
|
|
357
359
|
width: calc(unit * 2);
|
|
358
360
|
height: 100%;
|
|
359
361
|
|
|
360
|
-
content:
|
|
362
|
+
content: "";
|
|
361
363
|
transition: background-color var(--ring-ease);
|
|
362
364
|
}
|
|
363
365
|
}
|
|
@@ -409,7 +411,7 @@
|
|
|
409
411
|
top: 0;
|
|
410
412
|
left: calc(unit * 0.5);
|
|
411
413
|
|
|
412
|
-
content:
|
|
414
|
+
content: "•";
|
|
413
415
|
|
|
414
416
|
font-size: var(--ring-font-size-smaller);
|
|
415
417
|
}
|
|
@@ -453,6 +455,8 @@
|
|
|
453
455
|
height: cellSize;
|
|
454
456
|
padding-left: calc(unit * 1.5);
|
|
455
457
|
|
|
458
|
+
text-transform: capitalize;
|
|
459
|
+
|
|
456
460
|
line-height: cellSize;
|
|
457
461
|
}
|
|
458
462
|
|
|
@@ -90,7 +90,8 @@ export default class DatePicker extends PureComponent {
|
|
|
90
90
|
disabled: PropTypes.bool,
|
|
91
91
|
minDate: dateType,
|
|
92
92
|
maxDate: dateType,
|
|
93
|
-
translations: PropTypes.object
|
|
93
|
+
translations: PropTypes.object,
|
|
94
|
+
locale: PropTypes.object
|
|
94
95
|
};
|
|
95
96
|
|
|
96
97
|
static defaultProps = {
|
|
@@ -101,10 +102,10 @@ export default class DatePicker extends PureComponent {
|
|
|
101
102
|
from: null,
|
|
102
103
|
to: null,
|
|
103
104
|
clear: false,
|
|
104
|
-
displayFormat: date => (date ? formatDate(date, 'd MMM yyyy') : ''),
|
|
105
|
-
displayMonthFormat: date => (date ? formatDate(date, 'd MMM') : ''),
|
|
106
|
-
displayDayFormat: date => (date ? formatDate(date, 'd') : ''),
|
|
107
|
-
displayTimeFormat: date => (date ? formatDate(date, 'HH:mm') : ''),
|
|
105
|
+
displayFormat: (date, locale) => (date ? formatDate(date, 'd MMM yyyy', {locale}) : ''),
|
|
106
|
+
displayMonthFormat: (date, locale) => (date ? formatDate(date, 'd MMM', {locale}) : ''),
|
|
107
|
+
displayDayFormat: (date, locale) => (date ? formatDate(date, 'd', {locale}) : ''),
|
|
108
|
+
displayTimeFormat: (date, locale) => (date ? formatDate(date, 'HH:mm', {locale}) : ''),
|
|
108
109
|
datePlaceholder: 'Set a date',
|
|
109
110
|
dateTimePlaceholder: 'Set date and time',
|
|
110
111
|
rangePlaceholder: 'Set a period',
|
|
@@ -194,7 +195,8 @@ export default class DatePicker extends PureComponent {
|
|
|
194
195
|
displayFormat,
|
|
195
196
|
displayMonthFormat,
|
|
196
197
|
displayDayFormat,
|
|
197
|
-
translations
|
|
198
|
+
translations,
|
|
199
|
+
locale
|
|
198
200
|
} = this.props;
|
|
199
201
|
|
|
200
202
|
const date = this.parse(this.props.date);
|
|
@@ -204,27 +206,27 @@ export default class DatePicker extends PureComponent {
|
|
|
204
206
|
|
|
205
207
|
let text;
|
|
206
208
|
if (!range && !withTime) {
|
|
207
|
-
text = date ? displayFormat(date) : datePlaceholder || translations.setDate;
|
|
209
|
+
text = date ? displayFormat(date, locale) : datePlaceholder || translations.setDate;
|
|
208
210
|
} else if (!range && withTime) {
|
|
209
211
|
if (!date && !time) {
|
|
210
212
|
text = dateTimePlaceholder || translations.setDateTime;
|
|
211
213
|
} else {
|
|
212
|
-
text = `${date && displayFormat(date) || '—'}, ${time || '—'}`;
|
|
214
|
+
text = `${date && displayFormat(date, locale) || '—'}, ${time || '—'}`;
|
|
213
215
|
}
|
|
214
216
|
} else if (!from && !to) {
|
|
215
217
|
text = rangePlaceholder || translations.setPeriod;
|
|
216
218
|
} else if (!to) {
|
|
217
|
-
text = `${displayFormat(from)} —`;
|
|
219
|
+
text = `${displayFormat(from, locale)} —`;
|
|
218
220
|
} else if (!from) {
|
|
219
|
-
text = `— ${displayFormat(to)}`;
|
|
221
|
+
text = `— ${displayFormat(to, locale)}`;
|
|
220
222
|
} else if (!isSameYear(from, to)) {
|
|
221
|
-
text = `${displayFormat(from)} — ${displayFormat(to)}`;
|
|
223
|
+
text = `${displayFormat(from, locale)} — ${displayFormat(to, locale)}`;
|
|
222
224
|
} else if (!isSameMonth(from, to)) {
|
|
223
|
-
text = `${displayMonthFormat(from)} — ${displayFormat(to)}`;
|
|
225
|
+
text = `${displayMonthFormat(from, locale)} — ${displayFormat(to, locale)}`;
|
|
224
226
|
} else if (!isSameDay(from, to)) {
|
|
225
|
-
text = `${displayDayFormat(from)} — ${displayFormat(to)}`;
|
|
227
|
+
text = `${displayDayFormat(from, locale)} — ${displayFormat(to, locale)}`;
|
|
226
228
|
} else {
|
|
227
|
-
text = `${displayFormat(to)}`;
|
|
229
|
+
text = `${displayFormat(to, locale)}`;
|
|
228
230
|
}
|
|
229
231
|
|
|
230
232
|
return text;
|
|
@@ -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
|
|
|
@@ -297,7 +298,7 @@ export default class DatePopup extends Component {
|
|
|
297
298
|
};
|
|
298
299
|
|
|
299
300
|
render() {
|
|
300
|
-
const {range, hidden, withTime, time} = this.props;
|
|
301
|
+
const {range, hidden, withTime, time, locale} = this.props;
|
|
301
302
|
const parsedDate = this.parse(this.props.date, 'date');
|
|
302
303
|
const parsedTo = this.parse(this.props.to, 'to');
|
|
303
304
|
|
|
@@ -391,6 +392,7 @@ export default class DatePopup extends Component {
|
|
|
391
392
|
onInput={this.handleInput}
|
|
392
393
|
onConfirm={this.handleConfirm(name)}
|
|
393
394
|
onClear={onClear}
|
|
395
|
+
locale={locale}
|
|
394
396
|
/>
|
|
395
397
|
);
|
|
396
398
|
})}
|
|
@@ -413,12 +415,13 @@ export default class DatePopup extends Component {
|
|
|
413
415
|
onInput={this.handleInput}
|
|
414
416
|
onConfirm={this.handleConfirm('time')}
|
|
415
417
|
onClear={clearable && this.onClear || undefined}
|
|
418
|
+
locale={locale}
|
|
416
419
|
/>
|
|
417
420
|
)
|
|
418
421
|
: ('')
|
|
419
422
|
}
|
|
420
423
|
</div>
|
|
421
|
-
<Weekdays/>
|
|
424
|
+
<Weekdays locale={locale}/>
|
|
422
425
|
<div
|
|
423
426
|
className={styles.calendar}
|
|
424
427
|
>
|
|
@@ -426,6 +429,7 @@ export default class DatePopup extends Component {
|
|
|
426
429
|
{...calendarProps}
|
|
427
430
|
onHover={this.hoverHandler}
|
|
428
431
|
onSelect={this.selectHandler}
|
|
432
|
+
locale={locale}
|
|
429
433
|
/>
|
|
430
434
|
<Years {...calendarProps}/>
|
|
431
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
|
+
};
|
|
@@ -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';
|
|
@@ -16,6 +14,7 @@ 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
|
+
});
|