@oxyhq/bloom 0.30.3 → 0.30.5
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/lib/commonjs/activity-heatmap/ActivityHeatmap.js +2 -37
- package/lib/commonjs/activity-heatmap/ActivityHeatmap.js.map +1 -1
- package/lib/commonjs/bottom-sheet/BottomSheetBase.js +731 -0
- package/lib/commonjs/bottom-sheet/BottomSheetBase.js.map +1 -0
- package/lib/commonjs/bottom-sheet/index.js +24 -694
- package/lib/commonjs/bottom-sheet/index.js.map +1 -1
- package/lib/commonjs/bottom-sheet/index.web.js +64 -0
- package/lib/commonjs/bottom-sheet/index.web.js.map +1 -0
- package/lib/commonjs/dialog/Dialog.js +2 -2
- package/lib/commonjs/dialog/Dialog.js.map +1 -1
- package/lib/commonjs/dialog/DialogBottomSheet.js +2 -2
- package/lib/commonjs/dialog/DialogBottomSheet.js.map +1 -1
- package/lib/commonjs/dialog/SheetShell.js +2 -2
- package/lib/commonjs/dialog/SheetShell.js.map +1 -1
- package/lib/commonjs/index.js +44 -44
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +66 -66
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/theme/color-utils.js +65 -0
- package/lib/commonjs/theme/color-utils.js.map +1 -0
- package/lib/commonjs/theme/index.js +13 -0
- package/lib/commonjs/theme/index.js.map +1 -1
- package/lib/module/activity-heatmap/ActivityHeatmap.js +1 -36
- package/lib/module/activity-heatmap/ActivityHeatmap.js.map +1 -1
- package/lib/module/bottom-sheet/BottomSheetBase.js +728 -0
- package/lib/module/bottom-sheet/BottomSheetBase.js.map +1 -0
- package/lib/module/bottom-sheet/index.js +27 -696
- package/lib/module/bottom-sheet/index.js.map +1 -1
- package/lib/module/bottom-sheet/index.web.js +63 -0
- package/lib/module/bottom-sheet/index.web.js.map +1 -0
- package/lib/module/dialog/Dialog.js +1 -1
- package/lib/module/dialog/Dialog.js.map +1 -1
- package/lib/module/dialog/DialogBottomSheet.js +1 -1
- package/lib/module/dialog/DialogBottomSheet.js.map +1 -1
- package/lib/module/dialog/SheetShell.js +1 -1
- package/lib/module/dialog/SheetShell.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +1 -1
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/theme/color-utils.js +60 -0
- package/lib/module/theme/color-utils.js.map +1 -0
- package/lib/module/theme/index.js +1 -0
- package/lib/module/theme/index.js.map +1 -1
- package/lib/typescript/commonjs/activity-heatmap/ActivityHeatmap.d.ts.map +1 -1
- package/lib/typescript/commonjs/bottom-sheet/BottomSheetBase.d.ts +127 -0
- package/lib/typescript/commonjs/bottom-sheet/BottomSheetBase.d.ts.map +1 -0
- package/lib/typescript/commonjs/bottom-sheet/index.d.ts +2 -90
- package/lib/typescript/commonjs/bottom-sheet/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/bottom-sheet/index.web.d.ts +7 -0
- package/lib/typescript/commonjs/bottom-sheet/index.web.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.web.d.ts +2 -2
- package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-utils.d.ts +28 -0
- package/lib/typescript/commonjs/theme/color-utils.d.ts.map +1 -0
- package/lib/typescript/commonjs/theme/index.d.ts +2 -0
- package/lib/typescript/commonjs/theme/index.d.ts.map +1 -1
- package/lib/typescript/module/activity-heatmap/ActivityHeatmap.d.ts.map +1 -1
- package/lib/typescript/module/bottom-sheet/BottomSheetBase.d.ts +127 -0
- package/lib/typescript/module/bottom-sheet/BottomSheetBase.d.ts.map +1 -0
- package/lib/typescript/module/bottom-sheet/index.d.ts +2 -90
- package/lib/typescript/module/bottom-sheet/index.d.ts.map +1 -1
- package/lib/typescript/module/bottom-sheet/index.web.d.ts +7 -0
- package/lib/typescript/module/bottom-sheet/index.web.d.ts.map +1 -0
- package/lib/typescript/module/index.web.d.ts +2 -2
- package/lib/typescript/module/index.web.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-utils.d.ts +28 -0
- package/lib/typescript/module/theme/color-utils.d.ts.map +1 -0
- package/lib/typescript/module/theme/index.d.ts +2 -0
- package/lib/typescript/module/theme/index.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/__tests__/BottomSheetWebFork.test.ts +66 -0
- package/src/activity-heatmap/ActivityHeatmap.tsx +1 -29
- package/src/bottom-sheet/BottomSheetBase.tsx +853 -0
- package/src/bottom-sheet/index.tsx +26 -821
- package/src/bottom-sheet/index.web.tsx +66 -0
- package/src/index.web.ts +2 -2
- package/src/theme/__tests__/color-utils.test.ts +40 -0
- package/src/theme/color-utils.ts +54 -0
- package/src/theme/index.ts +2 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Regression guard for the BottomSheet RN-Web fix.
|
|
6
|
+
*
|
|
7
|
+
* On React-Native-Web, RN's `<Modal>` renders through `ModalPortal`, which
|
|
8
|
+
* appends its host `<div>` DURING RENDER and removes it in an unmount effect
|
|
9
|
+
* that nulls its ref. Under React 19 concurrent/StrictMode that host node is
|
|
10
|
+
* orphaned, so the sheet mounts but its DOM lands in a detached node and never
|
|
11
|
+
* paints — breaking the responsive `Dialog` bottom placement on narrow web.
|
|
12
|
+
*
|
|
13
|
+
* The fix splits the component: a shared, platform-agnostic `BottomSheetBase`
|
|
14
|
+
* (no `<Modal>`, no keyboard-controller) plus two shells — native `index.tsx`
|
|
15
|
+
* (RN `<Modal>` + keyboard-controller, unchanged) and web `index.web.tsx`
|
|
16
|
+
* (bloom's stable DOM `<Portal>`). These source/contract assertions fail loudly
|
|
17
|
+
* if any leg regresses. (The actual paint is verified in a real browser — jest
|
|
18
|
+
* cannot reproduce the RN-Web render race.)
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const SRC = join(__dirname, '..');
|
|
22
|
+
const REPO_ROOT = join(SRC, '..');
|
|
23
|
+
|
|
24
|
+
const read = (rel: string) => readFileSync(join(SRC, rel), 'utf8');
|
|
25
|
+
|
|
26
|
+
describe('BottomSheet web fork (RN-Web Modal-orphan fix)', () => {
|
|
27
|
+
it('web shell renders through bloom DOM Portal, never RN <Modal>/keyboard-controller', () => {
|
|
28
|
+
const web = read('bottom-sheet/index.web.tsx');
|
|
29
|
+
expect(web).toMatch(/from '\.\.\/portal\/index\.web'/);
|
|
30
|
+
expect(web).toMatch(/BottomSheetBase/);
|
|
31
|
+
// The whole point: no RN Modal *import* (orphaned ModalPortal) on web.
|
|
32
|
+
// Doc comments may still reference Modal to explain why it's avoided.
|
|
33
|
+
expect(web).not.toMatch(/import \{[^}]*\bModal\b[^}]*\} from 'react-native'/);
|
|
34
|
+
expect(web).not.toMatch(/require\(\s*['"]react-native-keyboard-controller['"]/);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('native shell keeps RN <Modal> + keyboard-controller', () => {
|
|
38
|
+
const native = read('bottom-sheet/index.tsx');
|
|
39
|
+
expect(native).toMatch(/import \{ Modal[^}]*\} from 'react-native'/);
|
|
40
|
+
expect(native).toContain('react-native-keyboard-controller');
|
|
41
|
+
expect(native).toMatch(/BottomSheetBase/);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('shared base is a clean default: no <Modal>, no keyboard-controller import', () => {
|
|
45
|
+
const base = read('bottom-sheet/BottomSheetBase.tsx');
|
|
46
|
+
// Comments may MENTION Modal; assert there is no Modal *import*.
|
|
47
|
+
expect(base).not.toMatch(/import \{[^}]*\bModal\b[^}]*\} from 'react-native'/);
|
|
48
|
+
expect(base).not.toContain("require('react-native-keyboard-controller')");
|
|
49
|
+
// Base injects the platform Shell rather than hard-coding a container.
|
|
50
|
+
expect(base).toContain('Shell');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('package.json exports ./bottom-sheet with a browser condition → index.web.js', () => {
|
|
54
|
+
const pkg = JSON.parse(readFileSync(join(REPO_ROOT, 'package.json'), 'utf8')) as {
|
|
55
|
+
exports: Record<string, { browser?: { import?: string } }>;
|
|
56
|
+
};
|
|
57
|
+
const entry = pkg.exports['./bottom-sheet'];
|
|
58
|
+
expect(entry).toBeDefined();
|
|
59
|
+
expect(entry?.browser?.import).toBe('./lib/module/bottom-sheet/index.web.js');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('generator lists ./bottom-sheet as a web-forked subpath', () => {
|
|
63
|
+
const gen = readFileSync(join(REPO_ROOT, 'scripts/generate-platform-exports.mjs'), 'utf8');
|
|
64
|
+
expect(gen).toMatch(/WEB_FORKED_SUBPATHS[\s\S]*'\.\/bottom-sheet'/);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
2
|
import { View, Pressable, StyleSheet } from 'react-native';
|
|
3
3
|
|
|
4
|
+
import { withAlpha } from '../theme/color-utils';
|
|
4
5
|
import { useTheme } from '../theme/use-theme';
|
|
5
6
|
import { Text } from '../typography';
|
|
6
7
|
import type { ActivityHeatmapDay, ActivityHeatmapProps } from './types';
|
|
@@ -52,35 +53,6 @@ function levelForCount(count: number, levels: number[]): number {
|
|
|
52
53
|
return level;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
function parseRgb(color: string): { r: number; g: number; b: number } | null {
|
|
56
|
-
const trimmed = color.trim();
|
|
57
|
-
if (trimmed.startsWith('#')) {
|
|
58
|
-
let hex = trimmed.slice(1);
|
|
59
|
-
if (hex.length === 3) hex = hex.split('').map((c) => c + c).join('');
|
|
60
|
-
if (hex.length !== 6) return null;
|
|
61
|
-
const r = parseInt(hex.slice(0, 2), 16);
|
|
62
|
-
const g = parseInt(hex.slice(2, 4), 16);
|
|
63
|
-
const b = parseInt(hex.slice(4, 6), 16);
|
|
64
|
-
if ([r, g, b].some((v) => Number.isNaN(v))) return null;
|
|
65
|
-
return { r, g, b };
|
|
66
|
-
}
|
|
67
|
-
const match = /rgba?\(([^)]+)\)/i.exec(trimmed);
|
|
68
|
-
if (!match || match[1] === undefined) return null;
|
|
69
|
-
const parts = match[1].split(/[\s,/]+/).filter(Boolean).map(Number);
|
|
70
|
-
if (parts.length < 3) return null;
|
|
71
|
-
const [r, g, b] = parts;
|
|
72
|
-
if (r === undefined || g === undefined || b === undefined) return null;
|
|
73
|
-
if ([r, g, b].some((v) => Number.isNaN(v))) return null;
|
|
74
|
-
return { r, g, b };
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** Compose `color` at `alpha`; returns the input unchanged if it can't parse. */
|
|
78
|
-
function withAlpha(color: string, alpha: number): string {
|
|
79
|
-
const rgb = parseRgb(color);
|
|
80
|
-
if (!rgb) return color;
|
|
81
|
-
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
56
|
interface Cell {
|
|
85
57
|
key: string;
|
|
86
58
|
count: number;
|