@fibery/ui-kit 1.19.0 → 1.20.0

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.
Files changed (50) hide show
  1. package/package.json +7 -6
  2. package/src/a11y-color.ts +9 -6
  3. package/src/antd/styles.ts +6 -6
  4. package/src/button/button.tsx +5 -5
  5. package/src/design-system.ts +19 -18
  6. package/src/emoji-picker/emoji-picker-content-with-color.tsx +1 -1
  7. package/src/emoji-picker/emoji-picker.tsx +2 -2
  8. package/src/emoji-picker/icon-emoji-picker.tsx +1 -1
  9. package/src/emoji-picker/primitives/category.tsx +2 -2
  10. package/src/emoji-picker/primitives/emoji.tsx +26 -3
  11. package/src/emoji-picker/primitives/footer.tsx +1 -1
  12. package/src/emoji-picker/primitives/header.tsx +1 -1
  13. package/src/emoji-picker/primitives/layout.ts +2 -2
  14. package/src/emoji-picker/primitives/search.tsx +5 -5
  15. package/src/error-alert.tsx +3 -3
  16. package/src/form-field-loader.tsx +3 -3
  17. package/src/icons/ast/AlertTriangle.ts +8 -0
  18. package/src/icons/ast/DragBlockHandleSingle.ts +8 -0
  19. package/src/icons/ast/Eye.ts +8 -0
  20. package/src/icons/ast/NetworkAdd.ts +8 -0
  21. package/src/icons/ast/RemovePeople.ts +8 -0
  22. package/src/icons/ast/RicheditorMarkTextBackgroundColor.ts +8 -0
  23. package/src/icons/ast/index.tsx +6 -1
  24. package/src/icons/react/AlertTriangle.tsx +12 -0
  25. package/src/icons/react/DragBlockHandleSingle.tsx +12 -0
  26. package/src/icons/react/Eye.tsx +12 -0
  27. package/src/icons/react/NetworkAdd.tsx +12 -0
  28. package/src/icons/react/RemovePeople.tsx +12 -0
  29. package/src/icons/react/RicheditorMarkTextBackgroundColor.tsx +12 -0
  30. package/src/icons/react/index.tsx +6 -1
  31. package/src/loaders.tsx +10 -10
  32. package/src/loading-sausage.tsx +2 -2
  33. package/src/media-query-utils.ts +1 -1
  34. package/src/select/custom-select-partials/group-heading.tsx +2 -2
  35. package/src/select/custom-select-partials/menu.tsx +9 -1
  36. package/src/select/custom-select-partials/no-option-message.tsx +1 -1
  37. package/src/select/custom-select-partials/option.tsx +64 -7
  38. package/src/select/index.tsx +1 -1
  39. package/src/select/select-in-popover.tsx +10 -10
  40. package/src/select/styles.ts +12 -4
  41. package/src/toast/primitives.tsx +21 -8
  42. package/src/toast/toast-action.tsx +9 -1
  43. package/src/toast/toast-provider.tsx +15 -0
  44. package/src/toast/{toast-queue.tsx → toast-queue.ts} +21 -25
  45. package/src/toast/toast.tsx +35 -28
  46. package/src/toast/toaster.tsx +11 -48
  47. package/src/toast/utils/toastify-item-name.ts +6 -0
  48. package/src/tooltip.tsx +2 -2
  49. package/src/icons/ast/RicheditorMarkHighlight.ts +0 -8
  50. package/src/icons/react/RicheditorMarkHighlight.tsx +0 -12
@@ -1,6 +1,7 @@
1
+ import {useCallbackRef} from "@fibery/react/src/use-callback-ref";
1
2
  import {useControllableState} from "@fibery/react/src/use-controllable-state";
2
3
  import {css} from "@linaria/core";
3
- import {useState} from "react";
4
+ import {useEffect, useRef} from "react";
4
5
  import {space, themeVars} from "../design-system";
5
6
  import Spinner from "../icons/react/Spinner";
6
7
  import SuccessIcon from "../icons/react/Success";
@@ -15,21 +16,23 @@ export type ToastProps = {
15
16
  subTitle?: React.ReactNode;
16
17
  icon?: React.ReactNode;
17
18
  action?: ToastActionElement;
18
- autoClose?: boolean;
19
+ duration?: number;
20
+ dismissable?: boolean;
19
21
  open?: boolean;
20
22
  onOpenChange?: (open: boolean) => void;
21
23
 
22
24
  type?: ToastType;
23
25
 
24
- /** Is called on exit animation end */
25
- onRemove?: () => void;
26
+ /** It gets called after exit animation */
27
+ onHide?: () => void;
26
28
  };
27
29
 
28
30
  const defaultPropsPerType: Record<ToastType, Partial<ToastProps>> = {
29
31
  info: {},
30
32
  error: {
31
33
  icon: <WarningTriangle color={themeVars.textColor} />,
32
- autoClose: false,
34
+ duration: 10000,
35
+ dismissable: true,
33
36
  },
34
37
  loading: {
35
38
  icon: <Spinner color={themeVars.textColor} />,
@@ -40,17 +43,19 @@ const defaultPropsPerType: Record<ToastType, Partial<ToastProps>> = {
40
43
  };
41
44
 
42
45
  const rootCss = css`
46
+ box-sizing: border-box;
47
+ min-height: 44px;
43
48
  min-width: 320px;
44
49
  display: flex;
45
50
  align-items: center;
46
- gap: ${space.l}px;
51
+ gap: ${space.s12}px;
47
52
  `;
48
53
 
49
54
  const messageCss = css`
50
55
  display: flex;
51
56
  flex-grow: 1;
52
57
  flex-direction: column;
53
- gap: ${space.xs}px;
58
+ gap: ${space.s4}px;
54
59
  `;
55
60
 
56
61
  const iconCss = css`
@@ -65,10 +70,11 @@ export const Toast: React.FC<ToastProps> = (props) => {
65
70
  subTitle,
66
71
  icon,
67
72
  action,
68
- autoClose = true,
73
+ duration = 5000,
74
+ dismissable,
69
75
  open,
70
76
  onOpenChange,
71
- onRemove,
77
+ onHide,
72
78
  } = {
73
79
  ...defaultProps,
74
80
  ...props,
@@ -76,31 +82,32 @@ export const Toast: React.FC<ToastProps> = (props) => {
76
82
 
77
83
  const [isOpen, setOpen] = useControllableState({value: open, defaultValue: true, onChange: onOpenChange});
78
84
 
79
- const [noReducedMotion] = useState(() => matchMedia("(prefers-reduced-motion: no-preference)").matches);
85
+ const ref = useRef<HTMLLIElement>(null);
86
+ const onHideCb = useCallbackRef(onHide);
80
87
 
81
- const close = autoClose ? null : <ToastClose />;
88
+ useEffect(() => {
89
+ const toastEl = ref.current;
90
+ if (!isOpen) {
91
+ const emergencyTimeout = setTimeout(onHideCb, 400); // just in case if animationend doesn't fire for some reasons or toast got closed before render
82
92
 
83
- const onCloseProps = noReducedMotion
84
- ? {
85
- onOpenChange: setOpen,
93
+ toastEl?.addEventListener("animationend", onHideCb, {
86
94
  // https://github.com/radix-ui/primitives/issues/1020
87
- onAnimationEndCapture() {
88
- if (!isOpen) {
89
- onRemove?.();
90
- }
91
- },
92
- }
93
- : {
94
- onOpenChange(v: boolean) {
95
- setOpen(v);
96
- if (!v) {
97
- onRemove?.();
98
- }
99
- },
95
+ capture: true,
96
+ });
97
+
98
+ return () => {
99
+ toastEl?.removeEventListener("animationend", onHideCb, {capture: true});
100
+ clearTimeout(emergencyTimeout);
100
101
  };
102
+ }
103
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
104
+ return () => {};
105
+ }, [isOpen, onHideCb]);
106
+
107
+ const close = dismissable ? <ToastClose /> : null;
101
108
 
102
109
  return (
103
- <ToastRoot open={open} duration={autoClose ? 5000 : Infinity} className={rootCss} {...onCloseProps}>
110
+ <ToastRoot ref={ref} open={open} duration={duration} className={rootCss} onOpenChange={setOpen}>
104
111
  {icon ? <div className={iconCss}>{icon}</div> : null}
105
112
  <div className={messageCss}>
106
113
  <ToastTitle>{title}</ToastTitle>
@@ -1,13 +1,10 @@
1
- import {createContext} from "@fibery/react/src/create-context";
2
- import React, {useEffect, useSyncExternalStore} from "react";
1
+ import {useSyncExternalStore} from "react";
3
2
  import {createInlineTheme} from "../create-inline-theme";
4
3
  import {colors, getThemeColors} from "../design-system";
5
4
  import {ThemeProvider, useThemeMode} from "../theme-provider";
6
- import {ToastProvider, ToastViewport} from "./primitives";
5
+ import {ToastViewport} from "./primitives";
7
6
  import {Toast} from "./toast";
8
- import type {ToastQueue} from "./toast-queue";
9
- import {useCallbackRef} from "@fibery/react/src/use-callback-ref";
10
- import {reactNodeToString} from "@fibery/react/src/react-node-to-string";
7
+ import {useToast} from "./toast-provider";
11
8
 
12
9
  const ToastThemeProvider: React.FC<React.PropsWithChildren> = ({children}) => {
13
10
  const themeMode = useThemeMode();
@@ -21,52 +18,18 @@ const ToastThemeProvider: React.FC<React.PropsWithChildren> = ({children}) => {
21
18
  );
22
19
  };
23
20
 
24
- const [Provider, useCtx] = createContext<ToastQueue>("ToastQueue");
21
+ export const Toaster: React.FC = () => {
22
+ const toastQueue = useToast();
25
23
 
26
- type OnTrackToast = (args: {title: string; type: string}) => void;
27
- const TrackToast: React.FC<
28
- React.PropsWithChildren<{title: React.ReactNode; type: string; onTrackToast: OnTrackToast}>
29
- > = ({title, type, onTrackToast, children}) => {
30
- const onTrackCb = useCallbackRef(onTrackToast);
31
- useEffect(() => {
32
- onTrackCb({title: reactNodeToString(title), type});
33
- }, [onTrackCb, title, type]);
34
-
35
- return children as JSX.Element;
36
- };
37
-
38
- export const Toaster: React.FC<React.PropsWithChildren<{toastQueue: ToastQueue; onTrackToast: OnTrackToast}>> = ({
39
- toastQueue,
40
- children,
41
- onTrackToast,
42
- }) => {
43
24
  const toasts = useSyncExternalStore(toastQueue.subscribe, toastQueue.getActiveToasts);
44
25
 
45
26
  return (
46
- <Provider value={toastQueue}>
47
- <ToastProvider>
48
- {children}
49
-
50
- <ToastThemeProvider>
51
- {toasts.map(({id, open = true, ...toastProps}) => (
52
- <TrackToast key={id} title={toastProps.title} type={toastProps.type || "info"} onTrackToast={onTrackToast}>
53
- <Toast
54
- {...toastProps}
55
- open={open}
56
- onOpenChange={(v) => {
57
- if (!v) {
58
- toastQueue.close(id);
59
- }
60
- }}
61
- onRemove={() => toastQueue.remove(id)}
62
- />
63
- </TrackToast>
64
- ))}
27
+ <ToastThemeProvider>
28
+ {toasts.map(({id, open, type = "info", ...toastProps}) => (
29
+ <Toast key={`${id}-${type}`} type={type} {...toastProps} open={open} onHide={() => toastQueue.remove(id)} />
30
+ ))}
65
31
 
66
- <ToastViewport />
67
- </ToastThemeProvider>
68
- </ToastProvider>
69
- </Provider>
32
+ <ToastViewport />
33
+ </ToastThemeProvider>
70
34
  );
71
35
  };
72
- export const useToast = useCtx;
@@ -0,0 +1,6 @@
1
+ const charLimit = 60;
2
+
3
+ const trimDynamicToastText = (str: string) => (str.length > charLimit ? `${str.slice(0, 60)}...` : str);
4
+
5
+ export const toastifyItemName = ({prefix, name, postfix}: {prefix?: string; name?: string; postfix?: string}) =>
6
+ `${prefix ? `${prefix} ` : ""}"${name ? trimDynamicToastText(name) : "Untitled"}"${postfix ? ` ${postfix}` : ""}`;
package/src/tooltip.tsx CHANGED
@@ -27,7 +27,7 @@ const tooltipStyle = css`
27
27
  min-height: 30px;
28
28
  max-width: 300px;
29
29
  background-color: ${themeVars.tooltipBgColor};
30
- padding: ${space.s}px ${space.m}px;
30
+ padding: ${space.s6}px ${space.s8}px;
31
31
  border-radius: ${border.radius6}px;
32
32
  box-shadow: ${themeVars.actionMenuShadow};
33
33
 
@@ -132,7 +132,7 @@ export const Tooltip = forwardRef<HTMLButtonElement, TooltipProps>(
132
132
  </>
133
133
  ),
134
134
  side,
135
- sideOffset = space.xs,
135
+ sideOffset = space.s4,
136
136
  align,
137
137
  alignOffset,
138
138
  instant,
@@ -1,8 +0,0 @@
1
-
2
- // This icon file is generated automatically.
3
-
4
- import { IconDefinition } from '../types';
5
-
6
- const RicheditorMarkHighlight: IconDefinition = {"icon":{"type":"root","children":[{"type":"element","tagName":"svg","properties":{"viewBox":"0 0 20 20"},"children":[{"type":"element","tagName":"g","properties":{},"children":[{"type":"element","tagName":"path","properties":{"d":"m5.07 16.9.898-.625h2.418c.643 0 1.197-.177 1.66-.607.15-.14.135-.377-.012-.522L5.23 10.438c-.156-.153-.408-.154-.535.023-.34.476-.509 1.087-.509 1.698v2.37l-.89.873c-.382.39-.17.154-.597.624 1.517.595 2.37.874 2.37.874ZM10.653 14.177c.255.25.51.25.764 0l5.997-7.786a1.474 1.474 0 0 0 0-1.746l-1.909-1.87a1.247 1.247 0 0 0-1.781 0l-7.61 6.313c-.255.249-.255.498 0 .748l4.54 4.341Z"},"children":[]}]}],"metadata":""}]},"name":"richeditor-mark-highlight"};
7
-
8
- export default RicheditorMarkHighlight;
@@ -1,12 +0,0 @@
1
- // This icon file is generated automatically.
2
-
3
- import RicheditorMarkHighlightSvg from '../ast/RicheditorMarkHighlight';
4
- import { Icon } from '../Icon';
5
- import { IconBaseProps } from '../types';
6
-
7
- const RicheditorMarkHighlight = (
8
- props: IconBaseProps,
9
- ): JSX.Element => <Icon {...props} icon={RicheditorMarkHighlightSvg} />;
10
-
11
- RicheditorMarkHighlight.displayName = 'RicheditorMarkHighlight';
12
- export default RicheditorMarkHighlight;