@oxyhq/bloom 0.2.2 → 0.3.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/assets/fonts/BlomusModernus-Bold.ttf +0 -0
- package/assets/fonts/BlomusModernus-Bold.woff2 +0 -0
- package/assets/fonts/BlomusModernus-Regular.ttf +0 -0
- package/assets/fonts/BlomusModernus-Regular.woff2 +0 -0
- package/assets/fonts/GeistMono-Variable.ttf +0 -0
- package/assets/fonts/GeistMono-Variable.woff2 +0 -0
- package/assets/fonts/InterVariable.ttf +0 -0
- package/assets/fonts/InterVariable.woff2 +0 -0
- package/lib/commonjs/code/Code.js +47 -0
- package/lib/commonjs/code/Code.js.map +1 -0
- package/lib/commonjs/code/Pre.js +61 -0
- package/lib/commonjs/code/Pre.js.map +1 -0
- package/lib/commonjs/code/index.js +20 -0
- package/lib/commonjs/code/index.js.map +1 -0
- package/lib/commonjs/context-menu/index.web.js +2 -2
- package/lib/commonjs/context-menu/index.web.js.map +1 -1
- package/lib/commonjs/dialog/Dialog.web.js +2 -2
- package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
- package/lib/commonjs/fonts/FontLoader.js +35 -0
- package/lib/commonjs/fonts/FontLoader.js.map +1 -0
- package/lib/commonjs/fonts/FontLoader.native.js +36 -0
- package/lib/commonjs/fonts/FontLoader.native.js.map +1 -0
- package/lib/commonjs/fonts/apply-font-faces.js +47 -0
- package/lib/commonjs/fonts/apply-font-faces.js.map +1 -0
- package/lib/commonjs/fonts/font-assets.js +23 -0
- package/lib/commonjs/fonts/font-assets.js.map +1 -0
- package/lib/commonjs/fonts/index.js +40 -0
- package/lib/commonjs/fonts/index.js.map +1 -0
- package/lib/commonjs/fonts/tokens.js +27 -0
- package/lib/commonjs/fonts/tokens.js.map +1 -0
- package/lib/commonjs/index.js +9 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +9 -3
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/menu/index.web.js +2 -2
- package/lib/commonjs/menu/index.web.js.map +1 -1
- package/lib/commonjs/select/index.web.js +2 -2
- package/lib/commonjs/select/index.web.js.map +1 -1
- package/lib/commonjs/theme/BloomThemeProvider.js +8 -1
- package/lib/commonjs/theme/BloomThemeProvider.js.map +1 -1
- package/lib/commonjs/typography/index.js +41 -3
- package/lib/commonjs/typography/index.js.map +1 -1
- package/lib/module/code/Code.js +42 -0
- package/lib/module/code/Code.js.map +1 -0
- package/lib/module/code/Pre.js +56 -0
- package/lib/module/code/Pre.js.map +1 -0
- package/lib/module/code/index.js +5 -0
- package/lib/module/code/index.js.map +1 -0
- package/lib/module/context-menu/index.web.js +1 -1
- package/lib/module/context-menu/index.web.js.map +1 -1
- package/lib/module/dialog/Dialog.web.js +1 -1
- package/lib/module/dialog/Dialog.web.js.map +1 -1
- package/lib/module/fonts/FontLoader.js +30 -0
- package/lib/module/fonts/FontLoader.js.map +1 -0
- package/lib/module/fonts/FontLoader.native.js +31 -0
- package/lib/module/fonts/FontLoader.native.js.map +1 -0
- package/lib/module/fonts/apply-font-faces.js +42 -0
- package/lib/module/fonts/apply-font-faces.js.map +1 -0
- package/lib/module/fonts/font-assets.js +19 -0
- package/lib/module/fonts/font-assets.js.map +1 -0
- package/lib/module/fonts/index.js +7 -0
- package/lib/module/fonts/index.js.map +1 -0
- package/lib/module/fonts/tokens.js +23 -0
- package/lib/module/fonts/tokens.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +6 -0
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/menu/index.web.js +1 -1
- package/lib/module/menu/index.web.js.map +1 -1
- package/lib/module/select/index.web.js +1 -1
- package/lib/module/select/index.web.js.map +1 -1
- package/lib/module/theme/BloomThemeProvider.js +8 -1
- package/lib/module/theme/BloomThemeProvider.js.map +1 -1
- package/lib/module/typography/index.js +36 -3
- package/lib/module/typography/index.js.map +1 -1
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.fonts-web.test.d.ts +5 -0
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.fonts-web.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/__tests__/Code.test.d.ts +2 -0
- package/lib/typescript/commonjs/__tests__/Code.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/__tests__/FontLoader.native.test.d.ts +2 -0
- package/lib/typescript/commonjs/__tests__/FontLoader.native.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/__tests__/Pre.test.d.ts +2 -0
- package/lib/typescript/commonjs/__tests__/Pre.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/__tests__/apply-font-faces.test.d.ts +5 -0
- package/lib/typescript/commonjs/__tests__/apply-font-faces.test.d.ts.map +1 -0
- package/lib/typescript/commonjs/code/Code.d.ts +7 -0
- package/lib/typescript/commonjs/code/Code.d.ts.map +1 -0
- package/lib/typescript/commonjs/code/Pre.d.ts +8 -0
- package/lib/typescript/commonjs/code/Pre.d.ts.map +1 -0
- package/lib/typescript/commonjs/code/index.d.ts +5 -0
- package/lib/typescript/commonjs/code/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/fonts/FontLoader.d.ts +28 -0
- package/lib/typescript/commonjs/fonts/FontLoader.d.ts.map +1 -0
- package/lib/typescript/commonjs/fonts/FontLoader.native.d.ts +22 -0
- package/lib/typescript/commonjs/fonts/FontLoader.native.d.ts.map +1 -0
- package/lib/typescript/commonjs/fonts/apply-font-faces.d.ts +15 -0
- package/lib/typescript/commonjs/fonts/apply-font-faces.d.ts.map +1 -0
- package/lib/typescript/commonjs/fonts/font-assets.d.ts +7 -0
- package/lib/typescript/commonjs/fonts/font-assets.d.ts.map +1 -0
- package/lib/typescript/commonjs/fonts/index.d.ts +7 -0
- package/lib/typescript/commonjs/fonts/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/fonts/tokens.d.ts +21 -0
- package/lib/typescript/commonjs/fonts/tokens.d.ts.map +1 -0
- package/lib/typescript/commonjs/icons/common.d.ts +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +2 -0
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts +13 -1
- package/lib/typescript/commonjs/theme/BloomThemeProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/toast/index.d.ts +7 -7
- package/lib/typescript/commonjs/typography/index.d.ts +2 -0
- package/lib/typescript/commonjs/typography/index.d.ts.map +1 -1
- package/lib/typescript/module/__tests__/BloomThemeProvider.fonts-web.test.d.ts +5 -0
- package/lib/typescript/module/__tests__/BloomThemeProvider.fonts-web.test.d.ts.map +1 -0
- package/lib/typescript/module/__tests__/Code.test.d.ts +2 -0
- package/lib/typescript/module/__tests__/Code.test.d.ts.map +1 -0
- package/lib/typescript/module/__tests__/FontLoader.native.test.d.ts +2 -0
- package/lib/typescript/module/__tests__/FontLoader.native.test.d.ts.map +1 -0
- package/lib/typescript/module/__tests__/Pre.test.d.ts +2 -0
- package/lib/typescript/module/__tests__/Pre.test.d.ts.map +1 -0
- package/lib/typescript/module/__tests__/apply-font-faces.test.d.ts +5 -0
- package/lib/typescript/module/__tests__/apply-font-faces.test.d.ts.map +1 -0
- package/lib/typescript/module/code/Code.d.ts +7 -0
- package/lib/typescript/module/code/Code.d.ts.map +1 -0
- package/lib/typescript/module/code/Pre.d.ts +8 -0
- package/lib/typescript/module/code/Pre.d.ts.map +1 -0
- package/lib/typescript/module/code/index.d.ts +5 -0
- package/lib/typescript/module/code/index.d.ts.map +1 -0
- package/lib/typescript/module/fonts/FontLoader.d.ts +28 -0
- package/lib/typescript/module/fonts/FontLoader.d.ts.map +1 -0
- package/lib/typescript/module/fonts/FontLoader.native.d.ts +22 -0
- package/lib/typescript/module/fonts/FontLoader.native.d.ts.map +1 -0
- package/lib/typescript/module/fonts/apply-font-faces.d.ts +15 -0
- package/lib/typescript/module/fonts/apply-font-faces.d.ts.map +1 -0
- package/lib/typescript/module/fonts/font-assets.d.ts +7 -0
- package/lib/typescript/module/fonts/font-assets.d.ts.map +1 -0
- package/lib/typescript/module/fonts/index.d.ts +7 -0
- package/lib/typescript/module/fonts/index.d.ts.map +1 -0
- package/lib/typescript/module/fonts/tokens.d.ts +21 -0
- package/lib/typescript/module/fonts/tokens.d.ts.map +1 -0
- package/lib/typescript/module/icons/common.d.ts +1 -1
- package/lib/typescript/module/index.d.ts +2 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/index.web.d.ts +2 -0
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/theme/BloomThemeProvider.d.ts +13 -1
- package/lib/typescript/module/theme/BloomThemeProvider.d.ts.map +1 -1
- package/lib/typescript/module/toast/index.d.ts +7 -7
- package/lib/typescript/module/typography/index.d.ts +2 -0
- package/lib/typescript/module/typography/index.d.ts.map +1 -1
- package/package.json +37 -18
- package/src/__tests__/BloomThemeProvider.fonts-web.test.tsx +42 -0
- package/src/__tests__/BloomThemeProvider.test.tsx +22 -0
- package/src/__tests__/Code.test.tsx +25 -0
- package/src/__tests__/FontLoader.native.test.tsx +75 -0
- package/src/__tests__/Pre.test.tsx +25 -0
- package/src/__tests__/apply-font-faces.test.ts +59 -0
- package/src/assets.d.ts +20 -0
- package/src/code/Code.tsx +52 -0
- package/src/code/Pre.tsx +76 -0
- package/src/code/index.ts +4 -0
- package/src/context-menu/index.web.tsx +1 -1
- package/src/dialog/Dialog.web.tsx +1 -1
- package/src/fonts/FontLoader.native.tsx +30 -0
- package/src/fonts/FontLoader.tsx +37 -0
- package/src/fonts/apply-font-faces.ts +41 -0
- package/src/fonts/font-assets.ts +16 -0
- package/src/fonts/index.ts +6 -0
- package/src/fonts/tokens.ts +23 -0
- package/src/index.ts +6 -0
- package/src/index.web.ts +6 -0
- package/src/menu/index.web.tsx +1 -1
- package/src/select/index.web.tsx +1 -1
- package/src/theme/BloomThemeProvider.tsx +18 -1
- package/src/typography/index.tsx +32 -3
package/src/code/Pre.tsx
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Text as RNText,
|
|
4
|
+
View,
|
|
5
|
+
type TextProps as RNTextProps,
|
|
6
|
+
Platform,
|
|
7
|
+
type StyleProp,
|
|
8
|
+
type ViewStyle,
|
|
9
|
+
type TextStyle,
|
|
10
|
+
} from 'react-native';
|
|
11
|
+
|
|
12
|
+
import { useTheme } from '../theme/use-theme';
|
|
13
|
+
|
|
14
|
+
export interface PreProps extends Omit<RNTextProps, 'style'> {
|
|
15
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
16
|
+
style?: StyleProp<TextStyle>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Block-level monospace text — render as `<pre>` on web (CSS var family)
|
|
21
|
+
* and `<View><Text fontFamily="Geist Mono"></View>` on native.
|
|
22
|
+
*/
|
|
23
|
+
const PreComponent = function Pre({
|
|
24
|
+
children,
|
|
25
|
+
containerStyle,
|
|
26
|
+
style,
|
|
27
|
+
...rest
|
|
28
|
+
}: PreProps) {
|
|
29
|
+
const { colors } = useTheme();
|
|
30
|
+
|
|
31
|
+
if (Platform.OS === 'web') {
|
|
32
|
+
return React.createElement(
|
|
33
|
+
'pre',
|
|
34
|
+
{
|
|
35
|
+
...rest,
|
|
36
|
+
style: {
|
|
37
|
+
fontFamily: 'var(--bloom-font-mono)',
|
|
38
|
+
fontSize: '0.92em',
|
|
39
|
+
color: colors.text,
|
|
40
|
+
backgroundColor: colors.backgroundSecondary,
|
|
41
|
+
padding: '12px 16px',
|
|
42
|
+
borderRadius: 8,
|
|
43
|
+
overflow: 'auto',
|
|
44
|
+
margin: 0,
|
|
45
|
+
...(containerStyle as object | undefined),
|
|
46
|
+
...(style as object | undefined),
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
children,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<View
|
|
55
|
+
style={[
|
|
56
|
+
{
|
|
57
|
+
backgroundColor: colors.backgroundSecondary,
|
|
58
|
+
padding: 12,
|
|
59
|
+
borderRadius: 8,
|
|
60
|
+
},
|
|
61
|
+
containerStyle,
|
|
62
|
+
]}>
|
|
63
|
+
<RNText
|
|
64
|
+
{...rest}
|
|
65
|
+
style={[
|
|
66
|
+
{ fontFamily: 'Geist Mono', fontSize: 13, color: colors.text },
|
|
67
|
+
style,
|
|
68
|
+
]}>
|
|
69
|
+
{children}
|
|
70
|
+
</RNText>
|
|
71
|
+
</View>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const Pre = memo(PreComponent);
|
|
76
|
+
Pre.displayName = 'Pre';
|
|
@@ -17,7 +17,7 @@ import { Pressable, StyleSheet, View } from 'react-native';
|
|
|
17
17
|
|
|
18
18
|
import { useTheme } from '../theme/use-theme';
|
|
19
19
|
import { Text } from '../typography';
|
|
20
|
-
import { Portal } from '../portal';
|
|
20
|
+
import { Portal } from '../portal/index.web';
|
|
21
21
|
import { useInteractionState } from '../hooks/useInteractionState';
|
|
22
22
|
import { ItemCtx, useItemContext } from './context';
|
|
23
23
|
import type {
|
|
@@ -3,7 +3,7 @@ import { Pressable, Text, View, type ViewStyle } from 'react-native';
|
|
|
3
3
|
import { RemoveScrollBar } from 'react-remove-scroll-bar';
|
|
4
4
|
|
|
5
5
|
import { useTheme } from '../theme/use-theme';
|
|
6
|
-
import { Portal } from '../portal';
|
|
6
|
+
import { Portal } from '../portal/index.web';
|
|
7
7
|
import { Context, useDialogContext } from './context';
|
|
8
8
|
import type { DialogControlProps, DialogInnerProps, DialogOuterProps } from './types';
|
|
9
9
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useFonts } from 'expo-font';
|
|
3
|
+
import { FONT_ASSETS } from './font-assets';
|
|
4
|
+
|
|
5
|
+
export interface FontLoaderProps {
|
|
6
|
+
/**
|
|
7
|
+
* Whether to gate rendering on fonts being loaded. When false the
|
|
8
|
+
* component is a pass-through that still calls `useFonts` (the hook must
|
|
9
|
+
* run unconditionally per the Rules of Hooks).
|
|
10
|
+
*/
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
/** Rendered while native fonts load. Defaults to `null`. */
|
|
13
|
+
fallback?: React.ReactNode;
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Native font loader. Calls `expo-font`'s `useFonts` with the Bloom font
|
|
19
|
+
* asset map and gates `children` on the load result. The hook is invoked
|
|
20
|
+
* unconditionally — `enabled` only affects what's rendered, not whether
|
|
21
|
+
* fonts get loaded. This keeps Hook order stable across renders and means
|
|
22
|
+
* `<BloomThemeProvider fonts={false}>` still gets fonts pre-loaded if the
|
|
23
|
+
* provider tree ever flips `fonts` back on.
|
|
24
|
+
*/
|
|
25
|
+
export function FontLoader({ enabled, fallback, children }: FontLoaderProps) {
|
|
26
|
+
const [loaded] = useFonts(FONT_ASSETS);
|
|
27
|
+
if (!enabled) return <>{children}</>;
|
|
28
|
+
if (!loaded) return <>{fallback ?? null}</>;
|
|
29
|
+
return <>{children}</>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import { applyFontFaces } from './apply-font-faces';
|
|
3
|
+
|
|
4
|
+
export interface FontLoaderProps {
|
|
5
|
+
/**
|
|
6
|
+
* Whether to load and inject the Bloom font system. When false, this
|
|
7
|
+
* component is a pass-through. Default true (set by `BloomThemeProvider`).
|
|
8
|
+
*/
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Rendered while native fonts load. Ignored on web — the web variant
|
|
12
|
+
* applies CSS `@font-face` rules synchronously and uses `font-display: swap`
|
|
13
|
+
* to handle the FOUT period.
|
|
14
|
+
*/
|
|
15
|
+
fallback?: React.ReactNode;
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Web font loader. Applies the Bloom `@font-face` rules and CSS variables
|
|
21
|
+
* to `:root` on first render, before the first paint, using the same
|
|
22
|
+
* `useRef`-during-render pattern as `BloomThemeProvider`'s color application.
|
|
23
|
+
*
|
|
24
|
+
* No `useEffect`: the side effect runs synchronously inside the render phase,
|
|
25
|
+
* gated by a ref so it only executes once. Subsequent renders short-circuit.
|
|
26
|
+
*
|
|
27
|
+
* Native consumers resolve `FontLoader.native.tsx` via the React Native /
|
|
28
|
+
* Metro bundler's platform extension resolution — they never load this file.
|
|
29
|
+
*/
|
|
30
|
+
export function FontLoader({ enabled, children }: FontLoaderProps) {
|
|
31
|
+
const applied = useRef(false);
|
|
32
|
+
if (enabled && !applied.current) {
|
|
33
|
+
applied.current = true;
|
|
34
|
+
applyFontFaces();
|
|
35
|
+
}
|
|
36
|
+
return <>{children}</>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import blomusReg from '../../assets/fonts/BlomusModernus-Regular.woff2';
|
|
3
|
+
import blomusBold from '../../assets/fonts/BlomusModernus-Bold.woff2';
|
|
4
|
+
import interVar from '../../assets/fonts/InterVariable.woff2';
|
|
5
|
+
import geistMono from '../../assets/fonts/GeistMono-Variable.woff2';
|
|
6
|
+
import { fontFamilies } from './tokens';
|
|
7
|
+
|
|
8
|
+
const STYLE_ID = 'bloom-fonts';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Inject @font-face rules and font CSS variables onto :root.
|
|
12
|
+
*
|
|
13
|
+
* No-op on native and when `document` is unavailable (SSR). Idempotent —
|
|
14
|
+
* safe to call multiple times; subsequent calls early-return after the
|
|
15
|
+
* `<style id="bloom-fonts">` tag has been mounted.
|
|
16
|
+
*
|
|
17
|
+
* Follows the same shape as `applyDarkClass` / `applyColorPresetVars`: a
|
|
18
|
+
* single file with an internal `Platform.OS` check rather than a `.web.ts` /
|
|
19
|
+
* `.native.ts` split. Bundlers strip the unreachable web import code path
|
|
20
|
+
* on native because the function body short-circuits before referencing the
|
|
21
|
+
* woff2 URLs.
|
|
22
|
+
*/
|
|
23
|
+
export function applyFontFaces(): void {
|
|
24
|
+
if (Platform.OS !== 'web' || typeof document === 'undefined') return;
|
|
25
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
26
|
+
|
|
27
|
+
const style = document.createElement('style');
|
|
28
|
+
style.id = STYLE_ID;
|
|
29
|
+
style.textContent = `
|
|
30
|
+
@font-face { font-family: 'BlomusModernus'; src: url(${blomusReg}) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
|
|
31
|
+
@font-face { font-family: 'BlomusModernus'; src: url(${blomusBold}) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }
|
|
32
|
+
@font-face { font-family: 'Inter'; src: url(${interVar}) format('woff2-variations'); font-weight: 100 900; font-style: normal; font-display: swap; }
|
|
33
|
+
@font-face { font-family: 'Geist Mono'; src: url(${geistMono}) format('woff2-variations'); font-weight: 100 900; font-style: normal; font-display: swap; }
|
|
34
|
+
:root {
|
|
35
|
+
--bloom-font-display: ${fontFamilies.display};
|
|
36
|
+
--bloom-font-sans: ${fontFamilies.sans};
|
|
37
|
+
--bloom-font-mono: ${fontFamilies.mono};
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
document.head.appendChild(style);
|
|
41
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Native font asset map for `useFonts(FONT_ASSETS)`.
|
|
2
|
+
//
|
|
3
|
+
// We ship variable .ttf files for Inter and Geist Mono (extracted from the
|
|
4
|
+
// official rsms/inter and vercel/geist-font releases) so the same family name
|
|
5
|
+
// covers all weights at runtime. `@fontsource(-variable)?/*` packages only
|
|
6
|
+
// publish .woff2 for their variable axes — modern react-native font loading
|
|
7
|
+
// requires .ttf, so we use the upstream variable TTFs instead. On web,
|
|
8
|
+
// `apply-font-faces.ts` references the .woff2 variants directly and this file
|
|
9
|
+
// is never imported.
|
|
10
|
+
|
|
11
|
+
export const FONT_ASSETS = {
|
|
12
|
+
BlomusModernus: require('../../assets/fonts/BlomusModernus-Regular.ttf'),
|
|
13
|
+
'BlomusModernus-Bold': require('../../assets/fonts/BlomusModernus-Bold.ttf'),
|
|
14
|
+
Inter: require('../../assets/fonts/InterVariable.ttf'),
|
|
15
|
+
'Geist Mono': require('../../assets/fonts/GeistMono-Variable.ttf'),
|
|
16
|
+
} as const;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { fontFamilies, fontCssVars } from './tokens';
|
|
2
|
+
export type { FontFamilyName } from './tokens';
|
|
3
|
+
export { applyFontFaces } from './apply-font-faces';
|
|
4
|
+
export { FONT_ASSETS } from './font-assets';
|
|
5
|
+
export { FontLoader } from './FontLoader';
|
|
6
|
+
export type { FontLoaderProps } from './FontLoader';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Font family tokens for the Bloom design system.
|
|
3
|
+
*
|
|
4
|
+
* `fontFamilies` resolves to CSS-style stacks (with system fallbacks) and is
|
|
5
|
+
* used to populate the `:root` custom properties on web and as the literal
|
|
6
|
+
* `fontFamily` string source on native.
|
|
7
|
+
*
|
|
8
|
+
* `fontCssVars` is the inverse map: name -> CSS custom property name.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export const fontFamilies = {
|
|
12
|
+
display: 'BlomusModernus, Georgia, "Times New Roman", serif',
|
|
13
|
+
sans: 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
14
|
+
mono: '"Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace',
|
|
15
|
+
} as const;
|
|
16
|
+
|
|
17
|
+
export const fontCssVars = {
|
|
18
|
+
display: '--bloom-font-display',
|
|
19
|
+
sans: '--bloom-font-sans',
|
|
20
|
+
mono: '--bloom-font-mono',
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
export type FontFamilyName = keyof typeof fontFamilies;
|
package/src/index.ts
CHANGED
|
@@ -68,3 +68,9 @@ export * as Menu from './menu';
|
|
|
68
68
|
export * as Tooltip from './tooltip';
|
|
69
69
|
export * as Select from './select';
|
|
70
70
|
export * as ContextMenu from './context-menu';
|
|
71
|
+
|
|
72
|
+
// Code (mono)
|
|
73
|
+
export * as Code from './code';
|
|
74
|
+
|
|
75
|
+
// Fonts
|
|
76
|
+
export * as Fonts from './fonts';
|
package/src/index.web.ts
CHANGED
|
@@ -73,3 +73,9 @@ export * as Menu from './menu/index.web';
|
|
|
73
73
|
export * as Tooltip from './tooltip/index.web';
|
|
74
74
|
export * as Select from './select/index.web';
|
|
75
75
|
export * as ContextMenu from './context-menu/index.web';
|
|
76
|
+
|
|
77
|
+
// Code (mono)
|
|
78
|
+
export * as Code from './code';
|
|
79
|
+
|
|
80
|
+
// Fonts
|
|
81
|
+
export * as Fonts from './fonts';
|
package/src/menu/index.web.tsx
CHANGED
|
@@ -13,7 +13,7 @@ import { Pressable, StyleSheet, View, type StyleProp, type ViewStyle } from 'rea
|
|
|
13
13
|
|
|
14
14
|
import { useTheme } from '../theme/use-theme';
|
|
15
15
|
import { Text } from '../typography';
|
|
16
|
-
import { Portal } from '../portal';
|
|
16
|
+
import { Portal } from '../portal/index.web';
|
|
17
17
|
import type { DialogControlProps } from '../dialog/types';
|
|
18
18
|
import {
|
|
19
19
|
MenuContext,
|
package/src/select/index.web.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { Pressable, StyleSheet, View } from 'react-native';
|
|
|
3
3
|
|
|
4
4
|
import { useTheme } from '../theme/use-theme';
|
|
5
5
|
import { Text } from '../typography';
|
|
6
|
-
import { Portal } from '../portal';
|
|
6
|
+
import { Portal } from '../portal/index.web';
|
|
7
7
|
import { RadioIndicator } from '../radio-indicator';
|
|
8
8
|
import { useInteractionState } from '../hooks/useInteractionState';
|
|
9
9
|
import {
|
|
@@ -4,6 +4,7 @@ import { APP_COLOR_PRESETS, type AppColorName } from './color-presets';
|
|
|
4
4
|
import { getAdaptiveColors } from './adaptive-colors';
|
|
5
5
|
import { applyDarkClass, applyColorPresetVars } from './apply-dark-class';
|
|
6
6
|
import { setColorSchemeSafe } from './set-color-scheme-safe';
|
|
7
|
+
import { FontLoader } from '../fonts/FontLoader';
|
|
7
8
|
import type { Theme, ThemeColors, ThemeMode } from './types';
|
|
8
9
|
|
|
9
10
|
function hslVarToCSS(value: string): string {
|
|
@@ -112,6 +113,18 @@ export interface BloomThemeProviderProps {
|
|
|
112
113
|
colorPreset?: AppColorName;
|
|
113
114
|
onModeChange?: (mode: ThemeMode) => void;
|
|
114
115
|
onColorPresetChange?: (preset: AppColorName) => void;
|
|
116
|
+
/**
|
|
117
|
+
* Load and inject the Bloom font system (BlomusModernus + Inter Variable
|
|
118
|
+
* + Geist Mono Variable). Default true. Set to false to opt out — e.g.
|
|
119
|
+
* apps that already ship their own font loader.
|
|
120
|
+
*/
|
|
121
|
+
fonts?: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Rendered while native fonts load. Ignored on web. Useful for matching
|
|
124
|
+
* an app-level splash screen so consumers don't see a system-font flash
|
|
125
|
+
* before the bundled fonts resolve.
|
|
126
|
+
*/
|
|
127
|
+
onFontsLoading?: React.ReactNode;
|
|
115
128
|
children: React.ReactNode;
|
|
116
129
|
}
|
|
117
130
|
|
|
@@ -120,6 +133,8 @@ export function BloomThemeProvider({
|
|
|
120
133
|
colorPreset: controlledPreset,
|
|
121
134
|
onModeChange,
|
|
122
135
|
onColorPresetChange,
|
|
136
|
+
fonts = true,
|
|
137
|
+
onFontsLoading,
|
|
123
138
|
children,
|
|
124
139
|
}: BloomThemeProviderProps) {
|
|
125
140
|
const rnScheme = useRNColorScheme();
|
|
@@ -175,7 +190,9 @@ export function BloomThemeProvider({
|
|
|
175
190
|
|
|
176
191
|
return (
|
|
177
192
|
<BloomThemeContext.Provider value={contextValue}>
|
|
178
|
-
{
|
|
193
|
+
<FontLoader enabled={fonts} fallback={onFontsLoading}>
|
|
194
|
+
{children}
|
|
195
|
+
</FontLoader>
|
|
179
196
|
</BloomThemeContext.Provider>
|
|
180
197
|
);
|
|
181
198
|
}
|
package/src/typography/index.tsx
CHANGED
|
@@ -8,11 +8,33 @@ import {
|
|
|
8
8
|
} from 'react-native';
|
|
9
9
|
|
|
10
10
|
import { useTheme } from '../theme/use-theme';
|
|
11
|
+
import { fontFamilies } from '../fonts/tokens';
|
|
11
12
|
|
|
12
13
|
export type TextProps = RNTextProps;
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
+
* Platform-aware font-family value. On web we resolve to the CSS custom
|
|
17
|
+
* property set by `applyFontFaces` so consumer apps can re-skin Bloom by
|
|
18
|
+
* overriding `--bloom-font-*` at any subtree. On native we use the literal
|
|
19
|
+
* family name registered by `expo-font`'s `useFonts(FONT_ASSETS)`.
|
|
20
|
+
*/
|
|
21
|
+
function fontFamilyStyle(
|
|
22
|
+
kind: 'display' | 'sans' | 'mono',
|
|
23
|
+
): { fontFamily: string } {
|
|
24
|
+
if (Platform.OS === 'web') {
|
|
25
|
+
return { fontFamily: `var(--bloom-font-${kind})` };
|
|
26
|
+
}
|
|
27
|
+
if (kind === 'display') return { fontFamily: 'BlomusModernus' };
|
|
28
|
+
if (kind === 'mono') return { fontFamily: 'Geist Mono' };
|
|
29
|
+
return { fontFamily: 'Inter' };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const SANS_FONT_FAMILY = fontFamilyStyle('sans');
|
|
33
|
+
const DISPLAY_FONT_FAMILY = fontFamilyStyle('display');
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Base text component with theme-aware default color and the Bloom sans
|
|
37
|
+
* font family applied.
|
|
16
38
|
*/
|
|
17
39
|
const TextComponent = function Text({ children, style, ...rest }: TextProps) {
|
|
18
40
|
const { colors } = useTheme();
|
|
@@ -20,7 +42,7 @@ const TextComponent = function Text({ children, style, ...rest }: TextProps) {
|
|
|
20
42
|
return (
|
|
21
43
|
<RNText
|
|
22
44
|
{...rest}
|
|
23
|
-
style={[{ fontSize: 13, color: colors.text }, style]}>
|
|
45
|
+
style={[{ fontSize: 13, color: colors.text, ...SANS_FONT_FAMILY }, style]}>
|
|
24
46
|
{children}
|
|
25
47
|
</RNText>
|
|
26
48
|
);
|
|
@@ -31,13 +53,18 @@ Text.displayName = 'Text';
|
|
|
31
53
|
|
|
32
54
|
export { Text as Span };
|
|
33
55
|
|
|
56
|
+
const HEADING_STYLE: StyleProp<TextStyle> = {
|
|
57
|
+
...DISPLAY_FONT_FAMILY,
|
|
58
|
+
fontWeight: '700',
|
|
59
|
+
};
|
|
60
|
+
|
|
34
61
|
function createHeadingElement({ level }: { level: number }): React.FC<TextProps> {
|
|
35
62
|
return function HeadingElement({ style, ...rest }: TextProps) {
|
|
36
63
|
const extraProps: Record<string, unknown> =
|
|
37
64
|
Platform.OS === 'web'
|
|
38
65
|
? { role: 'heading', 'aria-level': level }
|
|
39
66
|
: {};
|
|
40
|
-
return <Text {...extraProps} {...rest} style={style} />;
|
|
67
|
+
return <Text {...extraProps} {...rest} style={[HEADING_STYLE, style]} />;
|
|
41
68
|
};
|
|
42
69
|
}
|
|
43
70
|
|
|
@@ -66,3 +93,5 @@ export function P({ style, ...rest }: TextProps) {
|
|
|
66
93
|
);
|
|
67
94
|
}
|
|
68
95
|
P.displayName = 'P';
|
|
96
|
+
|
|
97
|
+
export { fontFamilies };
|