@soul-refiner/design-system 0.2.102 → 0.2.104
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/dist/components/atoms/index.d.ts +2 -0
- package/dist/components/atoms/index.js +1 -0
- package/dist/components/atoms/time_ago/index.d.ts +2 -0
- package/dist/components/atoms/time_ago/index.js +1 -0
- package/dist/components/atoms/time_ago/time_ago.d.ts +5 -0
- package/dist/components/{surfaces/post/helpers.js → atoms/time_ago/time_ago.js} +9 -4
- package/dist/components/hooks/click-outside.d.ts +2 -0
- package/dist/components/hooks/click-outside.js +10 -0
- package/dist/components/hooks/event-listenter.d.ts +1 -0
- package/dist/components/hooks/event-listenter.js +15 -0
- package/dist/components/hooks/hover.d.ts +2 -0
- package/dist/components/hooks/hover.js +9 -0
- package/dist/components/hooks/index.d.ts +4 -0
- package/dist/components/hooks/index.js +4 -0
- package/dist/components/hooks/window-size.d.ts +4 -0
- package/dist/components/hooks/window-size.js +13 -0
- package/dist/components/iconography/avatar/avatar.d.ts +3 -1
- package/dist/components/iconography/avatar/avatar.js +29 -12
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/surfaces/post/post.js +3 -3
- package/package.json +1 -1
- package/dist/components/surfaces/post/helpers.d.ts +0 -1
|
@@ -2,3 +2,5 @@ export { Box } from './box';
|
|
|
2
2
|
export type { BoxProps } from './box';
|
|
3
3
|
export { Display, H, P, Typography } from './typography';
|
|
4
4
|
export type { DisplayProps, HeadingProps, ParagraphProps, TypographyProps, } from './typography';
|
|
5
|
+
export { TimeAgo } from './time_ago';
|
|
6
|
+
export type { TimeAgoProps } from './time_ago';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { TimeAgo } from './time_ago';
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export const TimeAgo = ({ date }) => {
|
|
4
|
+
return React.createElement(React.Fragment, null, abbrTimeBeforeDate(date));
|
|
5
|
+
};
|
|
6
|
+
const abbrTimeBeforeDate = (date) => {
|
|
2
7
|
const now = new Date();
|
|
3
8
|
const diff = now.getTime() - date.getTime();
|
|
4
9
|
if (diff < 60000) {
|
|
@@ -8,17 +13,17 @@ export const abbrTimeBeforeDate = (date) => {
|
|
|
8
13
|
else if (diff < 3600000) {
|
|
9
14
|
// under one hour
|
|
10
15
|
const minutes = Math.floor(diff / 60000);
|
|
11
|
-
return `${minutes} ${minutes === 1 ? 'min' : 'mins'}`;
|
|
16
|
+
return `${minutes} ${minutes === 1 ? 'min' : 'mins'} ago`;
|
|
12
17
|
}
|
|
13
18
|
else if (diff < 86400000) {
|
|
14
19
|
// under one day
|
|
15
20
|
const hours = Math.floor(diff / 3600000);
|
|
16
|
-
return `${hours} ${hours === 1 ? 'hour' : 'hours'}`;
|
|
21
|
+
return `${hours} ${hours === 1 ? 'hour' : 'hours'} ago`;
|
|
17
22
|
}
|
|
18
23
|
else if (diff < 604800000) {
|
|
19
24
|
// under one week
|
|
20
25
|
const days = Math.floor(diff / 86400000);
|
|
21
|
-
return `${days} ${days === 1 ? 'day' : 'days'}`;
|
|
26
|
+
return `${days} ${days === 1 ? 'day' : 'days'} ago`;
|
|
22
27
|
}
|
|
23
28
|
else {
|
|
24
29
|
return date.toDateString().slice(4);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEventListener } from './event-listenter';
|
|
3
|
+
export const useClickOutside = (ref, cb) => {
|
|
4
|
+
useEventListener('click', (e) => {
|
|
5
|
+
if (ref?.current == null ||
|
|
6
|
+
ref?.current?.contains(e.target))
|
|
7
|
+
return;
|
|
8
|
+
cb(e);
|
|
9
|
+
}, document);
|
|
10
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useEventListener: (eventType: string, callback: (...args: any[]) => unknown, element?: Window & typeof globalThis) => void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export const useEventListener = (eventType, callback, element = window) => {
|
|
4
|
+
const callbackRef = React.useRef(callback);
|
|
5
|
+
React.useEffect(() => {
|
|
6
|
+
callbackRef.current = callback;
|
|
7
|
+
}, [callback]);
|
|
8
|
+
React.useEffect(() => {
|
|
9
|
+
if (element == null)
|
|
10
|
+
return;
|
|
11
|
+
const handler = (e) => callbackRef.current(e);
|
|
12
|
+
element.addEventListener(eventType, handler);
|
|
13
|
+
return () => element.removeEventListener(eventType, handler);
|
|
14
|
+
}, [eventType, element]);
|
|
15
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useEventListener } from './event-listenter';
|
|
4
|
+
export const useHover = (ref) => {
|
|
5
|
+
const [hovered, setHovered] = React.useState(false);
|
|
6
|
+
useEventListener('mouseover', () => setHovered(true), ref?.current);
|
|
7
|
+
useEventListener('mouseout', () => setHovered(false), ref?.current);
|
|
8
|
+
return hovered;
|
|
9
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useEventListener } from './event-listenter';
|
|
4
|
+
export const useWindowSize = () => {
|
|
5
|
+
const [windowSize, setWindowSize] = React.useState({
|
|
6
|
+
width: window.innerWidth,
|
|
7
|
+
height: window.innerHeight,
|
|
8
|
+
});
|
|
9
|
+
useEventListener('resize', () => {
|
|
10
|
+
setWindowSize({ width: window.innerWidth, height: window.innerHeight });
|
|
11
|
+
});
|
|
12
|
+
return windowSize;
|
|
13
|
+
};
|
|
@@ -15,13 +15,15 @@ export interface AvatarProps extends NativeProps {
|
|
|
15
15
|
textPosition?: 'left' | 'right';
|
|
16
16
|
title?: React.ReactNode;
|
|
17
17
|
tooltipContent?: React.ReactElement;
|
|
18
|
+
tooltipSx?: string;
|
|
19
|
+
tooltipWrapperId?: string;
|
|
18
20
|
}
|
|
19
21
|
/**
|
|
20
22
|
*
|
|
21
23
|
* Avatar
|
|
22
24
|
*/
|
|
23
25
|
declare const Avatar: {
|
|
24
|
-
({ as, href, image, size, status, subtitle, sx, textPosition, title, tooltipContent, ...rest }: AvatarProps): React.JSX.Element;
|
|
26
|
+
({ as, href, image, size, status, subtitle, sx, textPosition, title, tooltipContent, tooltipSx, tooltipWrapperId, ...rest }: AvatarProps): React.JSX.Element;
|
|
25
27
|
displayName: string;
|
|
26
28
|
Group: {
|
|
27
29
|
({ children, numDisplayed, total }: AvatarGroupProps): React.JSX.Element;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
|
-
import { Box, H, P } from '../../';
|
|
4
|
+
import { Box, H, P, Portal } from '../../';
|
|
5
5
|
import { Approved, Busy, Declined, Default, Focus, Locked, Offline, Online, Subscribed, } from './icons';
|
|
6
|
+
import { useHover } from '../../../';
|
|
6
7
|
/**
|
|
7
8
|
* Lookup tables for sizes
|
|
8
9
|
*/
|
|
@@ -57,16 +58,14 @@ const iconOffsetY = {
|
|
|
57
58
|
*
|
|
58
59
|
* Avatar
|
|
59
60
|
*/
|
|
60
|
-
const Avatar = ({ as = 'button', href, image, size = 64, status, subtitle, sx, textPosition = 'left', title, tooltipContent, ...rest }) => {
|
|
61
|
+
const Avatar = ({ as = 'button', href, image, size = 64, status, subtitle, sx, textPosition = 'left', title, tooltipContent, tooltipSx, tooltipWrapperId = 'avatar-tooltip', ...rest }) => {
|
|
61
62
|
const [displayDefault, setDisplayDefault] = React.useState(false);
|
|
63
|
+
const componentWrapperRef = React.useRef(null);
|
|
64
|
+
const tooltipRef = React.useRef(null);
|
|
65
|
+
const hovered = useHover(componentWrapperRef);
|
|
66
|
+
const tooltipHovered = useHover(tooltipRef);
|
|
62
67
|
const Icon = iconReference?.[status ?? 'none'];
|
|
63
|
-
return (React.createElement(
|
|
64
|
-
position: relative;
|
|
65
|
-
&:hover > div:nth-of-type(2) {
|
|
66
|
-
display: flex;
|
|
67
|
-
}
|
|
68
|
-
${sx}
|
|
69
|
-
`, ...rest },
|
|
68
|
+
return (React.createElement(ComponentWrapper, { id: "avatar-tooltip", ref: componentWrapperRef, "$sx": sx, ...rest },
|
|
70
69
|
React.createElement(Container, { as: as, "$size": size, href: href },
|
|
71
70
|
!displayDefault && (React.createElement("img", { src: image ?? '', onError: () => setDisplayDefault(true) })),
|
|
72
71
|
displayDefault && React.createElement(Default, null),
|
|
@@ -75,9 +74,26 @@ const Avatar = ({ as = 'button', href, image, size = 64, status, subtitle, sx, t
|
|
|
75
74
|
(title || subtitle) && (React.createElement(TextContainer, { "$textPosition": textPosition },
|
|
76
75
|
title && (React.createElement(H, { as: "h3", "$bold": true, "$color": "grey-2", "$textClampLines": 1, sx: "font-size: 26px;" }, title)),
|
|
77
76
|
subtitle && (React.createElement(P, { "$color": "grey-4", "$textClampLines": 1 }, subtitle)))),
|
|
78
|
-
tooltipContent && React.createElement(
|
|
77
|
+
tooltipContent && (React.createElement(Portal, { wrapperId: tooltipWrapperId },
|
|
78
|
+
React.createElement(TooltipContainer, { id: "tooltip-container", ref: tooltipRef, "$sx": `${hovered || tooltipHovered ? 'display: flex' : 'display: none'}; ${tooltipSx}` }, tooltipContent)))));
|
|
79
79
|
};
|
|
80
80
|
Avatar.displayName = 'Avatar';
|
|
81
|
+
const ComponentWrapper = styled.div `
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
gap: 18px;
|
|
85
|
+
flex: none;
|
|
86
|
+
flex-flow: row;
|
|
87
|
+
flex-direction: row;
|
|
88
|
+
justify-content: normal;
|
|
89
|
+
background-color: var(--page-bg);
|
|
90
|
+
box-shadow: none;
|
|
91
|
+
margin: 0px;
|
|
92
|
+
padding: 0px;
|
|
93
|
+
position: relative;
|
|
94
|
+
|
|
95
|
+
${({ $sx }) => ($sx ? $sx : '')};
|
|
96
|
+
`;
|
|
81
97
|
const Container = styled.div `
|
|
82
98
|
flex-shrink: 0;
|
|
83
99
|
display: flex;
|
|
@@ -115,13 +131,14 @@ const TextContainer = styled.div `
|
|
|
115
131
|
order: ${({ $textPosition }) => ($textPosition === 'left' ? -1 : 1)};
|
|
116
132
|
`;
|
|
117
133
|
const TooltipContainer = styled.div `
|
|
118
|
-
display: none;
|
|
119
134
|
position: absolute;
|
|
120
135
|
top: 100%;
|
|
121
|
-
|
|
136
|
+
z-index: 250;
|
|
122
137
|
background-color: var(--color-white);
|
|
123
138
|
border-radius: 24px;
|
|
124
139
|
box-shadow: var(--elevation-2);
|
|
140
|
+
// pointer-events: none;
|
|
141
|
+
${({ $sx }) => ($sx ? $sx : '')}
|
|
125
142
|
`;
|
|
126
143
|
const Group = ({ children, numDisplayed, total }) => {
|
|
127
144
|
let size = 0;
|
package/dist/components/index.js
CHANGED
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
import { H, P } from '../../atoms/typography';
|
|
5
|
+
import { TimeAgo } from '../../atoms/time_ago/time_ago';
|
|
5
6
|
import { Button } from '../../actions/button';
|
|
6
7
|
import { Avatar } from '../../iconography/avatar';
|
|
7
8
|
import { Lock } from '../../../icons';
|
|
8
|
-
import { abbrTimeBeforeDate } from './helpers';
|
|
9
9
|
export const Post = ({ actions, author, authorActive, authorHref, authorImage, avatarTooltipContent, children, content, createdDate, dropdown, hasComments, id, images, isPaywalled = false, onJoin, }) => {
|
|
10
10
|
const componentId = React.useId();
|
|
11
11
|
const _actions = React.Children.toArray(actions);
|
|
12
12
|
const _comments = React.Children.toArray(children);
|
|
13
|
-
const subtitle = abbrTimeBeforeDate(new Date(createdDate));
|
|
14
13
|
return (React.createElement(Wrapper, { id: id },
|
|
15
14
|
React.createElement(Header, null,
|
|
16
|
-
React.createElement(Avatar, { href: authorHref, image: authorImage, size: 64, status: authorActive ? 'online' : undefined, subtitle: React.createElement(P, { as: "span", sx: "vertical-align: top;", "$fontSize": 14, "$lineHeight": 20 },
|
|
15
|
+
React.createElement(Avatar, { href: authorHref, image: authorImage, size: 64, status: authorActive ? 'online' : undefined, subtitle: React.createElement(P, { as: "span", sx: "vertical-align: top;", "$fontSize": 14, "$lineHeight": 20 },
|
|
16
|
+
React.createElement(TimeAgo, { date: new Date(createdDate) })), title: React.createElement(H, { as: "span", "$bold": true, "$fontSize": 18, "$lineHeight": 26 }, author), textPosition: "right", tooltipContent: avatarTooltipContent }),
|
|
17
17
|
dropdown),
|
|
18
18
|
!!content?.length && (React.createElement("div", { style: { padding: 24 } },
|
|
19
19
|
React.createElement(P, { "$textClampLines": isPaywalled ? 2 : undefined }, content))),
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const abbrTimeBeforeDate: (date: Date) => string;
|