@synerise/ds-alert 0.5.1 → 0.6.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 CHANGED
@@ -3,6 +3,37 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.6.1](https://github.com/Synerise/synerise-design/compare/@synerise/ds-alert@0.6.0...@synerise/ds-alert@0.6.1) (2022-03-31)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **alert:** exporting NotificationProps typing ([985c994](https://github.com/Synerise/synerise-design/commit/985c994a516f0323e2903afddf9ca4bea33a594c))
12
+
13
+
14
+
15
+
16
+
17
+ # [0.6.0](https://github.com/Synerise/synerise-design/compare/@synerise/ds-alert@0.5.2...@synerise/ds-alert@0.6.0) (2022-03-30)
18
+
19
+
20
+ ### Features
21
+
22
+ * **alert:** add Notification component, stories, test todos ([eeb09d8](https://github.com/Synerise/synerise-design/commit/eeb09d857938100058e6c3112082014acdb67d6c))
23
+ * **alert:** add the remaining placements, code cleanup, storybook fixes ([c469574](https://github.com/Synerise/synerise-design/commit/c469574c2fa5135d956127a5bc35601808285569))
24
+
25
+
26
+
27
+
28
+
29
+ ## [0.5.2](https://github.com/Synerise/synerise-design/compare/@synerise/ds-alert@0.5.1...@synerise/ds-alert@0.5.2) (2022-03-21)
30
+
31
+ **Note:** Version bump only for package @synerise/ds-alert
32
+
33
+
34
+
35
+
36
+
6
37
  ## [0.5.1](https://github.com/Synerise/synerise-design/compare/@synerise/ds-alert@0.5.0...@synerise/ds-alert@0.5.1) (2022-03-14)
7
38
 
8
39
  **Note:** Version bump only for package @synerise/ds-alert
package/README.md CHANGED
@@ -13,7 +13,7 @@ yarn add @synerise/ds-alert
13
13
  ```
14
14
 
15
15
  ## Usage
16
- ```
16
+ ```jsx
17
17
  import Alert from '@synerise/ds-alert'
18
18
 
19
19
  <Alert
@@ -28,6 +28,38 @@ import Alert from '@synerise/ds-alert'
28
28
 
29
29
  ```
30
30
 
31
+ ### notifications api usage
32
+
33
+ #### Simple (`ant`-based)
34
+
35
+ ```jsx
36
+ import notification from '@ant/notification'
37
+
38
+ notification.open({message: 'Message content', duration 4.5})
39
+ ```
40
+
41
+ #### A `synerise-design`-styled notification
42
+ ```jsx
43
+ import Notification from '@ds-alert/Notification'
44
+ import notification from '@ant/notification'
45
+
46
+ notification.open({message: <Notification>'Message content'</Notification>, duration: 4.5})
47
+ ```
48
+
49
+ #### Differently positioned notification
50
+
51
+ `antd-notification` is mounted in `docuemnt.body` by default. In order to style using scoped css -
52
+ `getContainer` has to be a `styled-components`-scoped element, this is done in `mountInstance`, see source code for more.
53
+
54
+ ```jsx
55
+ import open from '@ds-alert/Notification'
56
+
57
+ const [api, contextHolder] = notification.useNotification();
58
+ open({message: Message content, duration: 4.5}, api, contextHolder))
59
+
60
+ console.log('@synerise/ds-alert notifications get mounted in this container', document.querySelector('.popup-container'))
61
+ ```
62
+
31
63
  ## Demo
32
64
 
33
65
  <iframe src="/storybook-static/iframe.html?id=components-alert--default"></iframe>
@@ -131,4 +163,17 @@ import Alert from '@synerise/ds-alert'
131
163
  | withClose | prop to set closeIcon | `React.ReactNode` | - |
132
164
  | button | prop to set button | `boolean` | - |
133
165
  | textButton | string of button | `string` | - |
134
- | text | string of withEmphasis or withLink | `string` | - |
166
+ | text | string of withEmphasis or withLink | `string` | - |
167
+
168
+
169
+ ### Alert.Notification
170
+ | Property | Description | Type | Default |
171
+ |---------------------|---------------------------------------------------------------------------------------------------|---------------------------------------------------------------|-----------------|
172
+ | children | Content of the notification | string\/React.ReactNode\/JSX.Element | JSX.Element |
173
+ | type | type of the notification, `"info"/"success"`, see `antd-notification`, `info` by default | keyof NotificationInstance | "info" |
174
+ | placement | where to position the notification | 'bottomLeft' 'bottomRight' 'topLeft' 'topRight' 'bottom' | "bottom" |
175
+ | onClose? | Handler for clicking on the close button (close button is rendered only if this prop is provided) | () => void | - |
176
+ | buttonText? | Text on the action button | string | - |
177
+ | onButtonClick? | Handler for `onClick` on the action button | () => void | - |
178
+ | icon? | Icon on the action button | DSIcon | - |
179
+ | closeIconClassName? | Class of the close icon name | string | "ds-close-icon" |
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import { NotificationInstance } from 'antd/lib/notification';
3
+ import type { ArgsProps, NotificationApi } from 'antd/es/notification';
4
+ import 'antd/lib/notification/style/index.less';
5
+ export declare type NotificationProps = {
6
+ /** content of the notification */
7
+ children?: JSX.Element | React.ReactNode | React.ReactNode[];
8
+ /** text displayed on the button */
9
+ buttonText?: string;
10
+ /** type of the notification, `"info" | "success"`, see `antd/notification`, `info` by default */
11
+ type?: keyof NotificationInstance;
12
+ /** handler for clicking on the button, note button is rendered only if `buttonText` is provided */
13
+ onButtonClick?: (ev: React.MouseEvent<HTMLElement, MouseEvent>) => void;
14
+ /** close icon class */
15
+ closeIconClassName?: string;
16
+ /** where to position notification, `"{top,bottom}{Left,Right}" | "bottom"` */
17
+ placement: ArgsProps['placement'] | 'bottom';
18
+ } & Partial<Omit<ArgsProps, 'placement'>>;
19
+ declare type NotificationApiHook = ReturnType<NotificationApi['useNotification']>;
20
+ declare type ApiHook = NotificationApiHook[0];
21
+ declare type ContextHolder = NotificationApiHook[1];
22
+ export declare function Notification({ buttonText, children, onButtonClick, onClose, icon, closeIconClassName, }: NotificationProps): JSX.Element;
23
+ /**
24
+ * creates a div, mounts it in getContainer and returns reference to it.
25
+ * This is a helper function for creating a getContainer-compatible element,
26
+ * which later should be passed to getContainer option in `antd-notification`'s api
27
+ *
28
+ * @param @contextHolder notification's hook api context
29
+ * @param @getContainer where to mount styled wrapper; can be a ref=React.useRef, <div ref={ref}/>
30
+ **/
31
+ export declare function mountInstance(contextHolder?: ContextHolder, { getContainer, className }?: {
32
+ getContainer?: (() => HTMLElement) | undefined;
33
+ className?: string | undefined;
34
+ }): [HTMLElement | null, Function];
35
+ export declare function notificationOpen({ type, className, message, icon, onClick, onClose, closeIconClassName, placement, ...props }: NotificationProps, notificationApi?: ApiHook, contextHolder?: ContextHolder): void;
36
+ export default Notification;
@@ -0,0 +1,134 @@
1
+ var _excluded = ["type", "className", "message", "icon", "onClick", "onClose", "closeIconClassName", "placement"];
2
+
3
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
4
+
5
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6
+
7
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+
9
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
10
+
11
+ import * as React from 'react';
12
+ import * as ReactDOM from 'react-dom';
13
+ import { notification } from 'antd';
14
+ import "antd/lib/notification/style/index.css";
15
+ import Button from '@synerise/ds-button';
16
+ import Icon, { UserAddM, CloseM } from '@synerise/ds-icon';
17
+ import * as S from './Notification.styles';
18
+ export function Notification(_ref) {
19
+ var buttonText = _ref.buttonText,
20
+ _ref$children = _ref.children,
21
+ children = _ref$children === void 0 ? undefined : _ref$children,
22
+ onButtonClick = _ref.onButtonClick,
23
+ onClose = _ref.onClose,
24
+ icon = _ref.icon,
25
+ _ref$closeIconClassNa = _ref.closeIconClassName,
26
+ closeIconClassName = _ref$closeIconClassNa === void 0 ? 'ds-close-icon' : _ref$closeIconClassNa;
27
+ return /*#__PURE__*/React.createElement(S.NotificationsContainer, null, /*#__PURE__*/React.createElement(S.TextLabel, null, children), (buttonText || onClose) && /*#__PURE__*/React.createElement(S.Shrink, null, buttonText && /*#__PURE__*/React.createElement(Button, {
28
+ type: "primary",
29
+ mode: "icon-label",
30
+ color: "blue",
31
+ onClick: onButtonClick
32
+ }, icon || icon !== null && /*#__PURE__*/React.createElement(Icon, {
33
+ component: /*#__PURE__*/React.createElement(UserAddM, null)
34
+ }), buttonText), onClose && /*#__PURE__*/React.createElement(Button, {
35
+ className: closeIconClassName,
36
+ type: "ghost",
37
+ onClick: onClose
38
+ }, /*#__PURE__*/React.createElement(Icon, {
39
+ component: /*#__PURE__*/React.createElement(CloseM, null)
40
+ }))));
41
+ }
42
+ /**
43
+ * creates a div, mounts it in getContainer and returns reference to it.
44
+ * This is a helper function for creating a getContainer-compatible element,
45
+ * which later should be passed to getContainer option in `antd-notification`'s api
46
+ *
47
+ * @param @contextHolder notification's hook api context
48
+ * @param @getContainer where to mount styled wrapper; can be a ref=React.useRef, <div ref={ref}/>
49
+ **/
50
+
51
+ export function mountInstance(contextHolder, _temp) {
52
+ var _ref2 = _temp === void 0 ? {} : _temp,
53
+ _ref2$getContainer = _ref2.getContainer,
54
+ getContainer = _ref2$getContainer === void 0 ? function () {
55
+ return document.body;
56
+ } : _ref2$getContainer,
57
+ _ref2$className = _ref2.className,
58
+ className = _ref2$className === void 0 ? 'popup-container' : _ref2$className;
59
+
60
+ var element = document.createElement('div');
61
+ element.setAttribute('class', className);
62
+ var cont = getContainer();
63
+ cont.appendChild(element);
64
+ var jsxEl = /*#__PURE__*/React.createElement(S.NotificationsWrapper, null, contextHolder);
65
+ ReactDOM.render(jsxEl, element);
66
+
67
+ var cleanUpFunction = function cleanUpFunction() {
68
+ cont.removeChild(element);
69
+ };
70
+
71
+ return [element, cleanUpFunction];
72
+ }
73
+ export function notificationOpen(_ref3, notificationApi, contextHolder) {
74
+ var _ref3$type = _ref3.type,
75
+ type = _ref3$type === void 0 ? 'info' : _ref3$type,
76
+ _ref3$className = _ref3.className,
77
+ className = _ref3$className === void 0 ? 'popup-container' : _ref3$className,
78
+ message = _ref3.message,
79
+ icon = _ref3.icon,
80
+ onClick = _ref3.onClick,
81
+ onClose = _ref3.onClose,
82
+ _ref3$closeIconClassN = _ref3.closeIconClassName,
83
+ closeIconClassName = _ref3$closeIconClassN === void 0 ? 'ds-close-icon' : _ref3$closeIconClassN,
84
+ _ref3$placement = _ref3.placement,
85
+ placement = _ref3$placement === void 0 ? 'bottom' : _ref3$placement,
86
+ props = _objectWithoutPropertiesLoose(_ref3, _excluded);
87
+
88
+ var api = notificationApi || notification; // TODO: check if context is actually available
89
+
90
+ var el = document.body.querySelector("." + className);
91
+
92
+ if (!el) {
93
+ var _mountInstance = mountInstance(contextHolder, {
94
+ className: className
95
+ });
96
+
97
+ el = _mountInstance[0];
98
+ }
99
+
100
+ var getContainer = function getContainer() {
101
+ var _el;
102
+
103
+ return (_el = el) == null ? void 0 : _el.querySelector('div>div,.NotificationsBottomPlacementWrapper>.NotificationsWrapper');
104
+ };
105
+ /** a workaround for handling close clicks,
106
+ * since there's no way for injecting other element triggering onClose listener.
107
+ * It is set as a listener for all the clicks
108
+ * and fires onClose when close-icon was clicked */
109
+
110
+
111
+ var maybeCloseClick = function maybeCloseClick(ev) {
112
+ var _ev$currentTarget;
113
+
114
+ var isClickedElementChildOfCloseIcon = ev.target.closest("." + closeIconClassName);
115
+ var isThisCloseIcon = ev == null ? void 0 : (_ev$currentTarget = ev.currentTarget) == null ? void 0 : _ev$currentTarget.classList.contains("" + closeIconClassName);
116
+
117
+ if (isClickedElementChildOfCloseIcon || isThisCloseIcon) {
118
+ return onClose && onClose();
119
+ }
120
+
121
+ return onClick && onClick();
122
+ };
123
+
124
+ return api.open(_objectSpread({
125
+ message: message,
126
+ type: type,
127
+ placement: placement,
128
+ getContainer: getContainer,
129
+ icon: icon,
130
+ onClick: maybeCloseClick,
131
+ bottom: 16
132
+ }, props));
133
+ }
134
+ export default Notification;
@@ -0,0 +1,11 @@
1
+ export declare const NotificationsContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
2
+ export declare const Shrink: import("styled-components").StyledComponent<"div", any, {}, never>;
3
+ export declare const TextLabel: import("styled-components").StyledComponent<"div", any, {}, never>;
4
+ export declare const NotificationsWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
5
+ declare const _default: {
6
+ NotificationsContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
7
+ NotificationsWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
8
+ TextLabel: import("styled-components").StyledComponent<"div", any, {}, never>;
9
+ Shrink: import("styled-components").StyledComponent<"div", any, {}, never>;
10
+ };
11
+ export default _default;
@@ -0,0 +1,36 @@
1
+ import styled from 'styled-components';
2
+ import theme from '@synerise/ds-core/dist/js/DSProvider/ThemeProvider/theme';
3
+ export var NotificationsContainer = styled.div.withConfig({
4
+ displayName: "Notificationstyles__NotificationsContainer",
5
+ componentId: "sc-1ke52b0-0"
6
+ })(["background-color:", ";color:white;min-width:588px;padding:8px 8px 8px 16px;display:flex;align-items:center;width:100px;min-height:50px;"], function (props) {
7
+ var _palette;
8
+
9
+ return (_palette = ((props == null ? void 0 : props.theme) || theme).palette) == null ? void 0 : _palette['grey-800'];
10
+ });
11
+ export var Shrink = styled.div.withConfig({
12
+ displayName: "Notificationstyles__Shrink",
13
+ componentId: "sc-1ke52b0-1"
14
+ })(["flex-grow:0;"]);
15
+ export var TextLabel = styled.div.withConfig({
16
+ displayName: "Notificationstyles__TextLabel",
17
+ componentId: "sc-1ke52b0-2"
18
+ })(["flex-grow:1;font-size:13px;"]);
19
+ export var NotificationsWrapper = styled.div.withConfig({
20
+ displayName: "Notificationstyles__NotificationsWrapper",
21
+ componentId: "sc-1ke52b0-3"
22
+ })(["& .ant-notification-bottom .ant-notification-hook-holder{margin:0;&:not(:first-child){margin-top:8px;}}& .ant-notification.ant-notification-bottom{right:0;left:0;margin:0 auto;width:588px;bottom:8px;}& .ant-notification-hook-holder{background-color:transparent;box-shadow:none;width:588px;}& .ant-notification-notice{padding:0;background-color:transparent;margin:unset;}& .ant-notification-notice{background-color:transparent;width:588px;border-radius:3px;box-shadow:0 16px 32px 0 ", "1a,0 8px 16px 0 ", "1a;}.ant-notification-notice-icon{display:none;}.ant-notification-notice-with-icon{background-color:transparent;}.ant-notification-notice-close{display:none;}& .ant-notification-notice-message,& .ant-notification-notice-closable .ant-notification-notice-message{padding-right:0;}& .ant-notification-notice-message,& .ant-notification-notice-with-icon .ant-notification-notice-message{margin-left:0;margin-bottom:0;}}"], function (props) {
23
+ var _palette2;
24
+
25
+ return (_palette2 = ((props == null ? void 0 : props.theme) || theme).palette) == null ? void 0 : _palette2['grey-900'];
26
+ }, function (props) {
27
+ var _palette3;
28
+
29
+ return (_palette3 = ((props == null ? void 0 : props.theme) || theme).palette) == null ? void 0 : _palette3['grey-900'];
30
+ });
31
+ export default {
32
+ NotificationsContainer: NotificationsContainer,
33
+ NotificationsWrapper: NotificationsWrapper,
34
+ TextLabel: TextLabel,
35
+ Shrink: Shrink
36
+ };
@@ -0,0 +1,27 @@
1
+ describe('notification', function () {
2
+ it.todo('notification message should allow passing jsx component');
3
+ it.todo('notification should have close-button');
4
+ it.todo('notification holder should have no padding nor margin');
5
+ it.todo('by default there should be no icon');
6
+ it.todo('notifications should be closable with a close icon-click');
7
+ it.todo('notifications should dissapear after given time');
8
+ it.todo('pass duration and other props to the notification.open api');
9
+ it.todo('should mount in a styled-components NotificationWrapper wrapper (not next to as a e.g. sibling)');
10
+ it.todo('notification message can handle multiline and/or long messages');
11
+ it.todo('notifications appear correctly even after destroying notifications instance');
12
+ it.todo('notification container has no background (so border-radius on the content can be applied)');
13
+ it.todo('container has background-color of gray-900 and 3px border-radius, padding-left is 16px');
14
+ it.todo('shadow has gray-800');
15
+ it.todo('default text font-size is 13px');
16
+ it.todo('button label font-size is 13px');
17
+ it.todo('notification has min-height of 50px (NotificationsContainer)');
18
+ it.todo('ant-notification-hook-holder should have 0px height if empty (including margins)');
19
+ it.todo('first ant-notification-hook-handler has margin-top 0px, the other ones have 8px');
20
+ it.todo('.ant-notification > div should have transparent background');
21
+ it.todo('close button and action button can be shown separately (even exclusively)');
22
+ it.todo("Notification's message can accept special characters \"&'");
23
+ it.todo('placement bottom applies .ant-notification-bottom class to the container');
24
+ it.todo('sending notification with another placement handles it correctly');
25
+ it.todo('getContainer should always point at NotificationsWrapper element');
26
+ it.todo('.ant-notification-bottom should be properly styled even if e.g. .ant-notification-topLeft was added first (`.ant-notification{, }.ant-notification-bottom`)');
27
+ });
package/dist/index.d.ts CHANGED
@@ -1 +1,5 @@
1
1
  export { default } from './Alert';
2
+ export * as S from './Notification/Notification.styles';
3
+ export { default as Notification } from './Notification/Notification';
4
+ export type { NotificationProps } from './Notification/Notification';
5
+ export { notificationOpen } from './Notification/Notification';
package/dist/index.js CHANGED
@@ -1 +1,5 @@
1
- export { default } from './Alert';
1
+ export { default } from './Alert';
2
+ import * as _S from './Notification/Notification.styles';
3
+ export { _S as S };
4
+ export { default as Notification } from './Notification/Notification';
5
+ export { notificationOpen } from './Notification/Notification';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-alert",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "Alert UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "Synerise/synerise-design",
@@ -32,10 +32,10 @@
32
32
  ],
33
33
  "types": "dist/index.d.ts",
34
34
  "dependencies": {
35
- "@synerise/ds-button": "^0.17.0",
36
- "@synerise/ds-icon": "^0.47.2",
35
+ "@synerise/ds-button": "^0.17.2",
36
+ "@synerise/ds-icon": "^0.49.0",
37
37
  "@synerise/ds-typography": "^0.12.2",
38
- "@synerise/ds-unordered-list": "^0.2.8",
38
+ "@synerise/ds-unordered-list": "^0.2.10",
39
39
  "animate.css": "^4.1.1",
40
40
  "react-animate-height": "^2.0.23",
41
41
  "react-mount-animation": "0.0.9"
@@ -47,5 +47,5 @@
47
47
  "devDependencies": {
48
48
  "@synerise/ds-utils": "^0.19.0"
49
49
  },
50
- "gitHead": "739b52320bb20c1646371224de5bb0c3454fac8c"
50
+ "gitHead": "510d01309981d010c794496292be958796c0b6b6"
51
51
  }