@fibery/ui-kit 1.9.2 → 1.10.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fibery/ui-kit",
3
- "version": "1.9.2",
3
+ "version": "1.10.1",
4
4
  "main": "index.ts",
5
5
  "private": false,
6
6
  "files": [
@@ -23,9 +23,7 @@
23
23
  "src/tooltip.tsx",
24
24
  "src/BackButton.tsx",
25
25
  "src/Button",
26
- "src/emoji-mart.tsx",
27
- "src/emoji-picker.tsx",
28
- "src/app-icon-picker.tsx"
26
+ "src/emoji-mart/*.ts*"
29
27
  ],
30
28
  "license": "UNLICENSED",
31
29
  "dependencies": {
@@ -53,7 +51,7 @@
53
51
  "rc-input-number": "7.3.11",
54
52
  "rc-menu": "9.8.1",
55
53
  "rc-progress": "3.4.1",
56
- "react-color": "2.13.8",
54
+ "react-color": "2.19.3",
57
55
  "react-day-picker": "8.1.4",
58
56
  "react-popper": "2.3.0",
59
57
  "react-select": "5.3.2",
@@ -61,8 +59,8 @@
61
59
  "react-windowed-select": "5.0.0",
62
60
  "screenfull": "6.0.1",
63
61
  "ua-parser-js": "0.7.24",
64
- "@fibery/helpers": "1.0.4",
65
- "@fibery/react": "1.0.2"
62
+ "@fibery/react": "1.0.2",
63
+ "@fibery/helpers": "1.0.4"
66
64
  },
67
65
  "peerDependencies": {
68
66
  "react": "^18.2.0",
@@ -95,8 +93,8 @@
95
93
  "svgo": "2.8.0",
96
94
  "typescript": "5.0.3",
97
95
  "unist-util-reduce": "0.2.2",
98
- "@fibery/eslint-config": "8.3.0",
99
- "@fibery/babel-preset": "7.2.0"
96
+ "@fibery/babel-preset": "7.2.0",
97
+ "@fibery/eslint-config": "8.3.0"
100
98
  },
101
99
  "jest": {
102
100
  "testEnvironment": "jsdom",
@@ -202,6 +202,7 @@ const lightColors = {
202
202
  cellBackgroundColor: slate.slate2,
203
203
  cellBackgroundHoverColor: getOpacities(slate.slate6).opacity30,
204
204
  cellBorderColor: getOpacities(slate.slate8).opacity50,
205
+ cellPinnedBorderColor: getOpacities(slate.slate8).opacity70,
205
206
  tableRowWarningColor: getOpacities(yellow.yellow6).opacity60,
206
207
  errorBgColor: getOpacities(red.red9).opacity20,
207
208
  errorTextColor: red.red11,
@@ -254,6 +255,7 @@ const lightColors = {
254
255
  progressFillBg: slate.slate11,
255
256
  progressFillText: whiteA.whiteA0,
256
257
  searchFiltersBg: slate.slate1,
258
+ colorPickerSwatchBorder: blackA.blackA7,
257
259
  } as const;
258
260
 
259
261
  const darkMenu = {
@@ -364,6 +366,7 @@ const darkColors = {
364
366
  cellBackgroundColor: slateDark.slate2,
365
367
  cellBackgroundHoverColor: getOpacities(slateDark.slate6).opacity30,
366
368
  cellBorderColor: getOpacities(slateDark.slate9).opacity50,
369
+ cellPinnedBorderColor: getOpacities(slateDark.slate9).opacity70,
367
370
  tableRowWarningColor: getOpacities(yellowDark.yellow9).opacity40,
368
371
  errorBgColor: getOpacities(redDark.red9).opacity60,
369
372
  errorTextColor: red.red7,
@@ -414,6 +417,7 @@ const darkColors = {
414
417
  progressFillBg: slate.slate11,
415
418
  progressFillText: whiteA.whiteA0,
416
419
  searchFiltersBg: slateDark.slate2,
420
+ colorPickerSwatchBorder: blackA.blackA7,
417
421
  ...darkMenu,
418
422
  } as const;
419
423
 
@@ -554,6 +558,9 @@ export const getEnumBackgroundColor = _.memoize(
554
558
  );
555
559
 
556
560
  export const cardTypeColors = [
561
+ "#4A4A4A",
562
+ "#6A849B",
563
+ "#BEC5CC",
557
564
  "#D40915",
558
565
  "#E72065",
559
566
  "#9C2BAF",
@@ -568,8 +575,6 @@ export const cardTypeColors = [
568
575
  "#FBA32F",
569
576
  "#FC551F",
570
577
  "#B04E31",
571
- "#6A849B",
572
- "#4A4A4A",
573
578
  ] as const;
574
579
 
575
580
  export const pastelColors = cardTypeColors.map((color) => makeChromaColor(color).luminance(0.8).hex());
@@ -579,13 +584,11 @@ export const colors = {
579
584
  ...getTypeColors(brandColors.green, "light"),
580
585
  brandColors,
581
586
  stateColors,
582
- textColor: "#2A3844",
583
- inversedTextColor: "#FFFFFF",
584
- disabledInversedTextColor: lights.opacity25,
585
- unitBg: "rgba(220, 224, 228, 0.33)",
586
587
  transparent,
587
588
  shades,
588
589
  lights,
590
+ inversedTextColor: "#FFFFFF",
591
+ disabledInversedTextColor: lights.opacity25,
589
592
  } as const;
590
593
 
591
594
  export const space = {
@@ -1,9 +1,12 @@
1
1
  import {forwardRef, useMemo} from "react";
2
2
  import {EmojiMartWrapper, NimblePicker, PickerProps} from "./emoji-mart";
3
- import {useThemeMode} from "./ThemeProvider";
4
- import {alignTheme} from "./theme-settings";
5
- import appIcons from "./appIcons.json";
6
- import {getThemedUrl} from "./AppIconWithFallback";
3
+ import {useThemeMode} from "../ThemeProvider";
4
+ import {alignTheme} from "../theme-settings";
5
+ import appIcons from "../appIcons.json";
6
+ import {getThemedUrl} from "../AppIconWithFallback";
7
+ import {$TSFixMe} from "../tsfixme";
8
+ import {cardTypeColors} from "../designSystem";
9
+ import {ColorPicker} from "../ColorPicker";
7
10
 
8
11
  const EMPTY_DATA = {
9
12
  aliases: {},
@@ -12,10 +15,16 @@ const EMPTY_DATA = {
12
15
  compressed: false,
13
16
  };
14
17
 
15
- export type AppIconPickerProps = {borderless?: boolean} & PickerProps;
18
+ export type AppIconPickerProps = {
19
+ borderless?: boolean;
20
+ color?: string;
21
+ onColorSelect?: (c: $TSFixMe) => void;
22
+ } & PickerProps;
23
+
24
+ const i18n = {search: "Search icon..."};
16
25
 
17
26
  export const AppIconPicker = forwardRef<HTMLDivElement, AppIconPickerProps>(function AppIconPicker(
18
- {borderless = true, ...pickerProps},
27
+ {borderless = true, onColorSelect, color, ...pickerProps},
19
28
  ref
20
29
  ) {
21
30
  const themeMode = useThemeMode();
@@ -34,17 +43,20 @@ export const AppIconPicker = forwardRef<HTMLDivElement, AppIconPickerProps>(func
34
43
  );
35
44
 
36
45
  return (
37
- <EmojiMartWrapper ref={ref} borderless={borderless} hideCategories>
46
+ <EmojiMartWrapper ref={ref} color={color} borderless={borderless} hideCategories>
38
47
  <NimblePicker
39
48
  data={EMPTY_DATA}
40
49
  theme={alignedTheme}
41
50
  showSkinTones={false}
42
51
  showPreview={false}
52
+ emojiTooltip
43
53
  title=""
44
54
  custom={customIcons}
45
- emojiSize={22}
55
+ emojiSize={20}
56
+ i18n={i18n}
46
57
  {...pickerProps}
47
58
  />
59
+ {onColorSelect ? <ColorPicker colors={cardTypeColors} color={color} onChangeComplete={onColorSelect} /> : null}
48
60
  </EmojiMartWrapper>
49
61
  );
50
62
  });
@@ -0,0 +1,226 @@
1
+ import {CSSProperties, css, cx} from "@linaria/core";
2
+ import {Emoji, EmojiProps} from "emoji-mart";
3
+ import "emoji-mart/css/emoji-mart.css";
4
+ import {forwardRef} from "react";
5
+ import {useTheme} from "../ThemeProvider";
6
+ import {a11yColor} from "../a11y-color";
7
+ import {border, fontFamily, getOpacities, space, textStyles, themeVars} from "../designSystem";
8
+
9
+ export {NimblePicker, Picker, emojiIndex} from "emoji-mart";
10
+ export type {BaseEmoji, EmojiSkin, PickerProps} from "emoji-mart";
11
+
12
+ export const backgroundImageFn = () => "https://assets-temp.fibery.io/images/emoji-datasource-apple-5_0_1-64.png";
13
+
14
+ const emojiMartCss = css`
15
+ padding: 0 ${space.l}px;
16
+ position: relative;
17
+
18
+ .emoji-mart {
19
+ font-family: ${fontFamily};
20
+ background-color: ${themeVars.actionMenuBg};
21
+ margin-top: ${space.xxs}px;
22
+ display: block;
23
+ width: 288px !important;
24
+
25
+ + * {
26
+ border-top: 1px solid ${themeVars.separatorColor};
27
+ }
28
+ }
29
+
30
+ .emoji-mart-bar {
31
+ border-bottom: 1px solid ${themeVars.separatorColor};
32
+
33
+ &:last-child {
34
+ border: 0;
35
+ }
36
+ }
37
+
38
+ .emoji-mart-search {
39
+ padding-bottom: ${space.s}px;
40
+ padding-left: 0;
41
+ padding-right: 0;
42
+
43
+ & input {
44
+ ${textStyles.regular}
45
+ background-color: ${themeVars.inputBgColor};
46
+ color: ${themeVars.textColor};
47
+ box-shadow: ${themeVars.inputBorderColor};
48
+ height: 32px;
49
+ border: 0;
50
+ }
51
+
52
+ & .emoji-mart-search-icon {
53
+ top: 5px;
54
+ right: 4px;
55
+ }
56
+ }
57
+
58
+ .emoji-mart-scroll {
59
+ padding-left: 0;
60
+ padding-right: 0;
61
+ }
62
+
63
+ .emoji-anchor-bar {
64
+ height: ${space.xxs}px;
65
+ }
66
+
67
+ .emoji-mart-category-label {
68
+ & span {
69
+ ${textStyles.heading6}
70
+ background-color: ${themeVars.actionMenuBg};
71
+ color: ${themeVars.textColor};
72
+ color: ${themeVars.accentTextColor};
73
+ padding-top: ${space.l}px;
74
+ }
75
+ }
76
+
77
+ .emoji-mart-category .emoji-mart-emoji span,
78
+ .emoji-mart-anchor {
79
+ cursor: pointer !important;
80
+ }
81
+
82
+ .emoji-mart-category .emoji-mart-emoji:hover::before {
83
+ background-color: var(--emoji-bg-color) !important;
84
+ border-radius: ${border.radius8}px !important;
85
+ }
86
+ .emoji-mart-dark .emoji-mart-category-label span {
87
+ background-color: ${themeVars.actionMenuBg};
88
+ }
89
+
90
+ .emoji-mart-skin-swatch {
91
+ cursor: pointer;
92
+ }
93
+
94
+ .emoji-mart-preview {
95
+ height: 0px;
96
+ position: unset;
97
+ }
98
+
99
+ .emoji-mart-emoji {
100
+ /* pathetic attemts to make it a bit faster without forking */
101
+ content-visibility: auto;
102
+ contain-intrinsic-size: 20px;
103
+ cursor: pointer;
104
+ }
105
+ .emoji-mart-category-list,
106
+ .emoji-mart-category-list li {
107
+ /* hack to maintain correct size of hidden emojis becuase of content-visibility */
108
+ line-height: 0;
109
+ }
110
+ .emoji-mart-preview-skins {
111
+ top: 16px;
112
+ right: 12px !important;
113
+ z-index: 2;
114
+ background-color: ${themeVars.actionMenuBg};
115
+
116
+ & .emoji-mart-skin-swatches {
117
+ background-color: ${themeVars.actionMenuBg};
118
+
119
+ &.opened {
120
+ & .emoji-mart-skin-swatch {
121
+ width: 32px !important;
122
+ }
123
+ }
124
+
125
+ & .emoji-mart-skin-swatch {
126
+ height: 32px !important;
127
+
128
+ &.selected {
129
+ width: 32px !important;
130
+ padding: 0;
131
+ }
132
+
133
+ & .emoji-mart-emoji-native span {
134
+ width: 20px;
135
+ font-size: 20px !important;
136
+ height: 20px;
137
+ display: inline-block;
138
+ }
139
+
140
+ &:hover {
141
+ background-color: ${themeVars.badgeBgColor} !important;
142
+ border-radius: ${border.radius8}px !important;
143
+ }
144
+ }
145
+ & .emoji-mart-skin-text {
146
+ height: auto;
147
+ padding: 0;
148
+ background-color: ${themeVars.actionMenuBg};
149
+ color: ${themeVars.accentTextColor};
150
+ border-radius: 0;
151
+
152
+ &.opened {
153
+ width: 98px;
154
+ padding-left: 8px;
155
+ }
156
+ }
157
+ }
158
+ }
159
+ `;
160
+
161
+ const borderlessEmojiMartCss = css`
162
+ .emoji-mart {
163
+ border-radius: 0;
164
+ border: none;
165
+ }
166
+ `;
167
+ const hideCategoriesEmojiMartCss = css`
168
+ .emoji-mart-bar:first-child {
169
+ display: none;
170
+ }
171
+ `;
172
+
173
+ const emojiMartWithShortSearchCss = css`
174
+ .emoji-mart-search {
175
+ width: 250px;
176
+ }
177
+ `;
178
+
179
+ type EmojiMartWrapperProps = React.PropsWithChildren<{
180
+ borderless?: boolean;
181
+ hideCategories?: boolean;
182
+ shortSearch?: boolean;
183
+ color?: string;
184
+ }>;
185
+
186
+ export const EmojiMartWrapper = forwardRef<HTMLDivElement, EmojiMartWrapperProps>(function EmojiMartWrapper(
187
+ {borderless, hideCategories, color, shortSearch, children},
188
+ ref
189
+ ) {
190
+ const theme = useTheme();
191
+
192
+ const bgColor = color ? a11yColor(getOpacities(color).opacity20, theme.menuBg, 1.3) : theme.badgeBgColor;
193
+
194
+ return (
195
+ <div
196
+ style={{"--emoji-bg-color": bgColor} as CSSProperties}
197
+ ref={ref}
198
+ className={cx(
199
+ emojiMartCss,
200
+ borderless && borderlessEmojiMartCss,
201
+ hideCategories && hideCategoriesEmojiMartCss,
202
+ shortSearch && emojiMartWithShortSearchCss
203
+ )}
204
+ >
205
+ {children}
206
+ </div>
207
+ );
208
+ });
209
+
210
+ const emojiWrapperCss = css`
211
+ & span.emoji-mart-emoji-native {
212
+ line-height: 1;
213
+ vertical-align: middle;
214
+ & span {
215
+ vertical-align: middle;
216
+ }
217
+ }
218
+ `;
219
+
220
+ export const EmojiMartEmoji: React.FC<EmojiProps> = (props) => {
221
+ return (
222
+ <span className={emojiWrapperCss}>
223
+ <Emoji backgroundImageFn={backgroundImageFn} {...props} />
224
+ </span>
225
+ );
226
+ };
@@ -0,0 +1,45 @@
1
+ import {forwardRef} from "react";
2
+ import {useTheme, useThemeMode} from "../ThemeProvider";
3
+ import {EmojiMartWrapper, Picker, PickerProps, backgroundImageFn} from "./emoji-mart";
4
+ import {alignTheme} from "../theme-settings";
5
+ import {$TSFixMe} from "../tsfixme";
6
+ import {ColorPicker} from "../ColorPicker";
7
+ import {cardTypeColors} from "../designSystem";
8
+
9
+ export type EmojiPickerProps = {
10
+ borderless?: boolean;
11
+ color?: string;
12
+ colors?: string[];
13
+ onColorSelect?: (c: $TSFixMe) => void;
14
+ } & PickerProps;
15
+
16
+ const i18n = {search: "Search emoji..."};
17
+
18
+ export const EmojiPicker = forwardRef<HTMLDivElement, EmojiPickerProps>(function EmojiPickerComponent(
19
+ {borderless = true, color, colors = cardTypeColors, onColorSelect, showSkinTones = true, ...pickerProps},
20
+ ref
21
+ ) {
22
+ const themeMode = useThemeMode();
23
+ const theme = useTheme();
24
+
25
+ return (
26
+ <EmojiMartWrapper ref={ref} color={color} borderless={borderless} hideCategories shortSearch={showSkinTones}>
27
+ <Picker
28
+ theme={alignTheme(themeMode)}
29
+ backgroundImageFn={backgroundImageFn}
30
+ native
31
+ title={""}
32
+ showPreview={false}
33
+ showSkinTones={showSkinTones}
34
+ skinEmoji="hand"
35
+ color={theme.primary}
36
+ emoji=""
37
+ emojiSize={20}
38
+ emojiTooltip
39
+ i18n={i18n}
40
+ {...pickerProps}
41
+ />
42
+ {onColorSelect ? <ColorPicker colors={colors} color={color} onChangeComplete={onColorSelect} /> : null}
43
+ </EmojiMartWrapper>
44
+ );
45
+ });
@@ -0,0 +1,101 @@
1
+ // copied from https://github.com/nolanlawson/emoji-picker-element/
2
+ const versionsAndTestEmoji = {
3
+ "🫠": 14,
4
+ "🥲": 13.1, // smiling face with tear, technically from v13 but see note above
5
+ "🥻": 12.1, // sari, technically from v12 but see note above
6
+ "🥰": 11,
7
+ "🤩": 5,
8
+ "👱‍♀️": 4,
9
+ "🤣": 3,
10
+ "👁️‍🗨️": 2,
11
+ "😀": 1,
12
+ "😐️": 0.7,
13
+ "😃": 0.6,
14
+ };
15
+ const FONT_FAMILY =
16
+ '"Twemoji Mozilla","Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol",' +
17
+ '"Noto Color Emoji","EmojiOne Color","Android Emoji",sans-serif';
18
+ const rIC = typeof requestIdleCallback === "function" ? requestIdleCallback : setTimeout;
19
+
20
+ // only used in jest tests
21
+ const simulateCanvasError = false;
22
+ const simulateOldBrowser = false;
23
+
24
+ const getTextFeature = (text: string, color: string) => {
25
+ const canvas = document.createElement("canvas");
26
+ canvas.width = canvas.height = 1;
27
+
28
+ const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
29
+ ctx.textBaseline = "top";
30
+ ctx.font = `100px ${FONT_FAMILY}`;
31
+ ctx.fillStyle = color;
32
+ ctx.scale(0.01, 0.01);
33
+ ctx.fillText(text, 0, 0);
34
+
35
+ return ctx.getImageData(0, 0, 1, 1).data;
36
+ };
37
+
38
+ const compareFeatures = (feature1: Uint8ClampedArray, feature2: Uint8ClampedArray) => {
39
+ const feature1Str = [...feature1].join(",");
40
+ const feature2Str = [...feature2].join(",");
41
+ // This is RGBA, so for 0,0,0, we are checking that the first RGB is not all zeroes.
42
+ // Most of the time when unsupported this is 0,0,0,0, but on Chrome on Mac it is
43
+ // 0,0,0,61 - there is a transparency here.
44
+ return feature1Str === feature2Str && !feature1Str.startsWith("0,0,0,");
45
+ };
46
+
47
+ function testColorEmojiSupported(text: string) {
48
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
49
+ // @ts-ignore TODO: fix type error
50
+ if (process.env.NODE_ENV === "test") {
51
+ if (simulateCanvasError) {
52
+ throw new Error("canvas error");
53
+ } else if (simulateOldBrowser) {
54
+ return Object.entries(versionsAndTestEmoji)
55
+ .filter(([, version]) => version < 12)
56
+ .map(([emoji]) => emoji)
57
+ .includes(text);
58
+ }
59
+ return true; // avoid using canvas in jest
60
+ }
61
+ // Render white and black and then compare them to each other and ensure they're the same
62
+ // color, and neither one is black. This shows that the emoji was rendered in color.
63
+ const feature1 = getTextFeature(text, "#000");
64
+ const feature2 = getTextFeature(text, "#fff");
65
+ return feature1 && feature2 && compareFeatures(feature1, feature2);
66
+ }
67
+
68
+ function determineEmojiSupportLevel() {
69
+ performance.mark("determineEmojiSupportLevel");
70
+ const entries = Object.entries(versionsAndTestEmoji);
71
+ try {
72
+ // start with latest emoji and work backwards
73
+ for (const [emoji, version] of entries) {
74
+ if (testColorEmojiSupported(emoji)) {
75
+ return version;
76
+ }
77
+ }
78
+ } catch (e) {
79
+ // canvas error
80
+ // eslint-disable-next-line no-console
81
+ console.log("Ignoring canvas error", e);
82
+ } finally {
83
+ performance.measure("determineEmojiSupportLevel", "determineEmojiSupportLevel");
84
+ }
85
+ // In case of an error, be generous and just assume all emoji are supported (e.g. for canvas errors
86
+ // due to anti-fingerprinting add-ons). Better to show some gray boxes than nothing at all.
87
+ return entries[0][1]; // first one in the list is the most recent version
88
+ }
89
+
90
+ // Check which emojis we know for sure aren't supported, based on Unicode version level
91
+ let promise: Promise<number>;
92
+ export const detectEmojiSupportLevel = () => {
93
+ if (!promise) {
94
+ promise = new Promise((resolve) => {
95
+ rIC(
96
+ () => resolve(determineEmojiSupportLevel()) // delay so ideally this can run while IDB is first populating
97
+ );
98
+ });
99
+ }
100
+ return promise;
101
+ };
@@ -0,0 +1,24 @@
1
+ import {lazy, Suspense} from "react";
2
+ import {detectEmojiSupportLevel} from "./emoji-support";
3
+
4
+ const LazyEmojiComponent = lazy(async () => {
5
+ const {EmojiMartEmoji} = await import("./emoji-mart");
6
+ const level = await detectEmojiSupportLevel();
7
+
8
+ function Emoji(props: React.ComponentPropsWithoutRef<typeof EmojiMartEmoji>) {
9
+ return <EmojiMartEmoji {...props} native={level >= 5} />;
10
+ }
11
+ return {
12
+ default: Emoji,
13
+ };
14
+ });
15
+
16
+ export const Emoji: React.FC<React.ComponentPropsWithoutRef<typeof LazyEmojiComponent>> = function EmojiOrLoader(
17
+ props
18
+ ) {
19
+ return (
20
+ <Suspense fallback={<div style={{width: props.size, height: props.size}} />}>
21
+ <LazyEmojiComponent {...props} />
22
+ </Suspense>
23
+ );
24
+ };
@@ -0,0 +1,69 @@
1
+ import {css} from "@linaria/core";
2
+ import {Button} from "../Button";
3
+ import {AntTabs} from "../antd";
4
+ import {space, textStyles} from "../designSystem";
5
+ import {$TSFixMe} from "../tsfixme";
6
+ import {AppIconPicker, AppIconPickerProps} from "./app-icon-picker";
7
+ import {EmojiPicker, EmojiPickerProps} from "./emoji-picker";
8
+
9
+ const TabHeader: React.FC<React.PropsWithChildren> = ({children}) => (
10
+ <div
11
+ className={css`
12
+ ${textStyles.heading5}
13
+ `}
14
+ >
15
+ {children}
16
+ </div>
17
+ );
18
+
19
+ type IconEmojiPickerProps = React.PropsWithChildren<{
20
+ onIconSelect: NonNullable<AppIconPickerProps["onSelect"]>;
21
+ onEmojiSelect: NonNullable<EmojiPickerProps["onSelect"]>;
22
+ onColorSelect?: (c: $TSFixMe) => void;
23
+ onReset?: () => void;
24
+ resetLabel?: string;
25
+ defaultTab?: "icons" | "emojis";
26
+ color?: string;
27
+ }>;
28
+ export const IconEmojiPicker: React.FC<IconEmojiPickerProps> = ({
29
+ onIconSelect,
30
+ onEmojiSelect,
31
+ onColorSelect,
32
+ defaultTab,
33
+ onReset,
34
+ resetLabel = "Reset",
35
+ color,
36
+ }) => {
37
+ return (
38
+ <AntTabs
39
+ animated={false}
40
+ destroyInactiveTabPane
41
+ defaultActiveKey={defaultTab}
42
+ items={[
43
+ {
44
+ key: "icons",
45
+ label: <TabHeader>Icons</TabHeader>,
46
+ children: <AppIconPicker color={color} onColorSelect={onColorSelect} onSelect={onIconSelect} />,
47
+ },
48
+ {
49
+ key: "emojis",
50
+ label: <TabHeader>Emojis</TabHeader>,
51
+ children: <EmojiPicker color={color} onColorSelect={onColorSelect} onSelect={onEmojiSelect} />,
52
+ },
53
+ ]}
54
+ tabBarExtraContent={
55
+ onReset ? (
56
+ <div
57
+ className={css`
58
+ padding-right: ${space.l}px;
59
+ `}
60
+ >
61
+ <Button size={":button-size/small"} onClick={onReset}>
62
+ {resetLabel}
63
+ </Button>
64
+ </div>
65
+ ) : null
66
+ }
67
+ />
68
+ );
69
+ };
@@ -1,122 +0,0 @@
1
- import "emoji-mart/css/emoji-mart.css";
2
- import {forwardRef} from "react";
3
- import {border, space, textStyles, themeVars} from "./designSystem";
4
- import {cx, css} from "@linaria/core";
5
- import {Emoji as EmojiMartEmoji, EmojiProps} from "emoji-mart";
6
-
7
- export {detectEmojiSupportLevel} from "./emojiSupport";
8
- export {emojiIndex, Picker, NimblePicker} from "emoji-mart";
9
- export type {BaseEmoji, PickerProps, EmojiSkin} from "emoji-mart";
10
-
11
- export const backgroundImageFn = () => "https://assets-temp.fibery.io/images/emoji-datasource-apple-5_0_1-64.png";
12
-
13
- const emojiMartCss = css`
14
- .emoji-mart {
15
- background-color: ${themeVars.actionMenuBg};
16
- margin-top: ${space.xxs}px;
17
- display: block;
18
- }
19
-
20
- .emoji-mart-bar {
21
- border-bottom: 1px solid ${themeVars.separatorColor};
22
-
23
- &:last-child {
24
- border-top: 1px solid ${themeVars.separatorColor};
25
- }
26
- }
27
-
28
- .emoji-mart-search {
29
- padding-bottom: ${space.s}px;
30
-
31
- & input {
32
- ${textStyles.regular}
33
- background-color: ${themeVars.inputBgColor};
34
- color: ${themeVars.textColor};
35
- box-shadow: ${themeVars.inputBorderColor};
36
- height: 34px;
37
- border: 0;
38
- }
39
- }
40
-
41
- .emoji-anchor-bar {
42
- height: ${space.xxs}px;
43
- }
44
-
45
- .emoji-mart-category-label {
46
- & span {
47
- ${textStyles.heading6}
48
- background-color: ${themeVars.actionMenuBg};
49
- color: ${themeVars.textColor};
50
- color: ${themeVars.accentTextColor};
51
- padding-top: ${space.l}px;
52
- }
53
- }
54
-
55
- .emoji-mart-category .emoji-mart-emoji span,
56
- .emoji-mart-anchor {
57
- cursor: pointer !important;
58
- }
59
-
60
- .emoji-mart-category .emoji-mart-emoji:hover::before {
61
- background-color: ${themeVars.badgeBgColor} !important;
62
- border-radius: ${border.radius8}px !important;
63
- }
64
- .emoji-mart-dark .emoji-mart-category-label span {
65
- background-color: ${themeVars.actionMenuBg};
66
- }
67
-
68
- .emoji-mart-skin-swatch {
69
- cursor: pointer;
70
- }
71
-
72
- .emoji-mart-preview {
73
- height: 50px;
74
- }
75
-
76
- .emoji-mart-preview-skins {
77
- right: 15px;
78
- }
79
-
80
- .emoji-mart-emoji {
81
- /* pathetic attemts to make it a bit faster without forking */
82
- content-visibility: auto;
83
- contain-intrinsic-size: 22px;
84
- }
85
- .emoji-mart-category-list,
86
- .emoji-mart-category-list li {
87
- /* hack to maintain correct size of hidden emojis becuase of content-visibility */
88
- line-height: 0;
89
- }
90
- `;
91
-
92
- const borderlessEmojiMartCss = css`
93
- .emoji-mart {
94
- border-radius: 0;
95
- border: none;
96
- }
97
- `;
98
- const hideCategoriesEmojiMartCss = css`
99
- .emoji-mart-bar:first-child {
100
- display: none;
101
- }
102
- `;
103
-
104
- type EmojiMartWrapperProps = React.PropsWithChildren<{borderless?: boolean; hideCategories?: boolean}>;
105
-
106
- export const EmojiMartWrapper = forwardRef<HTMLDivElement, EmojiMartWrapperProps>(function EmojiMartWrapper(
107
- {borderless, hideCategories, children},
108
- ref
109
- ) {
110
- return (
111
- <div
112
- ref={ref}
113
- className={cx(emojiMartCss, borderless && borderlessEmojiMartCss, hideCategories && hideCategoriesEmojiMartCss)}
114
- >
115
- {children}
116
- </div>
117
- );
118
- });
119
-
120
- export const Emoji: React.FC<EmojiProps> = (props) => {
121
- return <EmojiMartEmoji backgroundImageFn={backgroundImageFn} {...props} />;
122
- };
@@ -1,32 +0,0 @@
1
- import {forwardRef} from "react";
2
- import {useTheme, useThemeMode} from "./ThemeProvider";
3
- import {EmojiMartWrapper, Picker, PickerProps, backgroundImageFn} from "./emoji-mart";
4
- import {alignTheme} from "./theme-settings";
5
-
6
- type EmojiPickerProps = {
7
- borderless?: boolean;
8
- } & PickerProps;
9
-
10
- export const EmojiPicker = forwardRef<HTMLDivElement, EmojiPickerProps>(function EmojiPickerComponent(
11
- {borderless = true, ...pickerProps},
12
- ref
13
- ) {
14
- const themeMode = useThemeMode();
15
- const theme = useTheme();
16
-
17
- return (
18
- <EmojiMartWrapper ref={ref} borderless={borderless}>
19
- <Picker
20
- theme={alignTheme(themeMode)}
21
- backgroundImageFn={backgroundImageFn}
22
- native
23
- title={""}
24
- showPreview={false}
25
- color={theme.primary}
26
- emoji=""
27
- emojiSize={22}
28
- {...pickerProps}
29
- />
30
- </EmojiMartWrapper>
31
- );
32
- });