@fibery/ui-kit 1.37.0 → 1.38.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 (139) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +8 -5
  3. package/src/actions-menu/actions-menu-item.tsx +18 -6
  4. package/src/actions-menu/actions-menu-props.tsx +4 -0
  5. package/src/actions-menu/actions-menu-sub-command-menu.tsx +7 -4
  6. package/src/actions-menu/actions-menu-sub-menu.tsx +9 -3
  7. package/src/actions-menu/actions-menu.tsx +24 -8
  8. package/src/actions-panel.tsx +12 -2
  9. package/src/axis-header.tsx +136 -76
  10. package/src/box.tsx +1 -1
  11. package/src/breadcrumb.tsx +78 -0
  12. package/src/button/actions-button-compact.tsx +4 -1
  13. package/src/button/base-button.tsx +5 -3
  14. package/src/button/button-group.tsx +1 -1
  15. package/src/button/button.tsx +31 -0
  16. package/src/button/icon-button.tsx +9 -0
  17. package/src/button/select-button.tsx +4 -0
  18. package/src/card-container.tsx +7 -4
  19. package/src/color-picker/swatch.tsx +1 -0
  20. package/src/command-menu/index.tsx +3 -3
  21. package/src/context-menu/index.tsx +10 -1
  22. package/src/date-picker/date-range-picker.tsx +6 -3
  23. package/src/date-picker/relative-date-picker.tsx +6 -2
  24. package/src/date-picker/single-date-picker.tsx +8 -5
  25. package/src/date-picker/styles.ts +32 -26
  26. package/src/date-picker/types.ts +3 -1
  27. package/src/day-select/day-select.tsx +21 -75
  28. package/src/day-select/iso-week-day-select.tsx +1 -1
  29. package/src/day-select/mount-day-select.tsx +2 -2
  30. package/src/day-select/week-day-select.tsx +1 -5
  31. package/src/design-system.ts +21 -12
  32. package/src/dropdown-menu/index.tsx +8 -1
  33. package/src/emoji-picker/app-icon-picker.tsx +6 -4
  34. package/src/emoji-picker/emoji-picker-preview-footer.tsx +1 -1
  35. package/src/emoji-picker/emoji-picker.tsx +3 -0
  36. package/src/emoji-picker/emoji.tsx +2 -1
  37. package/src/emoji-picker/icon-emoji-picker.tsx +10 -1
  38. package/src/emoji-picker/primitives/footer.tsx +0 -1
  39. package/src/emoji-picker/primitives/skin-tone.tsx +1 -0
  40. package/src/emoji-picker/use-responsive-emoji-size.ts +11 -0
  41. package/src/emoji-picker/utils/emoji-set.ts +2 -1
  42. package/src/empty-state/empty-state.tsx +6 -0
  43. package/src/field-icon.tsx +4 -1
  44. package/src/file-item.tsx +164 -47
  45. package/src/html-styles.ts +8 -0
  46. package/src/icons/ast/ActivityFilled.ts +8 -0
  47. package/src/icons/ast/AiAssistantFilled.ts +8 -0
  48. package/src/icons/ast/CollapseAllHorizontal.ts +8 -0
  49. package/src/icons/ast/DateRange.ts +1 -1
  50. package/src/icons/ast/EntityCreateFilled.ts +8 -0
  51. package/src/icons/ast/ExpandAllHorizontal.ts +8 -0
  52. package/src/icons/ast/GlobeUnpublish.ts +8 -0
  53. package/src/icons/ast/HomeFilled.ts +8 -0
  54. package/src/icons/ast/KeyboardHideDown.ts +8 -0
  55. package/src/icons/ast/LayoutMultiple.ts +8 -0
  56. package/src/icons/ast/RicheditorHistoryRedo.ts +1 -1
  57. package/src/icons/ast/RicheditorHistoryUndo.ts +1 -1
  58. package/src/icons/ast/SearchFilled.ts +8 -0
  59. package/src/icons/ast/SettingsFilled.ts +8 -0
  60. package/src/icons/ast/SlideMenuFilled.ts +8 -0
  61. package/src/icons/ast/TypeDate.ts +1 -1
  62. package/src/icons/ast/index.tsx +12 -0
  63. package/src/icons/react/ActivityFilled.tsx +13 -0
  64. package/src/icons/react/AiAssistantFilled.tsx +13 -0
  65. package/src/icons/react/CollapseAllHorizontal.tsx +13 -0
  66. package/src/icons/react/EntityCreateFilled.tsx +13 -0
  67. package/src/icons/react/ExpandAllHorizontal.tsx +13 -0
  68. package/src/icons/react/GlobeUnpublish.tsx +13 -0
  69. package/src/icons/react/HomeFilled.tsx +13 -0
  70. package/src/icons/react/KeyboardHideDown.tsx +13 -0
  71. package/src/icons/react/LayoutMultiple.tsx +13 -0
  72. package/src/icons/react/SearchFilled.tsx +13 -0
  73. package/src/icons/react/SettingsFilled.tsx +13 -0
  74. package/src/icons/react/SlideMenuFilled.tsx +13 -0
  75. package/src/icons/react/index.tsx +12 -0
  76. package/src/icons/svg/activity-filled.svg +4 -0
  77. package/src/icons/svg/ai-assistant-filled.svg +3 -0
  78. package/src/icons/svg/collapse-all-horizontal.svg +3 -0
  79. package/src/icons/svg/date-range.svg +3 -3
  80. package/src/icons/svg/entity-create-filled.svg +4 -0
  81. package/src/icons/svg/expand-all-horizontal.svg +3 -0
  82. package/src/icons/svg/globe-unpublish.svg +4 -0
  83. package/src/icons/svg/home-filled.svg +3 -0
  84. package/src/icons/svg/keyboard-hide-down.svg +1 -0
  85. package/src/icons/svg/layout-multiple.svg +3 -0
  86. package/src/icons/svg/richeditor/history/redo.svg +3 -2
  87. package/src/icons/svg/richeditor/history/undo.svg +3 -2
  88. package/src/icons/svg/search-filled.svg +3 -0
  89. package/src/icons/svg/settings-filled.svg +3 -0
  90. package/src/icons/svg/slide-menu-filled.svg +1 -0
  91. package/src/icons/svg/type/date.svg +3 -2
  92. package/src/images-gallery/images-gallery.tsx +254 -0
  93. package/src/images-gallery/zoom.tsx +112 -0
  94. package/src/is-in-popup.ts +1 -1
  95. package/src/layout-styles.ts +21 -1
  96. package/src/lists/actions-menu-row-surface.tsx +3 -1
  97. package/src/lists/list-row-surface.tsx +7 -1
  98. package/src/mobile-keyboard-aware-popup.tsx +87 -0
  99. package/src/mobile-styles.ts +8 -0
  100. package/src/modal-menu/contexts/modal-menu-context.tsx +22 -0
  101. package/src/modal-menu/contexts/modal-submenu-context.tsx +16 -0
  102. package/src/modal-menu/index.tsx +14 -0
  103. package/src/modal-menu/modal-menu-content.tsx +68 -0
  104. package/src/modal-menu/modal-menu-group.tsx +10 -0
  105. package/src/modal-menu/modal-menu-item.tsx +37 -0
  106. package/src/modal-menu/modal-menu-label.tsx +24 -0
  107. package/src/modal-menu/modal-menu-root.tsx +57 -0
  108. package/src/modal-menu/modal-menu-separator.tsx +14 -0
  109. package/src/modal-menu/modal-menu-trigger.tsx +37 -0
  110. package/src/modal-menu/modal-submenu-content.tsx +49 -0
  111. package/src/modal-menu/modal-submenu-trigger.tsx +34 -0
  112. package/src/modal-menu/modal-submenu.tsx +17 -0
  113. package/src/online-users.tsx +3 -3
  114. package/src/palette.ts +1 -1
  115. package/src/popover/index.tsx +687 -0
  116. package/src/popover/mobile-popup-context.tsx +29 -0
  117. package/src/{popup → popover}/modifiers.tsx +0 -7
  118. package/src/{popup → popover}/popup-modifiers-context.ts +3 -3
  119. package/src/reactions/reaction-button.tsx +30 -45
  120. package/src/reactions/reaction-picker.tsx +39 -45
  121. package/src/select/index.tsx +8 -4
  122. package/src/select/select-in-popover.tsx +21 -33
  123. package/src/tab-nav/tab-nav.tsx +35 -9
  124. package/src/toast/primitives.tsx +8 -1
  125. package/src/toggle-button/round-toggle-button.tsx +23 -0
  126. package/src/toggle-button/toggle-button-group.tsx +34 -0
  127. package/src/toggle-button/toggle-button.tsx +164 -0
  128. package/src/toggle.tsx +3 -3
  129. package/src/tooltip.tsx +2 -2
  130. package/src/unit/styles.ts +2 -2
  131. package/src/use-is-phone.tsx +28 -3
  132. package/src/use-is-support-hover.ts +1 -1
  133. package/src/use-on-screen-keyboard-data.tsx +66 -0
  134. package/src/workflow-progress-icon.tsx +16 -22
  135. package/src/popup/index.tsx +0 -383
  136. /package/src/{popup → popover}/popup-stack-context.tsx +0 -0
  137. /package/src/{popup → popover}/reference.ts +0 -0
  138. /package/src/{popup → popover}/styles.ts +0 -0
  139. /package/src/{popup → popover}/use-click-outside.ts +0 -0
@@ -1,383 +0,0 @@
1
- import {stopPropagation} from "@fibery/react/src/stop-propagation";
2
- import {useControllableState} from "@fibery/react/src/use-controllable-state";
3
- import {usePointerDownOutside} from "@fibery/react/src/use-pointer-down-outside";
4
- import {css} from "@linaria/core";
5
- import {createPopper, Modifier, Placement, State} from "@popperjs/core";
6
- import {Options as FlipOptions} from "@popperjs/core/lib/modifiers/flip";
7
- import {Options as PreventOverflowOptions} from "@popperjs/core/lib/modifiers/preventOverflow";
8
- import cx from "classnames";
9
- import _ from "lodash";
10
- import {
11
- CSSProperties,
12
- forwardRef,
13
- MouseEvent,
14
- ReactNode,
15
- useEffect,
16
- useId,
17
- useImperativeHandle,
18
- useMemo,
19
- useRef,
20
- useState,
21
- } from "react";
22
- import {createPortal} from "react-dom";
23
- import {usePopper} from "react-popper";
24
- import {createInlineTheme, fontWeight, space, themeVars} from "../design-system";
25
- import {IconButton} from "../button/icon-button";
26
- import CloseIcon from "../icons/react/Close";
27
- import {useTheme} from "../theme-provider";
28
- import {$TSFixMe} from "../tsfixme";
29
- import {useIsPhone} from "../use-is-phone";
30
- import {usePopupModifiers} from "./popup-modifiers-context";
31
- import {getMaxSize, observeWidth} from "./modifiers";
32
- import {isElementReference, Reference} from "./reference";
33
- import {basicPopupClassName, basicPopupContainerClassName, hidePopupWhenTriggerIsHiddenClassName} from "./styles";
34
- import {usePopupStackContext} from "./popup-stack-context";
35
-
36
- export type Props = {
37
- trigger?: ReactNode;
38
- children: ReactNode;
39
- placement: Placement;
40
- open: boolean;
41
- popupStyle?: $TSFixMe;
42
- mobilePopupStyle?: CSSProperties;
43
- mobilePopupContentClassName?: string;
44
- popupClassName?: string;
45
- popupContainerClassName?: string;
46
- renderInPortal?: boolean;
47
- offset?: [number, number];
48
- disabled?: boolean;
49
- triggerDomElement?: Reference;
50
- onMouseLeave?: (e: MouseEvent<HTMLDivElement>) => void;
51
- renderBackdrop?: boolean;
52
- backdropClassName?: string;
53
- closeOnEscape?: boolean;
54
- preventOverflowOptions?: Partial<PreventOverflowOptions>;
55
- flipOptions?: Partial<FlipOptions>;
56
- additionalModifiers?: Array<Partial<Modifier<$TSFixMe, $TSFixMe>>>;
57
- hidePopupWhenTriggerIsHidden?: boolean;
58
- shrinkable?: boolean;
59
- onOpen?: () => unknown;
60
- onClose?: (event: Event) => unknown;
61
- supportMobile?: boolean;
62
- title?: string;
63
- getPopupContainer?: () => HTMLElement;
64
-
65
- /**
66
- * @deprecated
67
- * Because of openning animation popup creates new stacking context https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context
68
- * this might break any components that use position: fixed inside the popup (i.e. formula editor -> monaco editor)
69
- * Pass true to restore stacking context after animation is finished.
70
- *
71
- * Marked as deprecated because it's better to avoid this prop
72
- */
73
- fixStackingContextAfterOpen?: boolean;
74
- /**
75
- * ran after Popup positioned the element the first time
76
- */
77
- onFirstUpdate?: () => void;
78
- };
79
-
80
- export type {State};
81
-
82
- export type PopupApi = {popupElement: HTMLDivElement | null; update: (() => Promise<unknown>) | null};
83
-
84
- function MobilePopup({
85
- content,
86
- mobilePopupStyle,
87
- mobilePopupContentClassName,
88
- title,
89
- onClose,
90
- }: {
91
- content: ReactNode;
92
- mobilePopupStyle?: CSSProperties;
93
- mobilePopupContentClassName?: string;
94
- title: string;
95
- onClose: () => void;
96
- }) {
97
- const theme = useTheme();
98
-
99
- return createPortal(
100
- <div
101
- className={css`
102
- position: absolute;
103
- top: 0;
104
- bottom: 0;
105
- left: 0;
106
- right: 0;
107
- background: ${themeVars.actionMenuBg};
108
- z-index: 1002;
109
- display: grid;
110
- grid-template-rows: 45px 1fr;
111
- `}
112
- style={{...createInlineTheme(theme), ...mobilePopupStyle}}
113
- >
114
- <div
115
- className={css`
116
- display: flex;
117
- align-items: center;
118
- justify-content: space-between;
119
- gap: ${space.s8}px;
120
- padding: 0 ${space.s8}px 0 ${space.s12}px;
121
- `}
122
- >
123
- <div
124
- className={css`
125
- font-weight: ${fontWeight.medium};
126
- font-size: 16px;
127
- min-width: 0;
128
- overflow: hidden;
129
- text-overflow: ellipsis;
130
- `}
131
- >
132
- {title}
133
- </div>
134
- <IconButton onClick={onClose} size={"large"}>
135
- <CloseIcon />
136
- </IconButton>
137
- </div>
138
- <div
139
- className={cx(
140
- css`
141
- border-top: ${themeVars.separators.opacity5};
142
- min-width: 0;
143
- `,
144
- mobilePopupContentClassName
145
- )}
146
- >
147
- {content}
148
- </div>
149
- </div>,
150
- document.body
151
- );
152
- }
153
-
154
- export const Popup = forwardRef<PopupApi, Props>(
155
- (
156
- {
157
- trigger,
158
- children,
159
- placement,
160
- open,
161
- popupStyle,
162
- popupContainerClassName,
163
- popupClassName,
164
- renderInPortal,
165
- offset = [0, 0],
166
- disabled = false,
167
- triggerDomElement,
168
- onMouseLeave,
169
- renderBackdrop,
170
- backdropClassName,
171
- closeOnEscape = true,
172
- preventOverflowOptions = {},
173
- flipOptions = {},
174
- additionalModifiers = [],
175
- hidePopupWhenTriggerIsHidden = true,
176
- shrinkable,
177
- onOpen = _.noop,
178
- onClose = _.noop,
179
- supportMobile = false,
180
- title = "",
181
- mobilePopupStyle,
182
- mobilePopupContentClassName,
183
- getPopupContainer: popupContainerOverride,
184
- fixStackingContextAfterOpen = false,
185
- onFirstUpdate,
186
- },
187
- ref
188
- ) => {
189
- const popupModifiers = usePopupModifiers();
190
- const getPopupContainer = popupContainerOverride ?? popupModifiers.getPopupContainer;
191
- const id = useId();
192
- const theme = useTheme();
193
- const {registerEscapeCallback, registerPopup} = usePopupStackContext();
194
- const isPhone = useIsPhone();
195
- const updateRef = useRef<(() => Promise<unknown>) | null>(null);
196
- const [triggerElement, setTriggerElement] = useControllableState<Reference>({value: triggerDomElement});
197
- const [popupElement, setPopupElement] = useState<HTMLDivElement | null>(null);
198
-
199
- const shrinkableModifiers = useMemo(() => {
200
- return shrinkable ? getMaxSize(preventOverflowOptions) : [];
201
- }, [preventOverflowOptions, shrinkable]);
202
- // migrate to floating-ui https://floating-ui.com/docs/migration
203
- const {styles, attributes, update} = usePopper(triggerElement, popupElement, {
204
- placement,
205
- onFirstUpdate,
206
- modifiers: [
207
- {
208
- name: "flip",
209
- options: {
210
- ...popupModifiers.flipOptions,
211
- ...flipOptions,
212
- },
213
- },
214
- {
215
- name: "preventOverflow",
216
- options: {
217
- tether: false,
218
- padding: space.s6,
219
- ...popupModifiers.preventOverflowOptions,
220
- ...preventOverflowOptions,
221
- },
222
- },
223
- {
224
- name: "offset",
225
- options: {
226
- offset: offset,
227
- },
228
- },
229
- observeWidth,
230
- ...shrinkableModifiers,
231
- ...additionalModifiers,
232
- ...(popupModifiers.additionalModifiers ?? []),
233
- ],
234
- });
235
- updateRef.current = update;
236
- useImperativeHandle(
237
- ref,
238
- () => {
239
- return {popupElement, update};
240
- },
241
- [popupElement, update]
242
- );
243
- useEffect(() => {
244
- let unregister: () => void;
245
- if (registerPopup && open) {
246
- unregister = registerPopup(id);
247
- }
248
- return () => {
249
- unregister?.();
250
- };
251
- }, [registerPopup, id, open]);
252
- useEffect(() => {
253
- if (triggerElement && closeOnEscape && open) {
254
- const onKeyDown = (evt: KeyboardEvent) => {
255
- if (evt.defaultPrevented) {
256
- return;
257
- }
258
- if (evt.key === "Escape") {
259
- onClose(evt);
260
- evt.preventDefault();
261
- evt.stopPropagation();
262
- }
263
- };
264
-
265
- if (registerEscapeCallback) {
266
- registerEscapeCallback(id, onKeyDown);
267
- } else {
268
- document.addEventListener("keydown", onKeyDown);
269
- }
270
-
271
- // if popup was opened but nothing was focused inside it we should catch 'Escape' key from trigger as well
272
- // otherwise it can be caught by navigation panel
273
- "addEventListener" in triggerElement && triggerElement.addEventListener("keydown", onKeyDown);
274
-
275
- return () => {
276
- if (!registerEscapeCallback) {
277
- document.removeEventListener("keydown", onKeyDown);
278
- }
279
-
280
- "removeEventListener" in triggerElement && triggerElement.removeEventListener("keydown", onKeyDown);
281
- };
282
- }
283
- // eslint-disable-next-line @typescript-eslint/no-empty-function
284
- return () => {};
285
- }, [closeOnEscape, onClose, open, triggerElement, registerEscapeCallback, id]);
286
-
287
- const {onPointerDownCapture} = usePointerDownOutside((event) => {
288
- if (!open || (isPhone && supportMobile)) {
289
- return;
290
- }
291
- const target = event.target;
292
- if (target instanceof Node) {
293
- const ignoreElements = _.compact([isElementReference(triggerElement) && triggerElement]);
294
- if (ignoreElements.some((element) => element.contains(target))) {
295
- return;
296
- }
297
- }
298
- onClose(event);
299
- });
300
-
301
- if (isPhone && supportMobile) {
302
- return open ? (
303
- <MobilePopup
304
- onClose={onClose}
305
- title={title}
306
- mobilePopupContentClassName={mobilePopupContentClassName}
307
- mobilePopupStyle={mobilePopupStyle}
308
- content={children}
309
- />
310
- ) : null;
311
- }
312
-
313
- const renderPopup = () => {
314
- return (
315
- <>
316
- {renderBackdrop && (
317
- <div
318
- id={"popup-backdrop"}
319
- data-testid={"popup-backdrop"}
320
- className={cx(
321
- backdropClassName,
322
- css`
323
- position: absolute;
324
- inset: 0;
325
- z-index: 1000;
326
- `
327
- )}
328
- />
329
- )}
330
- <div
331
- className={cx(
332
- basicPopupContainerClassName,
333
- hidePopupWhenTriggerIsHidden && hidePopupWhenTriggerIsHiddenClassName,
334
- popupContainerClassName
335
- )}
336
- onMouseLeave={onMouseLeave}
337
- ref={setPopupElement}
338
- onClick={stopPropagation}
339
- {...attributes.popper}
340
- onPointerDownCapture={onPointerDownCapture}
341
- style={{...styles.popper, ...createInlineTheme(theme), ...popupStyle}}
342
- >
343
- <div
344
- className={cx(basicPopupClassName, popupClassName)}
345
- onAnimationEnd={
346
- fixStackingContextAfterOpen
347
- ? (e) => (e.target as HTMLElement).setAttribute("data-fix-stacking-context", "")
348
- : undefined
349
- }
350
- style={popupStyle}
351
- >
352
- {children}
353
- </div>
354
- </div>
355
- </>
356
- );
357
- };
358
-
359
- // TODO: ui-kit should not know about portal container in main ui
360
- if (triggerDomElement) {
361
- return open ? (renderInPortal ? createPortal(renderPopup(), getPopupContainer()) : renderPopup()) : null;
362
- }
363
-
364
- const onMouseDown: React.MouseEventHandler<HTMLDivElement> = (e) => {
365
- if (e.button === 0) {
366
- open ? onClose(e as unknown as Event) : onOpen();
367
- }
368
- };
369
-
370
- return (
371
- <div>
372
- <div ref={setTriggerElement} onMouseDown={disabled ? undefined : onMouseDown}>
373
- {trigger}
374
- </div>
375
- {open ? (renderInPortal ? createPortal(renderPopup(), getPopupContainer()) : renderPopup()) : null}
376
- </div>
377
- );
378
- }
379
- );
380
-
381
- export {createPopper};
382
-
383
- export type {Placement};
File without changes
File without changes
File without changes
File without changes