@fibery/ui-kit 1.40.4 → 1.42.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 (143) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/eslint.config.mjs +16 -0
  3. package/package.json +10 -9
  4. package/src/a11y-color.test.ts +5 -24
  5. package/src/actions-menu/actions-menu-item.tsx +6 -9
  6. package/src/actions-menu/context-actions-menu.tsx +8 -3
  7. package/src/ai/model.tsx +0 -1
  8. package/src/ai/temperature.tsx +0 -1
  9. package/src/animated-height-container.tsx +3 -3
  10. package/src/antd/index.tsx +3 -0
  11. package/src/antd/input.tsx +0 -1
  12. package/src/antd/styles.ts +9 -9
  13. package/src/app-icon-with-fallback.tsx +5 -5
  14. package/src/app-icon-wrapper.tsx +2 -3
  15. package/src/app-icon.tsx +3 -3
  16. package/src/avatar.tsx +3 -3
  17. package/src/button/base-button.tsx +0 -1
  18. package/src/button/make-button-colors.ts +2 -2
  19. package/src/checkbox.tsx +1 -1
  20. package/src/collapsible-section.tsx +11 -1
  21. package/src/color-utils.test.ts +15 -25
  22. package/src/color-utils.ts +43 -8
  23. package/src/command-menu/index.tsx +1 -0
  24. package/src/context-menu/index.tsx +5 -5
  25. package/src/date-picker/contexts.ts +2 -2
  26. package/src/date-picker/date-range-picker-popup-content.tsx +1 -2
  27. package/src/date-picker/date-range-picker.tsx +29 -31
  28. package/src/date-picker/single-date-picker-popup-content.tsx +1 -2
  29. package/src/date-picker/single-date-picker.tsx +149 -124
  30. package/src/date-picker/types.ts +4 -4
  31. package/src/day-select/iso-week-day-select.tsx +2 -2
  32. package/src/day-select/week-day-select.tsx +2 -2
  33. package/src/delayed.tsx +0 -1
  34. package/src/design-system/alpha.test.ts +59 -0
  35. package/src/design-system/alpha.ts +41 -0
  36. package/src/design-system/animation.ts +10 -0
  37. package/src/design-system/colors-css.test.ts +39 -0
  38. package/src/design-system/colors-css.ts +25 -0
  39. package/src/design-system/colors-js.test.ts +232 -0
  40. package/src/design-system/colors-js.ts +107 -0
  41. package/src/design-system/colors.test.ts +74 -0
  42. package/src/{design-system.colors.ts → design-system/colors.ts} +133 -134
  43. package/src/design-system/date.ts +3 -0
  44. package/src/design-system/layout.ts +106 -0
  45. package/src/design-system/theme.test.ts +94 -0
  46. package/src/design-system/theme.ts +93 -0
  47. package/src/design-system/typography.ts +179 -0
  48. package/src/design-system/vars.test.ts +1679 -0
  49. package/src/design-system/vars.ts +52 -0
  50. package/src/design-system.test.ts +46 -303
  51. package/src/design-system.ts +25 -545
  52. package/src/dropdown-menu/index.tsx +5 -5
  53. package/src/emoji-picker/icon-emoji-picker.tsx +1 -1
  54. package/src/fibermoji-placeholder.tsx +3 -3
  55. package/src/field-container.tsx +11 -2
  56. package/src/file-item/file-icon.tsx +3 -3
  57. package/src/file-item-2.tsx +4 -10
  58. package/src/file-item.tsx +0 -1
  59. package/src/icons/ast/ChatBubble.ts +8 -0
  60. package/src/icons/ast/ChatFloat.ts +8 -0
  61. package/src/icons/ast/ChatSidebar.ts +8 -0
  62. package/src/icons/ast/FileOther.ts +8 -0
  63. package/src/icons/ast/NoBorder.ts +8 -0
  64. package/src/icons/ast/NoFill.ts +8 -0
  65. package/src/icons/ast/index.tsx +6 -0
  66. package/src/icons/react/ChatBubble.tsx +13 -0
  67. package/src/icons/react/ChatFloat.tsx +13 -0
  68. package/src/icons/react/ChatSidebar.tsx +13 -0
  69. package/src/icons/react/FileOther.tsx +13 -0
  70. package/src/icons/react/NoBorder.tsx +13 -0
  71. package/src/icons/react/NoFill.tsx +13 -0
  72. package/src/icons/react/index.tsx +6 -0
  73. package/src/icons/svg/chat-bubble.svg +4 -0
  74. package/src/icons/svg/chat-float.svg +4 -0
  75. package/src/icons/svg/chat-sidebar.svg +4 -0
  76. package/src/icons/svg/file-other.svg +3 -0
  77. package/src/icons/svg/no-border.svg +17 -0
  78. package/src/icons/svg/no-fill.svg +4 -0
  79. package/src/images-gallery/images-gallery.tsx +8 -6
  80. package/src/images-gallery/slide-buttons.tsx +2 -2
  81. package/src/is-iOS.ts +0 -1
  82. package/src/is-in-popup.ts +2 -1
  83. package/src/lists/actions-menu-row-surface.tsx +4 -4
  84. package/src/loading-sausage.tsx +2 -2
  85. package/src/media-query-utils.ts +1 -2
  86. package/src/mobile-keyboard-aware-popup.tsx +2 -2
  87. package/src/modal-menu/modal-menu-content.tsx +2 -2
  88. package/src/number-input/decimal.js +9 -7
  89. package/src/number-input/{number-inline-input-with-autosize.tsx → number-input-inline-with-autosize.tsx} +20 -41
  90. package/src/number-input/number-input-inline.tsx +118 -0
  91. package/src/number-input/{index.test.js → number-input.test.tsx} +38 -43
  92. package/src/number-input/number-input.tsx +63 -121
  93. package/src/number-input/types.ts +19 -0
  94. package/src/number-input/utils.ts +61 -0
  95. package/src/online-users.tsx +2 -2
  96. package/src/palette-generator.test.ts +24 -281
  97. package/src/palette-generator.ts +39 -45
  98. package/src/palettes/_.ts +72 -0
  99. package/src/palettes/slate-arch.colors-snapshot.test.ts +1689 -0
  100. package/src/palettes/slate-arch.ts +188 -0
  101. package/src/palettes/slate-user.colors-snapshot.test.ts +1689 -0
  102. package/src/palettes/slate-user.ts +187 -0
  103. package/src/palettes/warm-arch.colors-snapshot.test.ts +1689 -0
  104. package/src/palettes/warm-arch.ts +222 -0
  105. package/src/palettes/warm-user.colors-snapshot.test.ts +1689 -0
  106. package/src/palettes/warm-user.ts +222 -0
  107. package/src/popover/get-element-ref.ts +28 -0
  108. package/src/popover/index.tsx +232 -333
  109. package/src/popover/{mobile-popup-context.tsx → mobile-popover-context.tsx} +7 -7
  110. package/src/popover/mobile-popover.tsx +169 -0
  111. package/src/popover/modifiers.tsx +2 -2
  112. package/src/popover/popup-stack-context.tsx +8 -9
  113. package/src/root-theme-provider.test.tsx +114 -19
  114. package/src/scale-generator.ts +31 -22
  115. package/src/select/components/menu-list-virtualized.tsx +5 -3
  116. package/src/select/index.tsx +6 -5
  117. package/src/select/select.tsx +36 -38
  118. package/src/select/util.ts +1 -1
  119. package/src/static-palettes.ts +221 -11
  120. package/src/thematic-controls.tsx +6 -6
  121. package/src/thematic-scales.tsx +15 -15
  122. package/src/thematic-state.ts +57 -20
  123. package/src/thematic.tsx +36 -32
  124. package/src/theme-provider.test.tsx +31 -19
  125. package/src/theme-provider.tsx +41 -38
  126. package/src/theme-settings.ts +66 -11
  127. package/src/theme-styles.ts +53 -8
  128. package/src/toast/toast.tsx +1 -2
  129. package/src/toggle.tsx +2 -2
  130. package/src/tooltip.tsx +4 -3
  131. package/src/type-badge.tsx +4 -11
  132. package/src/unit/styles.ts +0 -23
  133. package/src/use-is-phone.tsx +7 -2
  134. package/src/use-on-screen-keyboard-data.tsx +2 -2
  135. package/src/with-data.tsx +4 -3
  136. package/src/workflow-progress-icon.tsx +2 -2
  137. package/.eslintignore +0 -3
  138. package/.eslintrc +0 -14
  139. package/src/__mocks__/createInlineTheme.js +0 -3
  140. package/src/__snapshots__/design-system.test.ts.snap +0 -7265
  141. package/src/create-inline-theme.ts +0 -67
  142. package/src/number-input/index.js +0 -191
  143. package/src/palette.ts +0 -253
@@ -0,0 +1,94 @@
1
+ import {createInlineStyles, getThemeColors, makeThemeApi, ThemeColors} from "./theme";
2
+ import {ThemePalette} from "../palette-generator";
3
+ import {ThemeDefs} from "./colors";
4
+ import {ThemeMode, themeModes} from "../theme-settings";
5
+ import {typedObjectEntries} from "@fibery/helpers/utils/object";
6
+
7
+ describe("select", () => {
8
+ function makeSelect(mode: ThemeMode) {
9
+ return makeThemeApi({key: "smth"} as ThemePalette, {fns: {}} as ThemeDefs, mode).select;
10
+ }
11
+
12
+ test("light theme", () => {
13
+ expect(
14
+ makeSelect("light")({light: "light-value", light2: "light2-value", dark: "dark-value"})
15
+ ).toMatchInlineSnapshot(`"light-value"`);
16
+ });
17
+
18
+ test("dark theme", () => {
19
+ expect(
20
+ makeSelect("dark")({light: "light-value", light2: "light2-value", dark: "dark-value"})
21
+ ).toMatchInlineSnapshot(`"dark-value"`);
22
+ });
23
+
24
+ test("light2 theme", () => {
25
+ expect(
26
+ makeSelect("dark")({light: "light-value", light2: "light2-value", dark: "dark-value"})
27
+ ).toMatchInlineSnapshot(`"dark-value"`);
28
+ });
29
+
30
+ test("light2 theme falls back to light when key is not defined", () => {
31
+ expect(makeSelect("light2")({light: "fallback", dark: "dark"})).toMatchInlineSnapshot(`"fallback"`);
32
+ });
33
+ });
34
+
35
+ test("getThemeColors memoization", () => {
36
+ function getKeys(colors: ThemeColors) {
37
+ const keys = [];
38
+ for (const [key, value] of typedObjectEntries(colors)) {
39
+ // LINT.IfChange("skipMetaKeys")
40
+ if (key === "key" || key === "fns" || key === "select") {
41
+ // LINT.ThenChange(["./theme.ts#skipMetaKeys", "./vars.ts#skipMetaKeys")
42
+ continue;
43
+ }
44
+ if (typeof value === "string") {
45
+ keys.push(key);
46
+ } else {
47
+ const nestedKeys: Record<string, string[]> = {[key]: []};
48
+ for (const [nestedKey] of typedObjectEntries(value)) {
49
+ nestedKeys[key].push(nestedKey);
50
+ }
51
+ keys.push(nestedKeys);
52
+ }
53
+ }
54
+ return keys.sort();
55
+ }
56
+
57
+ const themes = themeModes.map((mode) => getThemeColors(null, mode));
58
+
59
+ // same input → same reference
60
+ themeModes.forEach((mode, i) => {
61
+ expect(getThemeColors(null, mode)).toBe(themes[i]);
62
+ });
63
+
64
+ // different modes → different references
65
+ expect(new Set(themes)).toMatchObject({size: themeModes.length});
66
+
67
+ // different modes → same keys
68
+ expect(new Set(themes.map((theme) => getKeys(theme).join(",")))).toMatchObject({size: 1});
69
+ });
70
+
71
+ describe("createInlineStyles", () => {
72
+ it("maps provided theme to css props", () => {
73
+ const theme = {
74
+ key: "key",
75
+ mode: "light2",
76
+ fns: {getIconColor: (_: string) => "IconColor"} satisfies Partial<ThemeColors["fns"]> as ThemeColors["fns"],
77
+ lights: {opacity5: "light5"} as ThemeColors["lights"],
78
+ shades: {opacity5: "shade5"} as ThemeColors["shades"],
79
+ separators: {opacity5: "separator5"} as ThemeColors["separators"],
80
+ transparent: "rgba(255, 255, 255, 0)",
81
+ colorAI: "rgb(157, 99, 212)",
82
+ } satisfies Partial<ThemeColors> as ThemeColors;
83
+ expect(createInlineStyles(theme)).toMatchInlineSnapshot(`
84
+ {
85
+ "--fibery-color-colorAI": "rgb(157, 99, 212)",
86
+ "--fibery-color-mode": "light2",
87
+ "--fibery-color-transparent": "rgba(255, 255, 255, 0)",
88
+ "--fibery-lights-opacity5": "light5",
89
+ "--fibery-separator-opacity5": "separator5",
90
+ "--fibery-shades-opacity5": "shade5",
91
+ }
92
+ `);
93
+ });
94
+ });
@@ -0,0 +1,93 @@
1
+ import {Colors, makeThemeDefs, pickColors, pickFns, ThemeDefs} from "./colors";
2
+ import {getTypeColors, TypeColors} from "./colors-js";
3
+ import {ThemeMode} from "../theme-settings";
4
+ import {defaultPaletteKey, makeDefaultPalette, ThemePalette} from "../palette-generator";
5
+ import memoize from "lodash/memoize";
6
+ import {makeThemeVars, varPrefix} from "./vars";
7
+ import {typedObjectEntries} from "@fibery/helpers/utils/object";
8
+
9
+ export function makeThemeApi(palette: ThemePalette, defs: ThemeDefs, mode: ThemeMode) {
10
+ return {
11
+ key: `${palette.key}-${mode}`,
12
+ fns: pickFns(defs.fns, mode),
13
+ select<T>(values: {light: T; light2?: T; dark: T}): T {
14
+ if (mode in values) {
15
+ return values[mode]!;
16
+ }
17
+ return values.light;
18
+ },
19
+ };
20
+ }
21
+
22
+ type ThemeApi = ReturnType<typeof makeThemeApi>;
23
+
24
+ // TODO rename into Theme
25
+ export type ThemeColors = ThemeApi & TypeColors & Colors;
26
+
27
+ /**
28
+ * @deprecated do NOT add new consumers in production code.
29
+ * Your helpers from now on are:
30
+ * themeVars (for CSS statics) and
31
+ * useTheme() (for dynamic calculations in js, for canvas)
32
+ */
33
+ export const getThemeColors = memoize(
34
+ (_: string | null, mode: ThemeMode, palette: ThemePalette = makeDefaultPalette()): ThemeColors => {
35
+ const defs = makeThemeDefs(palette);
36
+
37
+ return {
38
+ ...makeThemeApi(palette, defs, mode),
39
+ ...getTypeColors(palette.accent[9], mode),
40
+ ...pickColors(defs, mode),
41
+ };
42
+ },
43
+ (_, mode, palette) => `${palette?.key ?? defaultPaletteKey}-${mode}`
44
+ );
45
+
46
+ export const themeVars = makeThemeVars(getThemeColors(null, "light"));
47
+
48
+ export type ThemeStyles = Record<string, string>;
49
+
50
+ function createInlineStylesImpl(themes: ThemeColors): ThemeStyles {
51
+ return typedObjectEntries(themes).reduce<ThemeStyles>((inlineTheme, [key, value]) => {
52
+ // LINT.IfChange("skipMetaKeys")
53
+ if (key === "key" || key === "fns" || key === "select") {
54
+ // LINT.ThenChange(["./vars.ts#skipMetaKeys", "./theme.test.ts#skipMetaKeys"])
55
+ return inlineTheme;
56
+ }
57
+ if (key === "opacity") {
58
+ Object.entries(themes.opacity as Record<string, string>).forEach(([opacityKey, opacityValue]) => {
59
+ inlineTheme[`--${varPrefix}-opacity-${opacityKey}`] = opacityValue;
60
+ }, "");
61
+
62
+ return inlineTheme;
63
+ }
64
+ if (key === "shades") {
65
+ Object.entries(themes.shades as Record<string, string>).forEach(([shadeKey, shadeValue]) => {
66
+ inlineTheme[`--${varPrefix}-shades-${shadeKey}`] = shadeValue;
67
+ }, "");
68
+
69
+ return inlineTheme;
70
+ }
71
+ if (key === "lights") {
72
+ Object.entries(themes.lights as Record<string, string>).forEach(([lightKey, lightValue]) => {
73
+ inlineTheme[`--${varPrefix}-lights-${lightKey}`] = lightValue;
74
+ }, "");
75
+
76
+ return inlineTheme;
77
+ }
78
+ if (key === "separators") {
79
+ Object.entries(themes.separators as Record<string, string>).forEach(([separatorKey, separatorValue]) => {
80
+ inlineTheme[`--${varPrefix}-separator-${separatorKey}`] = separatorValue;
81
+ }, "");
82
+
83
+ return inlineTheme;
84
+ }
85
+ inlineTheme[`--${varPrefix}-color-${key}`] = value;
86
+ return inlineTheme;
87
+ }, {});
88
+ }
89
+
90
+ export const createInlineStyles = memoize(
91
+ (theme: ThemeColors) => createInlineStylesImpl(theme),
92
+ (theme) => theme.key
93
+ );
@@ -0,0 +1,179 @@
1
+ import {themeVars} from "./theme";
2
+ import {transition} from "./animation";
3
+ import {border} from "./layout";
4
+
5
+ export const lineHeight = {
6
+ text: 1.6,
7
+ regular: 1.5,
8
+ narrow: 1.4,
9
+ heading: 1.3,
10
+ nowrap: 1,
11
+ } as const;
12
+
13
+ export const typeSizes = [30, 24, 18, 16, 14, 12, 10, 8] as const;
14
+
15
+ // 300 basic, 310 experiment with a variable Inter
16
+ export const fontSize = {
17
+ xxl: 30,
18
+ xl: 24,
19
+ lg: 18,
20
+ md: 16,
21
+ sm: 15,
22
+ xs: 14,
23
+ xxs: 13,
24
+ xxxs: 12,
25
+ tiny: 11,
26
+ mini: 10,
27
+ micro: 9,
28
+ nano: 8,
29
+ } as const;
30
+
31
+ export const fontFamily =
32
+ '"Inter Variable", "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Display", "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif';
33
+
34
+ export const fontWeight = {
35
+ light: 310, // 300 basic, 310 experiment with a variable Inter
36
+ regular: 410, // 400 basic, 410 experiment with a variable Inter
37
+ mediumLight: 450,
38
+ medium: 500,
39
+ semibold: 600,
40
+ bold: 700,
41
+ } as const;
42
+
43
+ export const textStyles = {
44
+ heading1: {
45
+ fontFamily,
46
+ fontSize: typeSizes[0],
47
+ letterSpacing: "-0.01em",
48
+ lineHeight: lineHeight.heading,
49
+ fontWeight: fontWeight.semibold,
50
+ color: themeVars.textColor,
51
+ },
52
+ heading2: {
53
+ fontFamily,
54
+ fontSize: typeSizes[1],
55
+ letterSpacing: "-0.002em",
56
+ lineHeight: lineHeight.heading,
57
+ fontWeight: fontWeight.semibold,
58
+ color: themeVars.textColor,
59
+ },
60
+ heading3: {
61
+ fontFamily,
62
+ fontSize: typeSizes[2],
63
+ letterSpacing: "-0.002em",
64
+ lineHeight: lineHeight.heading,
65
+ fontWeight: fontWeight.semibold,
66
+ color: themeVars.textColor,
67
+ },
68
+ heading4: {
69
+ fontFamily,
70
+ fontSize: typeSizes[3],
71
+ lineHeight: lineHeight.heading,
72
+ fontWeight: fontWeight.semibold,
73
+ color: themeVars.textColor,
74
+ },
75
+ heading5: {
76
+ fontFamily,
77
+ fontSize: typeSizes[4],
78
+ lineHeight: lineHeight.heading,
79
+ fontWeight: fontWeight.semibold,
80
+ color: themeVars.textColor,
81
+ },
82
+ heading6: {
83
+ fontFamily,
84
+ fontSize: typeSizes[5],
85
+ lineHeight: lineHeight.heading,
86
+ letterSpacing: 0.6,
87
+ textTransform: "uppercase",
88
+ fontWeight: fontWeight.regular,
89
+ color: themeVars.textColor,
90
+ },
91
+ heading7: {
92
+ fontFamily,
93
+ fontSize: typeSizes[6],
94
+ lineHeight: lineHeight.heading,
95
+ letterSpacing: 0.6,
96
+ textTransform: "uppercase",
97
+ fontWeight: fontWeight.regular,
98
+ color: themeVars.textColor,
99
+ },
100
+ heading8: {
101
+ fontFamily,
102
+ fontSize: typeSizes[6],
103
+ lineHeight: lineHeight.heading,
104
+ fontWeight: fontWeight.medium,
105
+ color: themeVars.textColor,
106
+ },
107
+ big: {
108
+ fontFamily,
109
+ fontSize: typeSizes[3],
110
+ lineHeight: lineHeight.regular,
111
+ fontWeight: fontWeight.regular,
112
+ color: themeVars.textColor,
113
+ },
114
+ regular: {
115
+ fontFamily,
116
+ fontSize: typeSizes[4],
117
+ lineHeight: lineHeight.regular,
118
+ fontWeight: fontWeight.regular,
119
+ color: themeVars.textColor,
120
+ textTransform: "none",
121
+ letterSpacing: "normal",
122
+ },
123
+ small: {
124
+ fontFamily,
125
+ fontSize: typeSizes[5],
126
+ lineHeight: lineHeight.regular,
127
+ fontWeight: fontWeight.regular,
128
+ color: themeVars.textColor,
129
+ textTransform: "none",
130
+ },
131
+ code: {
132
+ fontFamily: '"SFMono-Regular", Menlo, Consolas, "PT Mono", "Liberation Mono", Courier, monospace',
133
+ fontSize: typeSizes[4],
134
+ lineHeight: lineHeight.regular,
135
+ fontWeight: fontWeight.regular,
136
+ color: themeVars.textColor,
137
+ },
138
+ link: {
139
+ color: themeVars.linkColor,
140
+ borderBottom: themeVars.linkBorder,
141
+ textDecoration: "none",
142
+ cursor: "pointer",
143
+ transition: `border ${transition}`,
144
+ },
145
+ note: {
146
+ fontFamily,
147
+ fontSize: typeSizes[3],
148
+ lineHeight: lineHeight.regular,
149
+ fontWeight: fontWeight.regular,
150
+ color: themeVars.textColor,
151
+ borderRadius: border.radius6,
152
+ },
153
+ important: {
154
+ fontFamily,
155
+ fontSize: typeSizes[3],
156
+ lineHeight: lineHeight.regular,
157
+ fontWeight: fontWeight.regular,
158
+ color: themeVars.textColor,
159
+ border: `1px solid ${themeVars.active}`,
160
+ borderRadius: border.radius6,
161
+ },
162
+ numeric: {
163
+ tabularOn: {
164
+ fontVariantNumeric: "tabular-nums",
165
+ fontFeatureSettings: '"tnum" 1',
166
+ },
167
+ tabularOff: {
168
+ fontVariantNumeric: "normal",
169
+ fontFeatureSettings: '"tnum" 0',
170
+ },
171
+ },
172
+ inherit: {
173
+ fontFamily: "inherit",
174
+ fontSize: "inherit",
175
+ lineHeight: "inherit",
176
+ fontWeight: "inherit",
177
+ color: "inherit",
178
+ },
179
+ } as const;