@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
@@ -0,0 +1,78 @@
1
+ import {css, cx} from "@linaria/core";
2
+ import {themeVars, transition} from "./design-system";
3
+ import ArrowRight from "./icons/react/ArrowRight";
4
+ import {ComponentPropsWithoutRef, ElementType, forwardRef} from "react";
5
+ import More from "./icons/react/More";
6
+
7
+ export const Breadcrumb = ({...props}: React.ComponentProps<"nav">) => {
8
+ return <nav aria-label="breadcrumb" {...props} />;
9
+ };
10
+
11
+ const olReset = css`
12
+ margin: 0;
13
+ padding: 0;
14
+ list-style: none;
15
+ `;
16
+
17
+ const listCss = css`
18
+ display: flex;
19
+ align-items: center;
20
+ white-space: nowrap;
21
+ overflow: hidden;
22
+ text-overflow: ellipsis;
23
+ color: ${themeVars.colorTextButtonGhostNeutral};
24
+ `;
25
+
26
+ export const BreadcrumbList = ({className, ...props}: React.ComponentProps<"ol">) => {
27
+ return <ol className={cx(olReset, listCss, className)} {...props} />;
28
+ };
29
+
30
+ const itemCss = css`
31
+ display: flex;
32
+ align-items: center;
33
+ `;
34
+
35
+ export const BreadcrumbItem = forwardRef<HTMLLIElement, React.ComponentProps<"li">>(({className, ...props}, ref) => {
36
+ return <li ref={ref} className={cx(itemCss, className)} {...props} />;
37
+ });
38
+
39
+ const linkCss = css`
40
+ color: ${themeVars.colorTextButtonGhostNeutral};
41
+ &:hover {
42
+ color: ${themeVars.textColor};
43
+ }
44
+ transition: color ${transition};
45
+ `;
46
+
47
+ type BreadcrumbLinkProps<C extends ElementType = "a"> = {
48
+ as?: C;
49
+ className?: string;
50
+ } & ComponentPropsWithoutRef<C>;
51
+
52
+ export const BreadcrumbLink = <C extends ElementType = "a">({className, as, ...props}: BreadcrumbLinkProps<C>) => {
53
+ const Component = as || "a";
54
+ return <Component className={cx(linkCss, className)} {...props} />;
55
+ };
56
+
57
+ const liReset = css`
58
+ margin: 0;
59
+ padding: 0;
60
+ `;
61
+
62
+ export const BreadcrumbSeparator = ({children, className, ...props}: React.ComponentProps<"li">) => {
63
+ return (
64
+ <li role="presentation" aria-hidden="true" className={cx(liReset, className)} {...props}>
65
+ {children ?? <ArrowRight color={themeVars.colorTextButtonGhostNeutral} containerSize={16} iconSize={16} />}
66
+ </li>
67
+ );
68
+ };
69
+
70
+ export const BreadcrumbEllipsis = forwardRef<HTMLSpanElement, React.ComponentProps<"span">>(
71
+ ({className, ...props}, ref) => {
72
+ return (
73
+ <span ref={ref} role="presentation" aria-hidden="true" className={cx(className)} {...props}>
74
+ <More color={themeVars.colorTextButtonGhostNeutral} containerSize={16} iconSize={16} />
75
+ </span>
76
+ );
77
+ }
78
+ );
@@ -1,12 +1,15 @@
1
1
  import {forwardRef} from "react";
2
2
  import {IconButton, IconButtonProps} from "./icon-button";
3
3
  import MoreCompactIcon from "../icons/react/MoreCompact";
4
+ import MoreIcon from "../icons/react/More";
5
+ import {useIsPhone} from "../use-is-phone";
4
6
 
5
7
  export const ActionsButtonCompact = forwardRef<HTMLButtonElement, IconButtonProps>(
6
8
  function ActionsButtonCompactComponent({...rest}, ref) {
9
+ const isPhone = useIsPhone();
7
10
  return (
8
11
  <IconButton supportMobile={true} ref={ref} size="small" {...rest}>
9
- <MoreCompactIcon />
12
+ {isPhone ? <MoreIcon iconSize={20} /> : <MoreCompactIcon />}
10
13
  </IconButton>
11
14
  );
12
15
  }
@@ -3,7 +3,7 @@ import {forwardRef} from "react";
3
3
  import {themeVars} from "../design-system";
4
4
  import {iconColorVar} from "../icons/Icon";
5
5
 
6
- export type ButtonSize = "tiny" | "small" | "medium" | "large";
6
+ export type ButtonSize = "tiny" | "small" | "medium" | "large" | "xLarge";
7
7
  export type ButtonVariant = "solid" | "outline" | "soft" | "ghost";
8
8
  export type ButtonColor = "accent" | "neutral" | "error";
9
9
 
@@ -32,8 +32,10 @@ export const baseButton = css`
32
32
 
33
33
  box-shadow: inset 0 0 0 1px var(--fibery-button-border-color);
34
34
 
35
- &:hover:not(:disabled) {
36
- background-color: var(--fibery-button-hover-color);
35
+ @media (any-hover: hover) {
36
+ &:hover:not(:disabled) {
37
+ background-color: var(--fibery-button-hover-color);
38
+ }
37
39
  }
38
40
  &:active {
39
41
  color: var(--fibery-button-text-active-color);
@@ -29,7 +29,7 @@ const buttonGroupDirection = {
29
29
  `,
30
30
  };
31
31
 
32
- const buttonGroup = css`
32
+ export const buttonGroup = css`
33
33
  display: flex;
34
34
  align-items: flex-start;
35
35
  `;
@@ -140,6 +140,37 @@ const buttonSize = {
140
140
  padding-right: ${space.s8 - space.s1}px;
141
141
  }
142
142
 
143
+ & > .${shortcutContainer} {
144
+ font-size: ${textStyles.regular.fontSize}px;
145
+ }
146
+ `,
147
+ xLarge: css`
148
+ font-size: ${textStyles.heading3.fontSize}px;
149
+ line-height: 20px;
150
+ letter-spacing: ${textStyles.heading3.letterSpacing};
151
+
152
+ border-radius: ${border.radius6}px;
153
+ min-height: 44px;
154
+ padding: ${space.s6}px ${space.s12}px;
155
+ gap: ${space.s6}px;
156
+
157
+ ${iconSizeVar}: 24px;
158
+
159
+ &.${withIconStart} {
160
+ padding-left: ${space.s10}px;
161
+ padding-right: ${space.s12}px;
162
+ }
163
+
164
+ &.${withIconEnd} {
165
+ padding-left: ${space.s12}px;
166
+ padding-right: ${space.s10}px;
167
+ }
168
+
169
+ &.${withoutChildren} {
170
+ padding-left: ${space.s8 - space.s1}px;
171
+ padding-right: ${space.s8 - space.s1}px;
172
+ }
173
+
143
174
  & > .${shortcutContainer} {
144
175
  font-size: ${textStyles.regular.fontSize}px;
145
176
  }
@@ -52,6 +52,15 @@ export const iconButtonSizes = {
52
52
 
53
53
  ${iconSizeVar}: 18px;
54
54
  `,
55
+ xLarge: css`
56
+ padding: ${space.s6}px;
57
+
58
+ min-width: 44px;
59
+ min-height: 44px;
60
+ border-radius: ${border.radius6}px;
61
+
62
+ ${iconSizeVar}: 24px;
63
+ `,
55
64
  };
56
65
 
57
66
  export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(function IconButton(
@@ -21,6 +21,10 @@ const iconSize = {
21
21
  margin-left: -${space.s4}px;
22
22
  margin-right: -${space.s4}px;
23
23
  `,
24
+ xLarge: css`
25
+ margin-left: -${space.s4}px;
26
+ margin-right: -${space.s4}px;
27
+ `,
24
28
  };
25
29
 
26
30
  export type SelectButtonProps = {
@@ -7,6 +7,7 @@ import {getBg} from "./box";
7
7
  import {CardHiddenLink} from "./card-hidden-link";
8
8
  import {border, space, themeVars} from "./design-system";
9
9
  import {visuallyHidden} from "./styles-utils";
10
+ import {mobileRootSelector} from "./mobile-styles";
10
11
 
11
12
  export type CardSize =
12
13
  | ":card-size/pinned"
@@ -109,10 +110,7 @@ const cardClassName = css`
109
110
  flex-direction: column;
110
111
  flex-grow: 1;
111
112
  height: 100%;
112
- padding-left: ${space.s8}px;
113
- padding-right: ${space.s6}px;
114
- padding-top: ${space.s6}px;
115
- padding-bottom: ${space.s8}px;
113
+ padding: ${space.s8}px;
116
114
  gap: ${space.s6}px;
117
115
 
118
116
  & > div:empty:not(.${colorCodingClassName}) {
@@ -159,6 +157,11 @@ const listClassName = css`
159
157
  & > div.title-wrapper:has(a:empty) {
160
158
  display: none;
161
159
  }
160
+
161
+ ${mobileRootSelector} & {
162
+ gap: ${space.s8}px;
163
+ min-height: 36px;
164
+ }
162
165
  `;
163
166
 
164
167
  const timelineClassName = css`
@@ -66,6 +66,7 @@ const iconSizes = {
66
66
  medium: 18,
67
67
  large: 20,
68
68
  huge: 22,
69
+ xLarge: 22,
69
70
  };
70
71
 
71
72
  type SwatchProps = {
@@ -4,7 +4,7 @@ import {css, cx} from "@linaria/core";
4
4
  import {styled} from "@linaria/react";
5
5
  import {CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandRoot, CommandSeparator} from "cmdk";
6
6
  import {forwardRef, useRef, useState} from "react";
7
- import {border, layout, space, textStyles, themeVars} from "../design-system";
7
+ import {border, layout, layoutVars, space, textStyles, themeVars} from "../design-system";
8
8
  import ClearInputFilled from "../icons/react/ClearInputFilled";
9
9
  import Search from "../icons/react/Search";
10
10
 
@@ -92,7 +92,7 @@ export const CommandMenuEmpty = styled(CommandEmpty)`
92
92
  display: flex;
93
93
  align-items: center;
94
94
  padding: 0 ${space.s12}px;
95
- min-height: ${layout.itemHeight}px;
95
+ min-height: ${layoutVars.menuItemHeight};
96
96
  color: ${themeVars.accentTextColor};
97
97
  `;
98
98
 
@@ -119,7 +119,7 @@ export const commandItemCss = css`
119
119
  gap: ${space.s6}px;
120
120
  padding: 0 ${space.s8}px;
121
121
  cursor: pointer;
122
- min-height: ${layout.menuItemHeight}px;
122
+ min-height: ${layoutVars.menuItemHeight};
123
123
  margin: 0 ${space.s4}px;
124
124
  border-radius: ${border.radius6}px;
125
125
 
@@ -3,6 +3,7 @@ import {styled} from "@linaria/react";
3
3
  import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
4
4
  import {forwardRef} from "react";
5
5
  import {border, layout, space, textStyles, themeVars} from "../design-system";
6
+ import {mobileRootSelector} from "../mobile-styles";
6
7
 
7
8
  export const Root = (contextMenuProps: ContextMenuPrimitive.ContextMenuProps) => (
8
9
  <ContextMenuPrimitive.Root dir="ltr" {...contextMenuProps} />
@@ -22,7 +23,7 @@ export const rowItemStyles = {
22
23
  margin: `0px ${space.s4}px`,
23
24
  cursor: "pointer",
24
25
 
25
- "&:hover,&[data-highlighted]": {
26
+ '&:hover,&[data-highlighted],&[aria-expanded="true"]': {
26
27
  inset: "10px 4px",
27
28
  marginLeft: 4,
28
29
  marginRight: 4,
@@ -34,11 +35,19 @@ export const rowItemStyles = {
34
35
  cursor: "default",
35
36
  color: themeVars.disabledTextColor,
36
37
 
38
+ "--actions-menu-item-icon-color": themeVars.disabledTextColor,
39
+
37
40
  "&:hover": {
38
41
  color: themeVars.disabledTextColor,
39
42
  backgroundColor: themeVars.transparent,
40
43
  },
41
44
  },
45
+
46
+ [`${mobileRootSelector} &`]: {
47
+ ...textStyles.big,
48
+ minHeight: layout.mobileMenuItemHeight,
49
+ padding: `0px ${space.s12}px`,
50
+ },
42
51
  };
43
52
 
44
53
  const dropdownMenuContentStyles = css`
@@ -1,5 +1,5 @@
1
1
  import {ControlledDatePickerProps, DatePickerCommonProps, MomentDateRangeProps} from "./types";
2
- import {Popup} from "../popup";
2
+ import {PopoverOld} from "../popover";
3
3
  import {space} from "../design-system";
4
4
  import {withPopupControl} from "./with-popup-control";
5
5
  import {DateRangePickerPopupContent} from "./date-range-picker-popup-content";
@@ -19,6 +19,7 @@ export const DateRangePicker = forwardRef<
19
19
  DatePickerCommonProps & ControlledDatePickerProps & MomentDateRangeProps
20
20
  >((props, ref) => {
21
21
  const {
22
+ title,
22
23
  open,
23
24
  onOpen,
24
25
  onClose,
@@ -90,13 +91,15 @@ export const DateRangePicker = forwardRef<
90
91
 
91
92
  return (
92
93
  <div ref={bypassedRef}>
93
- <Popup
94
+ <PopoverOld
95
+ title={title}
94
96
  offset={[0, space.s6]}
95
97
  trigger={
96
98
  <div ref={fakeWrapperRef} onClick={stopPropagation}>
97
99
  {pickerValue}
98
100
  </div>
99
101
  }
102
+ supportMobile
100
103
  placement="bottom-start"
101
104
  open={open}
102
105
  onOpen={onOpen}
@@ -116,7 +119,7 @@ export const DateRangePicker = forwardRef<
116
119
  value={dateValue}
117
120
  onKeyDown={onDatePickerKeyDown}
118
121
  />
119
- </Popup>
122
+ </PopoverOld>
120
123
  </div>
121
124
  );
122
125
  });
@@ -6,6 +6,7 @@ import {RelativeDateValue} from "./types";
6
6
  import {useCallback, useMemo, useState} from "react";
7
7
  import {$TSFixMe} from "../tsfixme";
8
8
  import {AntInputNumber} from "../antd/input-number";
9
+ import {unitOfTime} from "moment";
9
10
 
10
11
  type RelativeDatePickerProps = {
11
12
  value: RelativeDateValue | null;
@@ -29,11 +30,14 @@ const isBeforeNowOptions = [
29
30
  export const RelativeDatePicker = (props: RelativeDatePickerProps) => {
30
31
  const {value, onChange, relativeDateToExactDate} = props;
31
32
 
32
- const valueWithDefault = useMemo(() => value ?? {unit: "day", isBeforeNow: true, amount: 0}, [value]);
33
+ const valueWithDefault = useMemo(
34
+ () => value ?? {unit: "day" as unitOfTime.DurationConstructor, isBeforeNow: true, amount: 0},
35
+ [value]
36
+ );
33
37
 
34
38
  const onUnitChange = useCallback(
35
39
  (newUnit: SingleValue<{value: string}>) => {
36
- onChange({...valueWithDefault, unit: newUnit!.value});
40
+ onChange({...valueWithDefault, unit: newUnit!.value as unitOfTime.DurationConstructor});
37
41
  },
38
42
  [valueWithDefault, onChange]
39
43
  );
@@ -11,7 +11,7 @@ import moment, {Moment} from "moment";
11
11
  import _ from "lodash";
12
12
  import {EmptyValue} from "../empty-value";
13
13
  import {formatDateInputValue} from "./utils";
14
- import {Popup} from "../popup";
14
+ import {PopoverOld} from "../popover";
15
15
  import {focusable} from "tabbable";
16
16
  import {TabNavLink, TabNavList, TabNavRoot} from "../tab-nav/tab-nav";
17
17
  import {RelativeDatePicker} from "./relative-date-picker";
@@ -29,7 +29,7 @@ const tabNavLinkClassName = css`
29
29
  justify-content: center;
30
30
  `;
31
31
 
32
- const isRelativeDatePlaceholder = (value: $TSFixMe) => {
32
+ export const isRelativeDatePlaceholder = (value: $TSFixMe) => {
33
33
  return (
34
34
  value !== null &&
35
35
  Object.hasOwn(value, "isBeforeNow") &&
@@ -38,7 +38,7 @@ const isRelativeDatePlaceholder = (value: $TSFixMe) => {
38
38
  );
39
39
  };
40
40
 
41
- const formatRelativeDate = (value: RelativeDateValue) => {
41
+ export const formatRelativeDate = (value: RelativeDateValue) => {
42
42
  if (value.amount === 0) {
43
43
  return "today";
44
44
  } else if (value.amount === 1 && value.unit === "day" && !value.isBeforeNow) {
@@ -76,6 +76,7 @@ export const SingleDatePicker: SingleDatePickerWithForwardRefType = forwardRef<
76
76
  SingleDatePickerProps<boolean>
77
77
  >((props, ref) => {
78
78
  const {
79
+ title,
79
80
  open,
80
81
  onOpen,
81
82
  onClose,
@@ -156,7 +157,8 @@ export const SingleDatePicker: SingleDatePickerWithForwardRefType = forwardRef<
156
157
 
157
158
  return (
158
159
  <div ref={bypassedRef}>
159
- <Popup
160
+ <PopoverOld
161
+ title={title}
160
162
  offset={[0, space.s6]}
161
163
  trigger={
162
164
  <div ref={fakeWrapperRef} onClick={stopPropagation}>
@@ -167,6 +169,7 @@ export const SingleDatePicker: SingleDatePickerWithForwardRefType = forwardRef<
167
169
  open={open}
168
170
  onOpen={onOpen}
169
171
  onClose={onClose}
172
+ supportMobile
170
173
  popupContainerClassName={css`
171
174
  z-index: 10001;
172
175
  `}
@@ -234,7 +237,7 @@ export const SingleDatePicker: SingleDatePickerWithForwardRefType = forwardRef<
234
237
  />
235
238
  )}
236
239
  </div>
237
- </Popup>
240
+ </PopoverOld>
238
241
  </div>
239
242
  );
240
243
  });
@@ -1,6 +1,7 @@
1
1
  import {css} from "@linaria/core";
2
2
  import {inputOverrides} from "../antd/styles";
3
3
  import {border, fontWeight, space, textStyles, themeVars} from "../design-system";
4
+ import {mobileRootSelector} from "../mobile-styles";
4
5
 
5
6
  export const selectedStyle = css`
6
7
  ${inputOverrides.focus}
@@ -113,6 +114,32 @@ export const endButtonClassName = css`
113
114
  background: linear-gradient(90deg, ${focusGradient}) !important;
114
115
  }
115
116
  `;
117
+ export const dayWrapper = css`
118
+ display: flex;
119
+ height: 100%;
120
+ position: relative;
121
+ `;
122
+ export const dayContentClassName = css`
123
+ pointer-events: none;
124
+ position: absolute;
125
+ top: 0;
126
+ bottom: 0;
127
+ left: 0;
128
+ right: 0;
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: center;
132
+ `;
133
+ export const dayButtonsContainerClassName = css`
134
+ position: absolute;
135
+ top: 0;
136
+ left: 0;
137
+ bottom: 0;
138
+ right: 0;
139
+ display: flex;
140
+ align-items: stretch;
141
+ justify-content: stretch;
142
+ `;
116
143
  export const datePickerStylesOverrideClassName = css`
117
144
  .rdp {
118
145
  --rdp-cell-size: 36px;
@@ -150,6 +177,11 @@ export const datePickerStylesOverrideClassName = css`
150
177
  border: none !important;
151
178
  }
152
179
 
180
+ ${mobileRootSelector} & .${dayContentClassName} {
181
+ width: auto;
182
+ max-width: unset;
183
+ }
184
+
153
185
  .rdp-day.${startRangeClassName}.${endRangeClassName} {
154
186
  border-radius: ${border.radius12}px !important;
155
187
  }
@@ -234,29 +266,3 @@ export const datePickerStylesOverrideClassName = css`
234
266
  }
235
267
  }
236
268
  `;
237
- export const dayWrapper = css`
238
- display: flex;
239
- height: 100%;
240
- position: relative;
241
- `;
242
- export const dayContentClassName = css`
243
- pointer-events: none;
244
- position: absolute;
245
- top: 0;
246
- bottom: 0;
247
- left: 0;
248
- right: 0;
249
- display: flex;
250
- align-items: center;
251
- justify-content: center;
252
- `;
253
- export const dayButtonsContainerClassName = css`
254
- position: absolute;
255
- top: 0;
256
- left: 0;
257
- bottom: 0;
258
- right: 0;
259
- display: flex;
260
- align-items: stretch;
261
- justify-content: stretch;
262
- `;
@@ -1,8 +1,9 @@
1
1
  import {Moment} from "moment";
2
2
  import {$TSFixMe} from "../tsfixme";
3
3
  import {ReactNode} from "react";
4
+ import {unitOfTime} from "moment";
4
5
 
5
- export type RelativeDateValue = {isBeforeNow: boolean; unit: string; amount: number};
6
+ export type RelativeDateValue = {isBeforeNow: boolean; unit: unitOfTime.DurationConstructor; amount: number};
6
7
 
7
8
  export type MomentSingleDateProps<AllowRelativeDate extends boolean = false> = {
8
9
  value: AllowRelativeDate extends true ? Moment | RelativeDateValue | null : Moment | null;
@@ -17,6 +18,7 @@ export type NativeSingleDatePickerProps = {
17
18
  };
18
19
 
19
20
  export type DatePickerCommonProps = {
21
+ title?: string;
20
22
  showTime?: boolean;
21
23
  showToday?: boolean;
22
24
  showInput?: boolean;
@@ -1,71 +1,27 @@
1
- import {ChangeEvent} from "react";
2
1
  import {css} from "@linaria/core";
3
- import {colors, themeVars} from "../design-system";
4
- import {inputOverrides} from "../antd/styles";
2
+ import {RoundToggleButton} from "../toggle-button/round-toggle-button";
3
+ import {ToggleButtonGroup, ToggleButtonGroupItem} from "../toggle-button/toggle-button-group";
5
4
 
6
- export type Props<T extends number> = {
7
- value: Array<T>;
8
- onChange: (v: Array<T>) => void;
9
- days: Array<{key: string; title: string; value: T}>;
5
+ export type Props = {
6
+ value: Array<number>;
7
+ onChange: (v: Array<number>) => void;
8
+ days: Array<{key: string; title: string; value: number}>;
10
9
  allowEmpty?: boolean;
11
10
  };
12
11
 
13
- const daySize = "28px";
12
+ export function DaySelect({value = [], onChange, days, allowEmpty = false}: Props): JSX.Element {
13
+ const stringifiedValue = value.map((v) => v.toString());
14
14
 
15
- const checkboxInput = css`
16
- position: absolute;
17
- appearance: none;
18
- `;
19
-
20
- const checkbox = css`
21
- position: absolute;
22
- border-radius: 50%;
23
- font-size: 14px;
24
- width: ${daySize};
25
- height: ${daySize};
26
- display: flex;
27
- align-items: center;
28
- justify-content: center;
29
- color: ${themeVars.accentTextColor};
30
- background-color: ${themeVars.unitBg};
31
- .${checkboxInput}:checked + & {
32
- color: ${colors.inversedTextColor};
33
- background-color: ${themeVars.primary};
34
- }
35
- .${checkboxInput}:focus-visible + & {
36
- ${inputOverrides.focus}
37
- }
38
- `;
39
-
40
- function Day<T extends number>({
41
- value,
42
- onChange,
43
- checked,
44
- title,
45
- }: {
46
- value: T;
47
- onChange: (e: ChangeEvent<HTMLInputElement>) => void;
48
- checked: boolean;
49
- title: string;
50
- }): JSX.Element {
51
- return (
52
- <label
53
- className={css`
54
- cursor: pointer;
55
- position: relative;
56
- width: ${daySize};
57
- height: ${daySize};
58
- `}
59
- >
60
- <input className={checkboxInput} onChange={onChange} checked={checked} type="checkbox" value={value} />
61
- <div className={checkbox}>{title}</div>
62
- </label>
63
- );
64
- }
65
-
66
- export function DaySelect<T extends number>({value = [], onChange, days, allowEmpty = false}: Props<T>): JSX.Element {
67
15
  return (
68
- <div
16
+ <ToggleButtonGroup
17
+ type="multiple"
18
+ value={stringifiedValue}
19
+ onValueChange={(v) => {
20
+ if (v.length === 0 && !allowEmpty) {
21
+ return;
22
+ }
23
+ onChange(v.map(Number));
24
+ }}
69
25
  className={css`
70
26
  grid-template-columns: repeat(7, min-content);
71
27
  gap: 4px;
@@ -74,21 +30,11 @@ export function DaySelect<T extends number>({value = [], onChange, days, allowEm
74
30
  >
75
31
  {days.map(({key, value: v, title}) => {
76
32
  return (
77
- <Day
78
- checked={value.includes(v)}
79
- onChange={({currentTarget: {checked}}) => {
80
- if (checked) {
81
- onChange(value.concat(v));
82
- } else if (allowEmpty || value.length > 1) {
83
- onChange(value.filter((val) => val !== v));
84
- }
85
- }}
86
- key={key}
87
- title={title}
88
- value={v}
89
- />
33
+ <ToggleButtonGroupItem key={key} asChild value={v.toString()}>
34
+ <RoundToggleButton>{title}</RoundToggleButton>
35
+ </ToggleButtonGroupItem>
90
36
  );
91
37
  })}
92
- </div>
38
+ </ToggleButtonGroup>
93
39
  );
94
40
  }
@@ -10,6 +10,6 @@ const isoWeekDays = _.range(1, 8).map((day) => {
10
10
  };
11
11
  });
12
12
 
13
- export function IsoWeekdaySelect({value, onChange, allowEmpty}: Omit<Props<number>, "days">): JSX.Element {
13
+ export function IsoWeekdaySelect({value, onChange, allowEmpty}: Omit<Props, "days">): JSX.Element {
14
14
  return <DaySelect value={value} onChange={onChange} days={isoWeekDays} allowEmpty={allowEmpty} />;
15
15
  }
@@ -3,9 +3,9 @@ import {DaySelect, Props} from "./day-select";
3
3
  const days = Array.from({length: 28}).map((_, index) => {
4
4
  const value = index + 1;
5
5
  const key = String(value);
6
- return {key: String(value), title: key, value};
6
+ return {key: String(value), title: key, value: value};
7
7
  });
8
8
 
9
- export function MonthdaySelect({value = [], onChange}: Omit<Props<number>, "days">): JSX.Element {
9
+ export function MonthdaySelect({value = [], onChange}: Omit<Props, "days">): JSX.Element {
10
10
  return <DaySelect value={value} onChange={onChange} days={days} />;
11
11
  }
@@ -32,11 +32,7 @@ export const getDays = _.memoize((firstDay) => {
32
32
  });
33
33
  });
34
34
 
35
- export function WeekdaySelect({
36
- value = [],
37
- onChange,
38
- firstDay,
39
- }: Omit<Props<Days>, "days"> & {firstDay: number}): JSX.Element {
35
+ export function WeekdaySelect({value = [], onChange, firstDay}: Omit<Props, "days"> & {firstDay: number}): JSX.Element {
40
36
  const days = getDays(firstDay);
41
37
  return <DaySelect value={value} onChange={onChange} days={days} />;
42
38
  }