@fibery/ui-kit 4.0.0 → 4.2.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.
- package/CHANGELOG.md +18 -0
- package/esfint.config.mjs +0 -17
- package/package.json +7 -10
- package/scripts/generate-icons.mjs +45 -44
- package/src/actions-menu/actions-menu-item.tsx +1 -1
- package/src/actions-menu/context-actions-menu.tsx +1 -1
- package/src/animated-height-container.tsx +1 -1
- package/src/antd/ant-modal.tsx +21 -21
- package/src/antd/ant-upload.tsx +13 -13
- package/src/antd/auto-complete.tsx +10 -10
- package/src/antd/input-number.tsx +55 -45
- package/src/antd/styles.ts +30 -22
- package/src/antd/tabs.tsx +28 -28
- package/src/app-icon-with-fallback.tsx +3 -7
- package/src/app-icon-wrapper.tsx +1 -13
- package/src/breadcrumb.tsx +5 -1
- package/src/color-filter.ts +1 -1
- package/src/color-utils.test.ts +2 -2
- package/src/color-utils.ts +2 -2
- package/src/comment.tsx +2 -2
- package/src/copy-to-clipboard.ts +14 -3
- package/src/count-badge.tsx +3 -11
- package/src/date-picker/contexts.ts +6 -3
- package/src/date-picker/date-range-picker.tsx +1 -2
- package/src/date-picker/single-date-picker.tsx +1 -2
- package/src/day-select/iso-week-day-select.tsx +2 -2
- package/src/design-system/colors.ts +60 -40
- package/src/design-system/def.ts +1 -1
- package/src/dom-utils.ts +5 -12
- package/src/download-file.ts +36 -0
- package/src/dropdown-menu/index.tsx +0 -1
- package/src/emoji-picker/icon-emoji-picker.tsx +3 -3
- package/src/file-item/file-menu-items.tsx +29 -11
- package/src/file-item/file-preview-actions.tsx +52 -11
- package/src/file-item/share-file.ts +53 -0
- package/src/file-item.tsx +9 -9
- package/src/html-styles.ts +0 -1
- package/src/icons/ast/gauge.ts +12 -0
- package/src/icons/ast/index.tsx +449 -447
- package/src/icons/ast/people-edit.ts +12 -0
- package/src/icons/icon.tsx +14 -2
- package/src/icons/icons-integrity.test.ts +145 -0
- package/src/icons/react/gauge.tsx +18 -0
- package/src/icons/react/index.tsx +449 -447
- package/src/icons/react/people-edit.tsx +18 -0
- package/src/icons/svg/gauge.svg +5 -0
- package/src/icons/svg/people-edit.svg +4 -0
- package/src/images-gallery/images-gallery.tsx +2 -3
- package/src/images-gallery/slide-buttons.tsx +51 -20
- package/src/is-in-popup.ts +0 -3
- package/src/lists/actions-menu-row-surface.tsx +1 -1
- package/src/loading-sausage.tsx +3 -3
- package/src/media-query-utils.ts +1 -1
- package/src/mobile-keyboard-aware-popup.tsx +1 -1
- package/src/number-input/decimal.ts +6 -9
- package/src/number-input/number-input-inline-with-autosize.tsx +1 -1
- package/src/online-users.tsx +4 -5
- package/src/palettes/diff-colors.test.ts +1 -1
- package/src/palettes/inspect.defs.colors.neutral-arch.test.ts +98 -30
- package/src/palettes/inspect.defs.colors.neutral-user.test.ts +98 -30
- package/src/palettes/inspect.defs.colors.warm-arch.test.ts +98 -30
- package/src/palettes/inspect.defs.colors.warm-user.test.ts +98 -30
- package/src/palettes/show-colors.test.ts +2 -1
- package/src/palettes/testkit.ts +3 -1
- package/src/popover/index.tsx +24 -15
- package/src/popover/mobile-popover-context.tsx +1 -1
- package/src/popover/modifiers.tsx +1 -1
- package/src/popover/popup-modifiers-context.ts +1 -2
- package/src/rich-input-loader.tsx +1 -1
- package/src/select/components/menu-list-virtua.tsx +15 -16
- package/src/select/components/menu-list-virtualized.tsx +26 -29
- package/src/select/components/menu.tsx +3 -3
- package/src/select/components/option.tsx +0 -1
- package/src/select/index.tsx +2 -1
- package/src/select/reflection.ts +4 -5
- package/src/select/select-in-popover.tsx +1 -3
- package/src/select/select.tsx +5 -3
- package/src/select/styles.ts +1 -7
- package/src/select/util.ts +2 -2
- package/src/thematic.tsx +0 -1
- package/src/theme-provider.test.tsx +1 -1
- package/src/theming.generated.css +118 -58
- package/src/theming.generated.ts +135 -58
- package/src/type-badge.tsx +1 -2
- package/src/use-on-screen-keyboard-data.tsx +1 -1
- package/src/with-data.tsx +1 -1
|
@@ -23,64 +23,97 @@ const PrefixedInputNumber = forwardRef<HTMLInputElement, InputNumberPropsAny>(fu
|
|
|
23
23
|
|
|
24
24
|
const inputNumberStyles = css`
|
|
25
25
|
${{
|
|
26
|
-
"& .ant-input-number": {
|
|
26
|
+
":where(&) .ant-input-number": {
|
|
27
27
|
boxSizing: "border-box",
|
|
28
28
|
position: "relative",
|
|
29
29
|
display: "inline-flex",
|
|
30
30
|
alignItems: "stretch",
|
|
31
31
|
width: "90px",
|
|
32
|
+
},
|
|
33
|
+
"& .ant-input-number": {
|
|
32
34
|
height: "auto",
|
|
33
35
|
border: "none",
|
|
34
36
|
...textStyles.regular,
|
|
35
37
|
backgroundColor: themeVars.transparent,
|
|
36
38
|
},
|
|
37
|
-
"& .ant-input-number-input-wrap": {
|
|
39
|
+
":where(&) .ant-input-number-input-wrap": {
|
|
38
40
|
flex: 1,
|
|
39
41
|
minWidth: 0,
|
|
40
42
|
},
|
|
41
|
-
"& .ant-input-number-input": {
|
|
42
|
-
...inputOverrides.main,
|
|
43
|
+
":where(&) .ant-input-number-input": {
|
|
43
44
|
boxSizing: "border-box",
|
|
44
45
|
width: "100%",
|
|
45
46
|
height: "100%",
|
|
46
47
|
appearance: "textfield",
|
|
47
48
|
},
|
|
48
|
-
"& .ant-input-number-input
|
|
49
|
-
|
|
49
|
+
"& .ant-input-number-input": {
|
|
50
|
+
...inputOverrides.main,
|
|
50
51
|
},
|
|
51
|
-
"& .ant-input-number-input
|
|
52
|
-
|
|
53
|
-
appearance: "none",
|
|
52
|
+
":where(&) .ant-input-number-input:placeholder-shown": {
|
|
53
|
+
textOverflow: "ellipsis",
|
|
54
54
|
},
|
|
55
|
-
"& .ant-input-number-
|
|
55
|
+
":where(&) .ant-input-number-input::-webkit-inner-spin-button, :where(&) .ant-input-number-input::-webkit-outer-spin-button":
|
|
56
|
+
{
|
|
57
|
+
margin: 0,
|
|
58
|
+
appearance: "none",
|
|
59
|
+
},
|
|
60
|
+
":where(&) .ant-input-number-handler-wrap": {
|
|
56
61
|
position: "absolute",
|
|
57
|
-
top: 1,
|
|
58
|
-
bottom: 1,
|
|
59
|
-
right: 1,
|
|
60
62
|
width: 22,
|
|
61
|
-
backgroundColor: themeVars.transparent,
|
|
62
|
-
background: themeVars.transparent,
|
|
63
|
-
// antd hid the stepper arrows until hover/focus; reproduce that (dropped with the vendored CSS)
|
|
64
63
|
opacity: 0,
|
|
65
64
|
transition: `opacity ${transitionDuration.normal} linear ${transitionDuration.faster}`,
|
|
66
65
|
},
|
|
67
|
-
"& .ant-input-number-handler-wrap:hover .ant-input-number-handler": {
|
|
66
|
+
":where(&) .ant-input-number-handler-wrap:hover .ant-input-number-handler": {
|
|
68
67
|
height: "40%",
|
|
69
68
|
},
|
|
70
|
-
"& .ant-input-number:hover .ant-input-number-handler-wrap, & .ant-input-number-focused .ant-input-number-handler-wrap":
|
|
69
|
+
":where(&) .ant-input-number:hover .ant-input-number-handler-wrap, :where(&) .ant-input-number-focused .ant-input-number-handler-wrap":
|
|
71
70
|
{
|
|
72
71
|
opacity: 1,
|
|
73
72
|
},
|
|
74
|
-
"& .ant-input-number-
|
|
75
|
-
"& .ant-input-number-handler-up, & .ant-input-number-handler-down": {
|
|
73
|
+
":where(&) .ant-input-number-handler-up, :where(&) .ant-input-number-handler-down": {
|
|
76
74
|
cursor: "pointer",
|
|
77
75
|
},
|
|
78
|
-
"& .ant-input-number-handler-up:hover, & .ant-input-number-handler-down:hover": {
|
|
76
|
+
":where(&) .ant-input-number-handler-up:hover, :where(&) .ant-input-number-handler-down:hover": {
|
|
79
77
|
height: "60% !important",
|
|
80
78
|
},
|
|
81
|
-
"& .ant-input-number-handler-up-disabled, & .ant-input-number-handler-down-disabled": {
|
|
79
|
+
":where(&) .ant-input-number-handler-up-disabled, :where(&) .ant-input-number-handler-down-disabled": {
|
|
82
80
|
cursor: "not-allowed",
|
|
83
81
|
},
|
|
82
|
+
":where(&) .ant-input-number-handler-up-inner, :where(&) .ant-input-number-handler-down-inner": {
|
|
83
|
+
position: "absolute",
|
|
84
|
+
right: 4,
|
|
85
|
+
width: 12,
|
|
86
|
+
height: 12,
|
|
87
|
+
lineHeight: "12px",
|
|
88
|
+
transition: `all ${transitionDuration.faster} linear`,
|
|
89
|
+
userSelect: "none",
|
|
90
|
+
},
|
|
91
|
+
":where(&) .ant-input-number-handler-up-inner": {
|
|
92
|
+
top: "50%",
|
|
93
|
+
marginTop: -5,
|
|
94
|
+
},
|
|
95
|
+
":where(&) .ant-input-number-handler-down-inner": {
|
|
96
|
+
top: "50%",
|
|
97
|
+
transform: "translateY(-50%)",
|
|
98
|
+
},
|
|
99
|
+
":where(&) .ant-input-number-handler": {
|
|
100
|
+
position: "relative",
|
|
101
|
+
display: "block",
|
|
102
|
+
width: "100%",
|
|
103
|
+
height: "50%",
|
|
104
|
+
overflow: "hidden",
|
|
105
|
+
lineHeight: 0,
|
|
106
|
+
textAlign: "center",
|
|
107
|
+
transition: `all ${transitionDuration.faster} linear`,
|
|
108
|
+
},
|
|
109
|
+
"& .ant-input-number-handler-wrap": {
|
|
110
|
+
top: 1,
|
|
111
|
+
bottom: 1,
|
|
112
|
+
right: 1,
|
|
113
|
+
backgroundColor: themeVars.transparent,
|
|
114
|
+
background: themeVars.transparent,
|
|
115
|
+
},
|
|
116
|
+
"& .ant-input-number-focused": {boxShadow: "none"},
|
|
84
117
|
"& .ant-input-number-handler-up-disabled .ant-input-number-handler-up-inner, & .ant-input-number-handler-down-disabled .ant-input-number-handler-down-inner":
|
|
85
118
|
{
|
|
86
119
|
color: themeVars.disabledTextColor,
|
|
@@ -101,33 +134,10 @@ const inputNumberStyles = css`
|
|
|
101
134
|
},
|
|
102
135
|
"& .ant-input-number-handler-up-inner, & .ant-input-number-handler-down-inner": {
|
|
103
136
|
color: themeVars.iconColor,
|
|
104
|
-
position: "absolute",
|
|
105
|
-
right: 4,
|
|
106
|
-
width: 12,
|
|
107
|
-
height: 12,
|
|
108
|
-
lineHeight: "12px",
|
|
109
|
-
transition: `all ${transitionDuration.faster} linear`,
|
|
110
|
-
userSelect: "none",
|
|
111
|
-
},
|
|
112
|
-
"& .ant-input-number-handler-up-inner": {
|
|
113
|
-
top: "50%",
|
|
114
|
-
marginTop: -5,
|
|
115
|
-
},
|
|
116
|
-
"& .ant-input-number-handler-down-inner": {
|
|
117
|
-
top: "50%",
|
|
118
|
-
transform: "translateY(-50%)",
|
|
119
137
|
},
|
|
120
138
|
"& .ant-input-number-handler": {
|
|
121
|
-
position: "relative",
|
|
122
|
-
display: "block",
|
|
123
|
-
width: "100%",
|
|
124
|
-
height: "50%",
|
|
125
|
-
overflow: "hidden",
|
|
126
139
|
color: themeVars.iconColor,
|
|
127
|
-
lineHeight: 0,
|
|
128
|
-
textAlign: "center",
|
|
129
140
|
borderLeft: themeVars.borderSolidSeparator,
|
|
130
|
-
transition: `all ${transitionDuration.faster} linear`,
|
|
131
141
|
"&:active": {
|
|
132
142
|
backgroundColor: themeVars.transparent,
|
|
133
143
|
},
|
package/src/antd/styles.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {border, layout, shadows, space, textStyles, themeVars, transitions} from
|
|
|
5
5
|
const inputVariables = {
|
|
6
6
|
default: {
|
|
7
7
|
"--input-border": `${themeVars.inputBorderColor} inset`,
|
|
8
|
-
"--input-hover-border":
|
|
8
|
+
"--input-hover-border": `${themeVars.inputBorderHoverColor} inset`,
|
|
9
9
|
"--input-focus-border": `0 0 0 1px ${themeVars.colorAccentStrokeFocus} inset`,
|
|
10
10
|
"--input-focus-shadow": `0 0 0 2px ${themeVars.colorAccentStroke}`,
|
|
11
11
|
},
|
|
@@ -40,7 +40,7 @@ export const inputOverrides = {
|
|
|
40
40
|
},
|
|
41
41
|
},
|
|
42
42
|
hover: {
|
|
43
|
-
boxShadow: `var(--input-hover-border,
|
|
43
|
+
boxShadow: `var(--input-hover-border, ${themeVars.inputBorderHoverColor}) !important`,
|
|
44
44
|
transition: `box-shadow ${transitions.faster}`,
|
|
45
45
|
},
|
|
46
46
|
focus: {
|
|
@@ -69,10 +69,12 @@ export const inputStyles = css`
|
|
|
69
69
|
}
|
|
70
70
|
${{
|
|
71
71
|
...textStyles.regular,
|
|
72
|
-
"& .ant-input, & .ant-input-affix-wrapper, & .ant-input-group-wrapper, & .ant-input-wrapper":
|
|
72
|
+
":where(&) .ant-input, :where(&) .ant-input-affix-wrapper, :where(&) .ant-input-group-wrapper, :where(&) .ant-input-wrapper":
|
|
73
|
+
{
|
|
74
|
+
boxSizing: "border-box",
|
|
75
|
+
},
|
|
76
|
+
":where(&) .ant-input-affix-wrapper": {
|
|
73
77
|
boxSizing: "border-box",
|
|
74
|
-
},
|
|
75
|
-
"& .ant-input-affix-wrapper": {
|
|
76
78
|
display: "inline-flex",
|
|
77
79
|
alignItems: "center",
|
|
78
80
|
width: "100%",
|
|
@@ -83,40 +85,40 @@ export const inputStyles = css`
|
|
|
83
85
|
boxShadow: "none",
|
|
84
86
|
backgroundColor: themeVars.transparent,
|
|
85
87
|
},
|
|
86
|
-
"& .ant-input-affix-wrapper > input.ant-input": {
|
|
88
|
+
":where(&) .ant-input-affix-wrapper > input.ant-input": {
|
|
87
89
|
minWidth: 0,
|
|
88
90
|
flex: 1,
|
|
89
91
|
padding: "0 12px",
|
|
90
92
|
border: "inherit",
|
|
91
93
|
outline: "inherit",
|
|
92
94
|
},
|
|
93
|
-
"& .ant-input-prefix, & .ant-input-suffix": {
|
|
95
|
+
":where(&) .ant-input-prefix, :where(&) .ant-input-suffix": {
|
|
94
96
|
display: "flex",
|
|
95
97
|
flex: "none",
|
|
96
98
|
alignItems: "center",
|
|
97
99
|
},
|
|
98
100
|
// antd source: spacing between adjacent icons when prefix/suffix holds multiple nodes.
|
|
99
|
-
"& .ant-input-prefix > *:not(:last-child), & .ant-input-suffix > *:not(:last-child)": {
|
|
101
|
+
":where(&) .ant-input-prefix > *:not(:last-child), :where(&) .ant-input-suffix > *:not(:last-child)": {
|
|
100
102
|
marginRight: space.s8,
|
|
101
103
|
},
|
|
102
|
-
"& .ant-input-suffix": {
|
|
104
|
+
":where(&) .ant-input-suffix": {
|
|
103
105
|
marginLeft: space.s6,
|
|
104
106
|
},
|
|
105
|
-
"& .ant-input-clear-icon": {
|
|
107
|
+
":where(&) .ant-input-clear-icon": {
|
|
106
108
|
display: "inline-flex",
|
|
107
109
|
alignItems: "center",
|
|
108
110
|
color: themeVars.iconColor,
|
|
109
111
|
cursor: "pointer",
|
|
110
112
|
lineHeight: 1,
|
|
111
113
|
},
|
|
112
|
-
"& .ant-input-clear-icon-hidden": {
|
|
114
|
+
":where(&) .ant-input-clear-icon-hidden": {
|
|
113
115
|
visibility: "hidden",
|
|
114
116
|
},
|
|
115
|
-
"& .ant-input-group-wrapper": {
|
|
117
|
+
":where(&) .ant-input-group-wrapper": {
|
|
116
118
|
display: "inline-block",
|
|
117
119
|
width: "100%",
|
|
118
120
|
},
|
|
119
|
-
"& .ant-input-wrapper.ant-input-group": {
|
|
121
|
+
":where(&) .ant-input-wrapper.ant-input-group": {
|
|
120
122
|
display: "inline-flex",
|
|
121
123
|
width: "100%",
|
|
122
124
|
alignItems: "stretch",
|
|
@@ -130,9 +132,8 @@ export const inputStyles = css`
|
|
|
130
132
|
"&:hover": inputOverrides.hover,
|
|
131
133
|
"&:focus": inputOverrides.focus,
|
|
132
134
|
},
|
|
133
|
-
"& .ant-input-group": {borderSpacing: 1, ...textStyles.regular},
|
|
134
|
-
"& .ant-input": {
|
|
135
|
-
...inputOverrides.main,
|
|
135
|
+
":where(&) .ant-input-group": {borderSpacing: 1, ...textStyles.regular},
|
|
136
|
+
":where(&) .ant-input": {
|
|
136
137
|
// antd source: .ant-input { width: 100%; min-width: 0 } — without it, bare <AntInput>
|
|
137
138
|
// doesn't fill its container and can't shrink inside a flex parent. AutoComplete's
|
|
138
139
|
// .ant-select-selection-search .ant-input rule (two-class selector) beats this on
|
|
@@ -140,8 +141,11 @@ export const inputStyles = css`
|
|
|
140
141
|
width: "100%",
|
|
141
142
|
minWidth: 0,
|
|
142
143
|
},
|
|
144
|
+
"& .ant-input": {
|
|
145
|
+
...inputOverrides.main,
|
|
146
|
+
},
|
|
143
147
|
// antd source: long placeholders get ellipsis instead of wrap-clip.
|
|
144
|
-
"& .ant-input:placeholder-shown": {
|
|
148
|
+
":where(&) .ant-input:placeholder-shown": {
|
|
145
149
|
textOverflow: "ellipsis",
|
|
146
150
|
},
|
|
147
151
|
// bordered={false} → wrap with `ant-input-borderless` class; strip the box-shadow ring + bg.
|
|
@@ -155,7 +159,7 @@ export const inputStyles = css`
|
|
|
155
159
|
// antd source: inner input inside affix-wrapper must not paint its own focus ring —
|
|
156
160
|
// the wrapper owns the visual focus state. Without this prefix/suffix usage shows a
|
|
157
161
|
// double ring.
|
|
158
|
-
"& .ant-input-affix-wrapper > .ant-input:focus": {
|
|
162
|
+
":where(&) .ant-input-affix-wrapper > .ant-input:focus": {
|
|
159
163
|
boxShadow: "none !important",
|
|
160
164
|
},
|
|
161
165
|
"& .ant-input-status-error": inputVariables.error,
|
|
@@ -170,18 +174,22 @@ export const inputStyles = css`
|
|
|
170
174
|
"& .ant-input-affix-wrapper:hover .ant-input:not(.ant-input-disabled)": {
|
|
171
175
|
borderColor: "transparent",
|
|
172
176
|
},
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
// vertical-align: bottom matches the baseline of a single-line <input> next to it.
|
|
177
|
+
// Textarea padding must beat inputOverrides.main's zero vertical padding so rc-textarea
|
|
178
|
+
// autosize measures the same row height as the rendered control.
|
|
176
179
|
"& textarea.ant-input": {
|
|
177
180
|
paddingTop: space.s8,
|
|
178
181
|
paddingBottom: space.s8,
|
|
179
|
-
|
|
182
|
+
},
|
|
183
|
+
// antd source: textarea defaults — max-width prevents user-resize from blowing out the
|
|
184
|
+
// container, and vertical-align: bottom matches the baseline of a single-line <input> next to it.
|
|
185
|
+
":where(&) textarea.ant-input": {
|
|
180
186
|
maxWidth: "100%",
|
|
181
187
|
verticalAlign: "bottom",
|
|
182
188
|
},
|
|
183
189
|
"&& input:hover:not(:focus):not(:disabled), && textarea:hover:not(:focus):not(:disabled), && .ant-input:hover:not(:focus):not(:disabled)":
|
|
184
190
|
inputOverrides.hover,
|
|
191
|
+
"&& .ant-input-affix-wrapper > input.ant-input:focus, && .ant-input-affix-wrapper > input.ant-input:active":
|
|
192
|
+
inputOverrides.focus,
|
|
185
193
|
"&& input:focus, && textarea:focus, && input:active, && textarea:active": inputOverrides.focus,
|
|
186
194
|
"&& .ant-input-disabled, && .ant-input-disabled:hover, && .ant-input-disabled:focus, && .ant-input-disabled:active":
|
|
187
195
|
inputOverrides.disabled,
|
package/src/antd/tabs.tsx
CHANGED
|
@@ -16,16 +16,16 @@ const PrefixedTabs = forwardRef<HTMLDivElement, TabsPropsAny>(function PrefixedT
|
|
|
16
16
|
export const tabsStyles = css`
|
|
17
17
|
${{
|
|
18
18
|
width: "100%",
|
|
19
|
-
"& .ant-tabs": {
|
|
19
|
+
":where(&) .ant-tabs": {
|
|
20
20
|
boxSizing: "border-box",
|
|
21
21
|
display: "flex",
|
|
22
22
|
overflow: "visible",
|
|
23
23
|
width: "100%",
|
|
24
24
|
},
|
|
25
|
-
"& .ant-tabs-top, & .ant-tabs-bottom": {
|
|
25
|
+
":where(&) .ant-tabs-top, :where(&) .ant-tabs-bottom": {
|
|
26
26
|
flexDirection: "column",
|
|
27
27
|
},
|
|
28
|
-
"& .ant-tabs-nav": {
|
|
28
|
+
":where(&) .ant-tabs-nav": {
|
|
29
29
|
display: "flex",
|
|
30
30
|
flex: "none",
|
|
31
31
|
alignItems: "center",
|
|
@@ -41,7 +41,7 @@ export const tabsStyles = css`
|
|
|
41
41
|
content: "''",
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
|
-
"& .ant-tabs-nav-wrap": {
|
|
44
|
+
":where(&) .ant-tabs-nav-wrap": {
|
|
45
45
|
display: "flex",
|
|
46
46
|
flex: "auto",
|
|
47
47
|
overflow: "hidden",
|
|
@@ -53,7 +53,7 @@ export const tabsStyles = css`
|
|
|
53
53
|
marginLeft: space.s12,
|
|
54
54
|
marginRight: space.s12,
|
|
55
55
|
},
|
|
56
|
-
"& .ant-tabs-nav-wrap::before, & .ant-tabs-nav-wrap::after": {
|
|
56
|
+
":where(&) .ant-tabs-nav-wrap::before, :where(&) .ant-tabs-nav-wrap::after": {
|
|
57
57
|
position: "absolute",
|
|
58
58
|
zIndex: 1,
|
|
59
59
|
opacity: 0,
|
|
@@ -61,27 +61,27 @@ export const tabsStyles = css`
|
|
|
61
61
|
content: "''",
|
|
62
62
|
pointerEvents: "none",
|
|
63
63
|
},
|
|
64
|
-
"& .ant-tabs-nav-list": {
|
|
64
|
+
":where(&) .ant-tabs-nav-list": {
|
|
65
65
|
position: "relative",
|
|
66
66
|
display: "flex",
|
|
67
67
|
transition: `transform ${transitions.normal}`,
|
|
68
68
|
},
|
|
69
|
-
"& .ant-tabs-nav-operations": {
|
|
69
|
+
":where(&) .ant-tabs-nav-operations": {
|
|
70
70
|
display: "flex",
|
|
71
71
|
alignSelf: "stretch",
|
|
72
72
|
},
|
|
73
|
-
"& .ant-tabs-nav-operations-hidden": {
|
|
73
|
+
":where(&) .ant-tabs-nav-operations-hidden": {
|
|
74
74
|
position: "absolute",
|
|
75
75
|
visibility: "hidden",
|
|
76
76
|
pointerEvents: "none",
|
|
77
77
|
},
|
|
78
|
-
"& .ant-tabs-nav-more": {
|
|
78
|
+
":where(&) .ant-tabs-nav-more": {
|
|
79
79
|
position: "relative",
|
|
80
80
|
padding: `${space.s8}px ${space.s16}px`,
|
|
81
81
|
backgroundColor: themeVars.transparent,
|
|
82
82
|
border: 0,
|
|
83
83
|
},
|
|
84
|
-
"& .ant-tabs-nav-more::after": {
|
|
84
|
+
":where(&) .ant-tabs-nav-more::after": {
|
|
85
85
|
position: "absolute",
|
|
86
86
|
right: 0,
|
|
87
87
|
bottom: 0,
|
|
@@ -90,13 +90,13 @@ export const tabsStyles = css`
|
|
|
90
90
|
transform: "translateY(100%)",
|
|
91
91
|
content: "''",
|
|
92
92
|
},
|
|
93
|
-
"& .ant-tabs-extra-content": {
|
|
93
|
+
":where(&) .ant-tabs-extra-content": {
|
|
94
94
|
flex: "none",
|
|
95
95
|
},
|
|
96
|
-
"& .ant-tabs-centered .ant-tabs-nav-wrap:not([class*='ant-tabs-nav-wrap-ping'])": {
|
|
96
|
+
":where(&) .ant-tabs-centered .ant-tabs-nav-wrap:not([class*='ant-tabs-nav-wrap-ping'])": {
|
|
97
97
|
justifyContent: "center",
|
|
98
98
|
},
|
|
99
|
-
"& .ant-tabs-ink-bar": {
|
|
99
|
+
":where(&) .ant-tabs-ink-bar": {
|
|
100
100
|
position: "absolute",
|
|
101
101
|
bottom: 0,
|
|
102
102
|
backgroundColor: themeVars.colorAccent,
|
|
@@ -104,12 +104,12 @@ export const tabsStyles = css`
|
|
|
104
104
|
pointerEvents: "none",
|
|
105
105
|
transition: `left ${transitions.faster}, right ${transitions.faster}, width ${transitions.faster}`,
|
|
106
106
|
},
|
|
107
|
-
"& .ant-tabs-tab, & .ant-tabs-tab:hover, & .ant-tabs-tab-btn:active, & .ant-tabs-tabpane, & .ant-tabs-tab-active .ant-tabs-tab-btn":
|
|
107
|
+
":where(&) .ant-tabs-tab, :where(&) .ant-tabs-tab:hover, :where(&) .ant-tabs-tab-btn:active, :where(&) .ant-tabs-tabpane, :where(&) .ant-tabs-tab-active .ant-tabs-tab-btn":
|
|
108
108
|
{
|
|
109
109
|
...textStyles.regular,
|
|
110
110
|
textShadow: "none",
|
|
111
111
|
},
|
|
112
|
-
"& .ant-tabs-tab": {
|
|
112
|
+
":where(&) .ant-tabs-tab": {
|
|
113
113
|
position: "relative",
|
|
114
114
|
display: "inline-flex",
|
|
115
115
|
alignItems: "center",
|
|
@@ -118,53 +118,53 @@ export const tabsStyles = css`
|
|
|
118
118
|
cursor: "pointer",
|
|
119
119
|
outline: "none",
|
|
120
120
|
},
|
|
121
|
-
"& .ant-tabs-tab + .ant-tabs-tab": {
|
|
121
|
+
":where(&) .ant-tabs-tab + .ant-tabs-tab": {
|
|
122
122
|
margin: `0 ${space.s8}px 0 0`,
|
|
123
123
|
},
|
|
124
|
-
"& .ant-tabs-tab-btn": {
|
|
124
|
+
":where(&) .ant-tabs-tab-btn": {
|
|
125
125
|
outline: "none",
|
|
126
126
|
transition: `all ${transitions.slow}`,
|
|
127
127
|
},
|
|
128
|
-
"& .ant-tabs-tab-active .ant-tabs-tab-btn": {
|
|
128
|
+
":where(&) .ant-tabs-tab-active .ant-tabs-tab-btn": {
|
|
129
129
|
color: themeVars.colorAccent,
|
|
130
130
|
},
|
|
131
|
-
"& .ant-tabs-content-holder": {
|
|
131
|
+
":where(&) .ant-tabs-content-holder": {
|
|
132
132
|
flex: "auto",
|
|
133
133
|
minWidth: 0,
|
|
134
134
|
minHeight: 0,
|
|
135
135
|
},
|
|
136
|
-
"& .ant-tabs-content": {
|
|
136
|
+
":where(&) .ant-tabs-content": {
|
|
137
137
|
position: "relative",
|
|
138
138
|
display: "flex",
|
|
139
139
|
width: "100%",
|
|
140
140
|
},
|
|
141
|
-
"& .ant-tabs-tabpane": {
|
|
141
|
+
":where(&) .ant-tabs-tabpane": {
|
|
142
142
|
flex: "none",
|
|
143
143
|
width: "100%",
|
|
144
144
|
outline: "none",
|
|
145
145
|
},
|
|
146
|
-
"& .ant-tabs-tabpane-hidden": {
|
|
146
|
+
":where(&) .ant-tabs-tabpane-hidden": {
|
|
147
147
|
display: "none",
|
|
148
148
|
},
|
|
149
|
-
"& .ant-tabs-switch-appear, & .ant-tabs-switch-enter": {
|
|
149
|
+
":where(&) .ant-tabs-switch-appear, :where(&) .ant-tabs-switch-enter": {
|
|
150
150
|
transition: "none",
|
|
151
151
|
},
|
|
152
|
-
"& .ant-tabs-switch-appear-start, & .ant-tabs-switch-enter-start": {
|
|
152
|
+
":where(&) .ant-tabs-switch-appear-start, :where(&) .ant-tabs-switch-enter-start": {
|
|
153
153
|
opacity: 0,
|
|
154
154
|
},
|
|
155
|
-
"& .ant-tabs-switch-appear-active, & .ant-tabs-switch-enter-active": {
|
|
155
|
+
":where(&) .ant-tabs-switch-appear-active, :where(&) .ant-tabs-switch-enter-active": {
|
|
156
156
|
opacity: 1,
|
|
157
157
|
transition: `opacity ${transitions.slow}`,
|
|
158
158
|
},
|
|
159
|
-
"& .ant-tabs-switch-leave": {
|
|
159
|
+
":where(&) .ant-tabs-switch-leave": {
|
|
160
160
|
position: "absolute",
|
|
161
161
|
inset: 0,
|
|
162
162
|
transition: "none",
|
|
163
163
|
},
|
|
164
|
-
"& .ant-tabs-switch-leave-start": {
|
|
164
|
+
":where(&) .ant-tabs-switch-leave-start": {
|
|
165
165
|
opacity: 1,
|
|
166
166
|
},
|
|
167
|
-
"& .ant-tabs-switch-leave-active": {
|
|
167
|
+
":where(&) .ant-tabs-switch-leave-active": {
|
|
168
168
|
opacity: 0,
|
|
169
169
|
transition: `opacity ${transitions.slow}`,
|
|
170
170
|
},
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import {css} from "@linaria/core";
|
|
2
|
-
import fromPairs from "lodash/fromPairs";
|
|
3
2
|
import type {FC} from "react";
|
|
4
3
|
import {lazy, Suspense} from "react";
|
|
5
4
|
|
|
6
5
|
import {AppIconWrapper} from "./app-icon-wrapper";
|
|
7
6
|
import {alpha, iconSize, layout} from "./design-system";
|
|
8
|
-
import {isFlagPresent} from "./flags";
|
|
9
7
|
import {Icon} from "./icons/icon";
|
|
10
8
|
import {useTheme} from "./theme-provider";
|
|
11
9
|
import {useIsPhone} from "./use-is-phone";
|
|
@@ -94,7 +92,7 @@ type UglyExternalIconProps = Omit<UglyExternalIconImplProps, "appIconsLookup">;
|
|
|
94
92
|
|
|
95
93
|
const UglyExternalIcon = lazy(async () => {
|
|
96
94
|
const appIcons = await import("./app-icons.json");
|
|
97
|
-
const appIconsLookup =
|
|
95
|
+
const appIconsLookup = Object.fromEntries(
|
|
98
96
|
appIcons.default.flatMap((appIcon) => appIcon.short_names.map((shortName) => [shortName, appIcon]))
|
|
99
97
|
);
|
|
100
98
|
|
|
@@ -146,12 +144,10 @@ export const AppIcon: FC<AppIconProps> = ({icon, color: neutralColor, isSelected
|
|
|
146
144
|
const isPhone = useIsPhone();
|
|
147
145
|
const defaultIconSize = isPhone ? layout.mobileSidebarIconSize : layout.newMenuIconSize;
|
|
148
146
|
const {iconSize = defaultIconSize, containerSize = defaultIconSize} = rest;
|
|
149
|
-
const {fg
|
|
150
|
-
|
|
151
|
-
const bgColor = !isFlagPresent("no-sidebar-app-icon-bg") ? alpha(fg, 0.2) : bg;
|
|
147
|
+
const {fg} = theme.fns.icon(neutralColor);
|
|
152
148
|
|
|
153
149
|
return (
|
|
154
|
-
<AppIconWrapper color={
|
|
150
|
+
<AppIconWrapper color={alpha(fg, 0.2)} borderless={isSelected} containerSize={containerSize}>
|
|
155
151
|
<AppIconWithFallback name={icon} color={fg} colorProcessed containerSize={containerSize} iconSize={iconSize} />
|
|
156
152
|
</AppIconWrapper>
|
|
157
153
|
);
|
package/src/app-icon-wrapper.tsx
CHANGED
|
@@ -3,20 +3,12 @@ import cn from "classnames";
|
|
|
3
3
|
import type {ReactNode} from "react";
|
|
4
4
|
|
|
5
5
|
import {border, layout} from "./design-system";
|
|
6
|
-
import {isFlagPresent} from "./flags";
|
|
7
|
-
import {useTheme} from "./theme-provider";
|
|
8
6
|
import {useIsPhone} from "./use-is-phone";
|
|
9
7
|
|
|
10
8
|
const appIconContainerStyle = css`
|
|
11
9
|
border-radius: ${border.radius4}px;
|
|
12
10
|
`;
|
|
13
11
|
|
|
14
|
-
const appIconGradientStyle = css`
|
|
15
|
-
${{
|
|
16
|
-
backgroundImage: "linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0))",
|
|
17
|
-
}}
|
|
18
|
-
`;
|
|
19
|
-
|
|
20
12
|
export const AppIconWrapper = ({
|
|
21
13
|
children,
|
|
22
14
|
color,
|
|
@@ -28,16 +20,12 @@ export const AppIconWrapper = ({
|
|
|
28
20
|
borderless?: boolean;
|
|
29
21
|
containerSize?: number;
|
|
30
22
|
}) => {
|
|
31
|
-
const theme = useTheme();
|
|
32
23
|
const isPhone = useIsPhone();
|
|
33
24
|
const {containerSize = isPhone ? layout.mobileSidebarIconSize : layout.newMenuIconSize} = rest;
|
|
34
25
|
return (
|
|
35
26
|
<div
|
|
36
27
|
style={{backgroundColor: borderless ? "transparent" : color, width: containerSize, height: containerSize}}
|
|
37
|
-
className={cn(
|
|
38
|
-
appIconContainerStyle,
|
|
39
|
-
!borderless && isFlagPresent("no-sidebar-app-icon-bg") && theme.mode === "dark" && appIconGradientStyle
|
|
40
|
-
)}
|
|
28
|
+
className={cn(appIconContainerStyle)}
|
|
41
29
|
>
|
|
42
30
|
{children}
|
|
43
31
|
</div>
|
package/src/breadcrumb.tsx
CHANGED
|
@@ -64,10 +64,14 @@ const liReset = css`
|
|
|
64
64
|
padding: 0;
|
|
65
65
|
`;
|
|
66
66
|
|
|
67
|
+
const separatorIconCss = css`
|
|
68
|
+
--fibery-icon-size: var(--breadcrumb-separator-size, 16px);
|
|
69
|
+
`;
|
|
70
|
+
|
|
67
71
|
export const BreadcrumbSeparator = ({children, className, ...props}: React.ComponentProps<"li">) => {
|
|
68
72
|
return (
|
|
69
73
|
<li role="presentation" aria-hidden="true" className={cx(liReset, className)} {...props}>
|
|
70
|
-
{children ?? <ArrowRight color={breadcrumbColor}
|
|
74
|
+
{children ?? <ArrowRight color={breadcrumbColor} className={separatorIconCss} />}
|
|
71
75
|
</li>
|
|
72
76
|
);
|
|
73
77
|
};
|
package/src/color-filter.ts
CHANGED
|
@@ -65,7 +65,7 @@ export function makeColorFilter(spec: ColorFilterSpec | undefined): ColorFilter
|
|
|
65
65
|
if (!color) {
|
|
66
66
|
return color;
|
|
67
67
|
}
|
|
68
|
-
//
|
|
68
|
+
// eslint-disable-next-line no-param-reassign
|
|
69
69
|
color = spec.swatches?.[color.toUpperCase()] ?? color;
|
|
70
70
|
|
|
71
71
|
const parsed = oklchFrom(color);
|
package/src/color-utils.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// oxlint-disable typescript/consistent-type-imports
|
|
2
|
-
import {cssFromUnsafe, getColorDistance, getLuminance, isValidColor} from "./color-utils";
|
|
2
|
+
import {cssFromUnsafe, getColorDistance, getLuminance, isValidColor, invalidColorFallback} from "./color-utils";
|
|
3
3
|
|
|
4
4
|
describe("color-utils", () => {
|
|
5
5
|
describe("cssFromUnsafe", () => {
|
|
@@ -21,7 +21,7 @@ describe("color-utils", () => {
|
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
it("returns fallback for invalid color", () => {
|
|
24
|
-
expect(cssFromUnsafe("invalid")).
|
|
24
|
+
expect(cssFromUnsafe("invalid")).toEqual(invalidColorFallback);
|
|
25
25
|
});
|
|
26
26
|
});
|
|
27
27
|
|
package/src/color-utils.ts
CHANGED
|
@@ -27,8 +27,8 @@ export const oklchFrom = converter("oklch");
|
|
|
27
27
|
const mapToSrgb = toGamut("rgb", "oklch");
|
|
28
28
|
|
|
29
29
|
export const isValidColor = (color: string) => parse(color) !== undefined;
|
|
30
|
-
|
|
31
|
-
export function colorFromUnsafe(color: string, fallback =
|
|
30
|
+
export const invalidColorFallback = "rgb(94, 94, 94)";
|
|
31
|
+
export function colorFromUnsafe(color: string, fallback = invalidColorFallback): Color {
|
|
32
32
|
const parsed = parse(resolveColorArg(color, "colorFromUnsafe") ?? "") ?? parse(fallback)!;
|
|
33
33
|
if (!parsed) {
|
|
34
34
|
throw new Error(`Failed to parse fallback color ${fallback}`);
|
package/src/comment.tsx
CHANGED
|
@@ -89,9 +89,9 @@ export const actionsClassName = css`
|
|
|
89
89
|
right: 0;
|
|
90
90
|
z-index: 1;
|
|
91
91
|
padding: ${space.s2 + 1}px;
|
|
92
|
-
background-color: ${themeVars.
|
|
92
|
+
background-color: ${themeVars.colorBgFloatingPanel};
|
|
93
93
|
border-radius: ${border.radius8}px;
|
|
94
|
-
box-shadow: ${themeVars.
|
|
94
|
+
box-shadow: ${themeVars.shadowFloatingPanel};
|
|
95
95
|
gap: ${space.s2}px;
|
|
96
96
|
|
|
97
97
|
.${defaultCommentStyle}:hover & {
|
package/src/copy-to-clipboard.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
function checkClipboard() {
|
|
2
|
+
if (!navigator.clipboard) {
|
|
3
|
+
throw new Error("Clipboard disabled by browser permissions policy");
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const copyToClipboard = async (text: string) => {
|
|
8
|
+
checkClipboard();
|
|
9
|
+
await navigator.clipboard.writeText(text);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const copyUrlToClipboard = async ({url, label}: {url: string; label?: string}) => {
|
|
13
|
+
checkClipboard();
|
|
3
14
|
const htmlString = `<a href="${url}" target="_blank">${label || url}</a>`;
|
|
4
15
|
|
|
5
|
-
|
|
16
|
+
await navigator.clipboard.write([
|
|
6
17
|
new ClipboardItem({
|
|
7
18
|
"text/html": new Blob([htmlString], {type: "text/html"}),
|
|
8
19
|
"text/plain": url,
|
package/src/count-badge.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import {fontWeight, space, themeVars} from "./design-system";
|
|
|
7
7
|
type Props = {
|
|
8
8
|
className?: string;
|
|
9
9
|
count: number;
|
|
10
|
+
limit?: number;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
const countStyle = css`
|
|
@@ -34,17 +35,8 @@ const warningStyle = css`
|
|
|
34
35
|
color: ${themeVars.textColor};
|
|
35
36
|
`;
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
);
|
|
40
|
-
const COUNT_BADGE_LIMIT = Number.isInteger(countBadgeLimitOverride) ? countBadgeLimitOverride : 99;
|
|
41
|
-
|
|
42
|
-
export function CountBadge({className, count}: Props) {
|
|
43
|
-
return (
|
|
44
|
-
<span className={cx(countStyle, countBadgeStyle, className)}>
|
|
45
|
-
{count <= COUNT_BADGE_LIMIT ? count : `${COUNT_BADGE_LIMIT}+`}
|
|
46
|
-
</span>
|
|
47
|
-
);
|
|
38
|
+
export function CountBadge({className, count, limit = 99}: Props) {
|
|
39
|
+
return <span className={cx(countStyle, countBadgeStyle, className)}>{count <= limit ? count : `${limit}+`}</span>;
|
|
48
40
|
}
|
|
49
41
|
|
|
50
42
|
export function CountBadgeWithNoLimits({count, warning}: {count: number | string; warning?: boolean}) {
|