@fibery/ui-kit 1.22.0 → 1.24.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.
@@ -28,17 +28,25 @@ export const listRowSurfaceStylesBase = css`
28
28
  color: ${themeVars.textColor};
29
29
  border-radius: ${border.radius6}px;
30
30
  transition: background-color;
31
+
32
+ &:focus {
33
+ outline: none;
34
+ }
35
+
31
36
  ${NATURAL_HOVER},
32
37
  &.hover {
33
38
  cursor: pointer;
34
39
  }
40
+
35
41
  &.done {
36
42
  cursor: not-allowed;
37
43
  color: ${themeVars.colorTextListItemGeneralDisabled};
44
+
38
45
  > * {
39
46
  opacity: ${themeVars.opacityListItemGeneralDisabled};
40
47
  }
41
48
  }
49
+
42
50
  &.selected {
43
51
  cursor: default;
44
52
  }
@@ -103,6 +103,11 @@ function countOptions<Option, Group extends GroupBase<Option>>(categorizedOption
103
103
  }, 0);
104
104
  }
105
105
 
106
+ /**
107
+ * Draws a select input.
108
+ * Please use formatOptionLabel instead of Option component override. Select has smart optimisations for large lists
109
+ * those would be lost and your select slow if options are too numerous
110
+ */
106
111
  export const Select = forwardRef(function Select<
107
112
  Option = unknown,
108
113
  IsMulti extends boolean = boolean,
@@ -1,177 +0,0 @@
1
- import {Category, EmojiItem} from "@fibery/emoji-data";
2
- import {css} from "@linaria/core";
3
- import {memo} from "react";
4
- import {useInView} from "react-intersection-observer";
5
- import {IconButton} from "../../button/icon-button";
6
- import {space, textStyles, themeVars} from "../../design-system";
7
- import {Settings} from "../../icons/react";
8
- import {useEmojiDataStoreSelector} from "../stores/emoji-data-store";
9
- import {useEmojiPickerContentSettings} from "./content";
10
- import {Emoji} from "./emoji";
11
- import {emojiPadding} from "./layout";
12
- import {useEmojiPickerCtx, useEmojiPickerI18N} from "./root";
13
- import {useEmojiSkin} from "./skin-provider";
14
-
15
- const categoryCss = css``;
16
-
17
- const categoryLabelCss = css`
18
- ${textStyles.heading6}
19
- color: ${themeVars.accentTextColor};
20
- background-color: ${themeVars.actionMenuBg};
21
- padding: ${space.s12}px ${space.s6}px ${space.s4}px ${space.s6}px;
22
- position: sticky;
23
- top: 0;
24
-
25
- display: flex;
26
- align-items: center;
27
- gap: ${space.s4}px;
28
-
29
- z-index: 1;
30
- `;
31
-
32
- const categoryListCss = css`
33
- display: flex;
34
- flex-wrap: wrap;
35
- margin: 0;
36
- padding: 0;
37
-
38
- & li {
39
- list-style: none;
40
- margin: 0;
41
- padding: 0;
42
-
43
- line-height: 1;
44
- }
45
- `;
46
-
47
- const notFoundCss = css`
48
- padding-top: 70px;
49
- text-align: center;
50
-
51
- ${textStyles.regular};
52
- color: ${themeVars.accentTextColor};
53
- `;
54
-
55
- const NotFound = () => {
56
- const i18n = useEmojiPickerI18N();
57
-
58
- return (
59
- <div className={notFoundCss}>
60
- <Emoji emoji="sleuth_or_spy" size={38} />
61
- <div>{i18n.notfound}</div>
62
- </div>
63
- );
64
- };
65
-
66
- type CategoryItemProps = {
67
- id: string;
68
- /** Custom renderer for emoji items */
69
- renderEmoji?: (args: {emoji: EmojiItem}) => React.ReactNode;
70
- };
71
-
72
- const CategoryItem: React.FC<CategoryItemProps> = ({id, renderEmoji}) => {
73
- const skin = useEmojiSkin();
74
- const emojiPickerCtx = useEmojiPickerCtx();
75
- const emojiContentSettings = useEmojiPickerContentSettings();
76
-
77
- const emoji = useEmojiDataStoreSelector((store) => store.get(id, {skin}));
78
-
79
- if (!emoji) {
80
- return null;
81
- }
82
-
83
- // TODO: title should be shown in preview in footer
84
- const title = emoji.shortNames ? emoji.shortNames[0] : undefined;
85
-
86
- return (
87
- <IconButton
88
- size="big"
89
- onClick={() => emojiPickerCtx.onEmojiSelect(emoji)}
90
- className={css`
91
- &:hover:not(:disabled),
92
- &:focus-visible {
93
- background-color: var(--fibery-emoji-hover-color, ${themeVars.badgeBgColor});
94
- }
95
- `}
96
- title={title}
97
- aria-label={emoji.name}
98
- >
99
- {renderEmoji ? (
100
- renderEmoji({emoji})
101
- ) : (
102
- <Emoji
103
- emoji={id}
104
- size={emojiContentSettings.emojiSize}
105
- version={emojiPickerCtx.version}
106
- skin={skin}
107
- native={emojiPickerCtx.native}
108
- />
109
- )}
110
- </IconButton>
111
- );
112
- };
113
-
114
- export type EmojiPickerCategoryProps = {
115
- category: Category;
116
-
117
- preRender?: boolean;
118
- scrollParent: Element | null;
119
- } & Pick<CategoryItemProps, "renderEmoji">;
120
-
121
- export const EmojiPickerCategory = memo<EmojiPickerCategoryProps>(function EmojiPickerCategoryComponent({
122
- category,
123
- renderEmoji,
124
- scrollParent,
125
- preRender = false,
126
- }) {
127
- const i18n = useEmojiPickerI18N();
128
- const emojiPickerCtx = useEmojiPickerCtx();
129
- const emojiContentSettings = useEmojiPickerContentSettings();
130
-
131
- const {ref, inView} = useInView({
132
- root: scrollParent,
133
- rootMargin: `129px 0px`, // grid height / 2
134
- initialInView: preRender,
135
- fallbackInView: true,
136
- triggerOnce: true,
137
- });
138
-
139
- const label = i18n.categories[category.id as keyof (typeof i18n)["categories"]] || category.name;
140
-
141
- const emojiSize = emojiContentSettings.emojiSize + emojiPadding * 2;
142
-
143
- return (
144
- <section className={categoryCss} aria-label={label}>
145
- <div className={categoryLabelCss}>
146
- {/* already labeled by the section aria-label */}
147
- <span aria-hidden={true}>{label}</span>
148
-
149
- {category.id === "custom" && emojiPickerCtx.onCustomCategorySettings && (
150
- <IconButton onClick={emojiPickerCtx.onCustomCategorySettings}>
151
- <Settings iconSize={16} />
152
- </IconButton>
153
- )}
154
- </div>
155
-
156
- {category.emojis.length > 0 ? (
157
- <ul ref={ref} className={categoryListCss}>
158
- {category.emojis.map((id) => {
159
- return (
160
- <li
161
- key={id}
162
- style={{
163
- width: emojiSize,
164
- height: emojiSize,
165
- }}
166
- >
167
- {inView ? <CategoryItem id={id} renderEmoji={renderEmoji} /> : null}
168
- </li>
169
- );
170
- })}
171
- </ul>
172
- ) : (
173
- <NotFound />
174
- )}
175
- </section>
176
- );
177
- });
@@ -1,29 +0,0 @@
1
- import {makeEmojiData} from "@fibery/emoji-data";
2
- import {Suspense, lazy} from "react";
3
- import {EmojiDataStoreProvider} from "./emoji-data-store";
4
- import {getEmojiSet} from "../utils/emoji-set";
5
- import {loadEmojiData} from "../utils/load-emoji-data";
6
-
7
- const LazyEmojiDataStoreComponent = lazy(async () => {
8
- const rawData = await loadEmojiData();
9
-
10
- const emojiData = makeEmojiData(rawData, {set: getEmojiSet()});
11
-
12
- return {
13
- default: function EmojiDataStore({children}: React.PropsWithChildren) {
14
- return <EmojiDataStoreProvider data={emojiData}>{children}</EmojiDataStoreProvider>;
15
- },
16
- };
17
- });
18
-
19
- export const LazyEmojiDataStore: React.FC<
20
- React.PropsWithChildren<{
21
- fallback: React.ReactNode;
22
- }>
23
- > = ({fallback, children}) => {
24
- return (
25
- <Suspense fallback={fallback}>
26
- <LazyEmojiDataStoreComponent>{children}</LazyEmojiDataStoreComponent>
27
- </Suspense>
28
- );
29
- };