@oxyhq/bloom 0.5.0 → 0.5.1
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/fonts/FontLoader.js +6 -5
- package/lib/commonjs/fonts/FontLoader.js.map +1 -1
- package/lib/commonjs/fonts/apply-font-faces.js +4 -4
- package/lib/commonjs/fonts/apply-font-faces.web.js +13 -12
- package/lib/commonjs/fonts/apply-font-faces.web.js.map +1 -1
- package/lib/commonjs/fonts/font-assets.js +2 -2
- package/lib/commonjs/fonts/font-data.web.js +22 -0
- package/lib/commonjs/fonts/font-data.web.js.map +1 -0
- package/lib/module/fonts/FontLoader.js +6 -5
- package/lib/module/fonts/FontLoader.js.map +1 -1
- package/lib/module/fonts/apply-font-faces.js +4 -4
- package/lib/module/fonts/apply-font-faces.web.js +13 -10
- package/lib/module/fonts/apply-font-faces.web.js.map +1 -1
- package/lib/module/fonts/font-assets.js +2 -2
- package/lib/module/fonts/font-data.web.js +18 -0
- package/lib/module/fonts/font-data.web.js.map +1 -0
- package/lib/module/fonts/index.web.js +4 -4
- package/lib/typescript/commonjs/fonts/FontLoader.d.ts.map +1 -1
- package/lib/typescript/commonjs/fonts/apply-font-faces.web.d.ts +8 -1
- package/lib/typescript/commonjs/fonts/apply-font-faces.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/fonts/font-data.web.d.ts +5 -0
- package/lib/typescript/commonjs/fonts/font-data.web.d.ts.map +1 -0
- package/lib/typescript/module/fonts/FontLoader.d.ts.map +1 -1
- package/lib/typescript/module/fonts/apply-font-faces.web.d.ts +8 -1
- package/lib/typescript/module/fonts/apply-font-faces.web.d.ts.map +1 -1
- package/lib/typescript/module/fonts/font-data.web.d.ts +5 -0
- package/lib/typescript/module/fonts/font-data.web.d.ts.map +1 -0
- package/package.json +36 -5
- package/src/avatar/Avatar.stories.tsx +69 -0
- package/src/bottom-sheet/BottomSheet.stories.tsx +92 -0
- package/src/button/Button.stories.tsx +94 -0
- package/src/context-menu/ContextMenu.stories.tsx +71 -0
- package/src/dialog/Dialog.stories.tsx +112 -0
- package/src/fonts/FontLoader.tsx +6 -5
- package/src/fonts/apply-font-faces.ts +4 -4
- package/src/fonts/apply-font-faces.web.ts +18 -10
- package/src/fonts/font-assets.ts +2 -2
- package/src/fonts/font-data.web.ts +15 -0
- package/src/fonts/index.web.ts +4 -4
- package/src/loading/Loading.stories.tsx +60 -0
- package/src/menu/Menu.stories.tsx +79 -0
- package/src/prompt-input/PromptInput.stories.tsx +82 -0
- package/src/select/Select.stories.tsx +84 -0
- package/src/settings-list/SettingsList.stories.tsx +106 -0
- package/src/text-field/TextField.stories.tsx +90 -0
- package/src/toast/Toast.stories.tsx +109 -0
- package/lib/commonjs/fonts/assets/BlomusModernus-Bold.woff2 +0 -0
- package/lib/commonjs/fonts/assets/BlomusModernus-Regular.woff2 +0 -0
- package/lib/commonjs/fonts/assets/GeistMono-Variable.woff2 +0 -0
- package/lib/commonjs/fonts/assets/InterVariable.woff2 +0 -0
- package/lib/module/fonts/assets/BlomusModernus-Bold.woff2 +0 -0
- package/lib/module/fonts/assets/BlomusModernus-Regular.woff2 +0 -0
- package/lib/module/fonts/assets/GeistMono-Variable.woff2 +0 -0
- package/lib/module/fonts/assets/InterVariable.woff2 +0 -0
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.fonts-web.test.d.ts +0 -5
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.fonts-web.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/BloomThemeProvider.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/BottomSheet.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/BottomSheet.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/Button.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/Button.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/Code.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/Code.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/Dialog.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/Dialog.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/FontLoader.native.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/FontLoader.native.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/Pre.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/Pre.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/SettingsList.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/SettingsList.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/apply-font-faces.test.d.ts +0 -5
- package/lib/typescript/commonjs/__tests__/apply-font-faces.test.d.ts.map +0 -1
- package/lib/typescript/commonjs/__tests__/theme.test.d.ts +0 -2
- package/lib/typescript/commonjs/__tests__/theme.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/BloomThemeProvider.fonts-web.test.d.ts +0 -5
- package/lib/typescript/module/__tests__/BloomThemeProvider.fonts-web.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/BloomThemeProvider.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/BloomThemeProvider.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/BottomSheet.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/BottomSheet.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/Button.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/Button.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/Code.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/Code.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/Dialog.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/Dialog.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/FontLoader.native.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/FontLoader.native.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/Pre.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/Pre.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/SettingsList.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/SettingsList.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/apply-font-faces.test.d.ts +0 -5
- package/lib/typescript/module/__tests__/apply-font-faces.test.d.ts.map +0 -1
- package/lib/typescript/module/__tests__/theme.test.d.ts +0 -2
- package/lib/typescript/module/__tests__/theme.test.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["blomusModernusRegular","blomusModernusBold","interVariable","geistMonoVariable"],"sourceRoot":"../../../src","sources":["fonts/font-data.web.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAO,MAAMA,qBAA6B,GAAG,ioqGAAioqG;AAC9qqG,OAAO,MAAMC,kBAA0B,GAAG,qlqGAAqlqG;AAC/nqG,OAAO,MAAMC,aAAqB,GAAG,i39DAAi39D;AACt59D,OAAO,MAAMC,iBAAyB,GAAG,i9tCAAi9tC","ignoreList":[]}
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
// Web variant of the `./fonts` barrel.
|
|
4
4
|
//
|
|
5
5
|
// The default barrel (`./index.ts`) re-exports `applyFontFaces` from
|
|
6
|
-
// `./apply-font-faces`, which on native
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
6
|
+
// `./apply-font-faces`, which on native is a no-op stub. The web fork
|
|
7
|
+
// explicitly reaches for `./apply-font-faces.web`, which performs the real
|
|
8
|
+
// `@font-face` injection using inlined base64 data URLs (see
|
|
9
|
+
// `font-data.web.ts`).
|
|
10
10
|
//
|
|
11
11
|
// Web bundlers select this file via the `"browser"` condition in
|
|
12
12
|
// `package.json`'s `exports['./fonts']`; native bundlers fall through to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FontLoader.d.ts","sourceRoot":"","sources":["../../../../src/fonts/FontLoader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"FontLoader.d.ts","sourceRoot":"","sources":["../../../../src/fonts/FontLoader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAUtC,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,eAAe,2CAOhE"}
|
|
@@ -3,10 +3,17 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Web-only. The native counterpart in `apply-font-faces.ts` is a no-op
|
|
5
5
|
* stub — Metro cannot parse `.woff2` imports, so the file split keeps
|
|
6
|
-
*
|
|
6
|
+
* the font payload out of the native bundle entirely. Idempotent: safe to
|
|
7
7
|
* call multiple times; subsequent calls early-return after the
|
|
8
8
|
* `<style id="bloom-fonts">` tag has been mounted. SSR-safe via the
|
|
9
9
|
* `typeof document === 'undefined'` guard.
|
|
10
|
+
*
|
|
11
|
+
* The font URLs come from `./font-data.web`, a generated module that
|
|
12
|
+
* embeds the woff2 bytes as base64 data URLs. Inlining (rather than
|
|
13
|
+
* relying on bundler asset loaders for `.woff2`) means consumers do not
|
|
14
|
+
* have to extend Metro's `assetExts` or add a webpack/Vite asset rule —
|
|
15
|
+
* the published JS is self-contained. See `scripts/generate-font-data.mjs`
|
|
16
|
+
* for the rationale and trade-offs.
|
|
10
17
|
*/
|
|
11
18
|
export declare function applyFontFaces(): void;
|
|
12
19
|
//# sourceMappingURL=apply-font-faces.web.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-font-faces.web.d.ts","sourceRoot":"","sources":["../../../../src/fonts/apply-font-faces.web.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apply-font-faces.web.d.ts","sourceRoot":"","sources":["../../../../src/fonts/apply-font-faces.web.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAkBrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-data.web.d.ts","sourceRoot":"","sources":["../../../../src/fonts/font-data.web.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,qBAAqB,EAAE,MAA0oqG,CAAC;AAC/qqG,eAAO,MAAM,kBAAkB,EAAE,MAA8lqG,CAAC;AAChoqG,eAAO,MAAM,aAAa,EAAE,MAA039D,CAAC;AACv59D,eAAO,MAAM,iBAAiB,EAAE,MAA09tC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FontLoader.d.ts","sourceRoot":"","sources":["../../../../src/fonts/FontLoader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"FontLoader.d.ts","sourceRoot":"","sources":["../../../../src/fonts/FontLoader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAUtC,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,eAAe,2CAOhE"}
|
|
@@ -3,10 +3,17 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Web-only. The native counterpart in `apply-font-faces.ts` is a no-op
|
|
5
5
|
* stub — Metro cannot parse `.woff2` imports, so the file split keeps
|
|
6
|
-
*
|
|
6
|
+
* the font payload out of the native bundle entirely. Idempotent: safe to
|
|
7
7
|
* call multiple times; subsequent calls early-return after the
|
|
8
8
|
* `<style id="bloom-fonts">` tag has been mounted. SSR-safe via the
|
|
9
9
|
* `typeof document === 'undefined'` guard.
|
|
10
|
+
*
|
|
11
|
+
* The font URLs come from `./font-data.web`, a generated module that
|
|
12
|
+
* embeds the woff2 bytes as base64 data URLs. Inlining (rather than
|
|
13
|
+
* relying on bundler asset loaders for `.woff2`) means consumers do not
|
|
14
|
+
* have to extend Metro's `assetExts` or add a webpack/Vite asset rule —
|
|
15
|
+
* the published JS is self-contained. See `scripts/generate-font-data.mjs`
|
|
16
|
+
* for the rationale and trade-offs.
|
|
10
17
|
*/
|
|
11
18
|
export declare function applyFontFaces(): void;
|
|
12
19
|
//# sourceMappingURL=apply-font-faces.web.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-font-faces.web.d.ts","sourceRoot":"","sources":["../../../../src/fonts/apply-font-faces.web.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apply-font-faces.web.d.ts","sourceRoot":"","sources":["../../../../src/fonts/apply-font-faces.web.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAkBrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-data.web.d.ts","sourceRoot":"","sources":["../../../../src/fonts/font-data.web.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,qBAAqB,EAAE,MAA0oqG,CAAC;AAC/qqG,eAAO,MAAM,kBAAkB,EAAE,MAA8lqG,CAAC;AAChoqG,eAAO,MAAM,aAAa,EAAE,MAA039D,CAAC;AACv59D,eAAO,MAAM,iBAAiB,EAAE,MAA09tC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxyhq/bloom",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Bloom UI — Oxy ecosystem component library for React Native + Expo + Web",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -582,20 +582,42 @@
|
|
|
582
582
|
"license": "MIT",
|
|
583
583
|
"scripts": {
|
|
584
584
|
"generate:exports": "node scripts/generate-platform-exports.mjs",
|
|
585
|
-
"
|
|
585
|
+
"generate:font-data": "node scripts/generate-font-data.mjs",
|
|
586
|
+
"prebuild": "node scripts/generate-platform-exports.mjs && node scripts/generate-font-data.mjs",
|
|
586
587
|
"build": "bob build",
|
|
587
588
|
"test": "jest",
|
|
589
|
+
"pretest": "node scripts/generate-font-data.mjs",
|
|
588
590
|
"typescript": "tsc --noEmit",
|
|
591
|
+
"pretypescript": "node scripts/generate-font-data.mjs",
|
|
589
592
|
"clean": "rm -rf lib",
|
|
590
593
|
"prepare": "bob build || true",
|
|
591
|
-
"release": "rm -rf lib &&
|
|
594
|
+
"release": "rm -rf lib && bun run build && release-it",
|
|
595
|
+
"storybook": "storybook dev -p 6006 --no-open",
|
|
596
|
+
"storybook:build": "storybook build -o storybook-static"
|
|
597
|
+
},
|
|
598
|
+
"release-it": {
|
|
599
|
+
"git": {
|
|
600
|
+
"tagName": "@oxyhq/bloom@${version}",
|
|
601
|
+
"tagAnnotation": "Release @oxyhq/bloom@${version}",
|
|
602
|
+
"commitMessage": "chore: release @oxyhq/bloom@${version}"
|
|
603
|
+
},
|
|
604
|
+
"github": {
|
|
605
|
+
"release": true,
|
|
606
|
+
"releaseName": "@oxyhq/bloom@${version}"
|
|
607
|
+
},
|
|
608
|
+
"npm": {
|
|
609
|
+
"publish": true
|
|
610
|
+
}
|
|
592
611
|
},
|
|
593
612
|
"devDependencies": {
|
|
613
|
+
"@storybook/addon-docs": "^10",
|
|
614
|
+
"@storybook/react-vite": "^10",
|
|
594
615
|
"@testing-library/react-native": "^13.3.3",
|
|
595
616
|
"@types/jest": "^30.0.0",
|
|
596
617
|
"@types/react": "~19.1.0",
|
|
597
618
|
"@types/react-dom": "^19.2.3",
|
|
598
619
|
"@types/react-native": "*",
|
|
620
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
599
621
|
"expo-font": "^56.0.5",
|
|
600
622
|
"jest": "^30.3.0",
|
|
601
623
|
"jest-environment-jsdom": "^30.4.1",
|
|
@@ -607,12 +629,15 @@
|
|
|
607
629
|
"react-native-reanimated": "^4.2.2",
|
|
608
630
|
"react-native-safe-area-context": "~5.6.0",
|
|
609
631
|
"react-native-svg": "^15.15.3",
|
|
632
|
+
"react-native-web": "^0.21.2",
|
|
610
633
|
"react-test-renderer": "^19.2.0",
|
|
611
634
|
"release-it": "^19.0.6",
|
|
612
635
|
"sonner": "^2.0.3",
|
|
613
636
|
"sonner-native": "^0.23.1",
|
|
637
|
+
"storybook": "^10",
|
|
614
638
|
"ts-jest": "^29.4.6",
|
|
615
|
-
"typescript": "~5.9.2"
|
|
639
|
+
"typescript": "~5.9.2",
|
|
640
|
+
"vite": "^7"
|
|
616
641
|
},
|
|
617
642
|
"peerDependencies": {
|
|
618
643
|
"expo": "*",
|
|
@@ -656,6 +681,7 @@
|
|
|
656
681
|
"react-native-builder-bob": {
|
|
657
682
|
"source": "src",
|
|
658
683
|
"output": "lib",
|
|
684
|
+
"exclude": "{**/{__tests__,__fixtures__,__mocks__}/**,**/*.stories.{ts,tsx},**/*.{test,spec}.{ts,tsx},**/*.woff2}",
|
|
659
685
|
"targets": [
|
|
660
686
|
[
|
|
661
687
|
"commonjs",
|
|
@@ -669,7 +695,12 @@
|
|
|
669
695
|
"esm": true
|
|
670
696
|
}
|
|
671
697
|
],
|
|
672
|
-
|
|
698
|
+
[
|
|
699
|
+
"typescript",
|
|
700
|
+
{
|
|
701
|
+
"project": "tsconfig.build.json"
|
|
702
|
+
}
|
|
703
|
+
]
|
|
673
704
|
]
|
|
674
705
|
},
|
|
675
706
|
"dependencies": {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
import { Avatar } from './Avatar';
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Avatar> = {
|
|
8
|
+
title: 'Components/Avatar',
|
|
9
|
+
component: Avatar,
|
|
10
|
+
argTypes: {
|
|
11
|
+
size: {
|
|
12
|
+
control: { type: 'number', min: 16, max: 256, step: 4 },
|
|
13
|
+
},
|
|
14
|
+
shape: {
|
|
15
|
+
control: 'select',
|
|
16
|
+
options: ['circle', 'squircle'],
|
|
17
|
+
},
|
|
18
|
+
verified: { control: 'boolean' },
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
|
|
24
|
+
type Story = StoryObj<typeof Avatar>;
|
|
25
|
+
|
|
26
|
+
const SAMPLE_URI =
|
|
27
|
+
'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200&h=200&fit=crop';
|
|
28
|
+
|
|
29
|
+
export const Basic: Story = {
|
|
30
|
+
args: { size: 64, name: 'Nate Isern' },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const FromUri: Story = {
|
|
34
|
+
args: { size: 64, uri: SAMPLE_URI },
|
|
35
|
+
name: 'From URI',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const Initials: Story = {
|
|
39
|
+
args: { size: 64, name: 'Ada Lovelace' },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const Squircle: Story = {
|
|
43
|
+
args: { size: 64, name: 'Ada Lovelace', shape: 'squircle' },
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const Sizes: Story = {
|
|
47
|
+
render: () => (
|
|
48
|
+
<View style={{ flexDirection: 'row', gap: 12, alignItems: 'center' }}>
|
|
49
|
+
<Avatar size={24} name="Ada" />
|
|
50
|
+
<Avatar size={32} name="Ada" />
|
|
51
|
+
<Avatar size={40} name="Ada" />
|
|
52
|
+
<Avatar size={56} name="Ada" />
|
|
53
|
+
<Avatar size={80} name="Ada" />
|
|
54
|
+
<Avatar size={120} name="Ada" />
|
|
55
|
+
</View>
|
|
56
|
+
),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const Composition: Story = {
|
|
60
|
+
render: () => (
|
|
61
|
+
<View style={{ flexDirection: 'row', gap: 12, alignItems: 'center' }}>
|
|
62
|
+
<Avatar size={48} name="Ada Lovelace" />
|
|
63
|
+
<Avatar size={48} name="Grace Hopper" />
|
|
64
|
+
<Avatar size={48} name="Alan Turing" />
|
|
65
|
+
<Avatar size={48} name="Linus Torvalds" />
|
|
66
|
+
<Avatar size={48} name="Margaret Hamilton" />
|
|
67
|
+
</View>
|
|
68
|
+
),
|
|
69
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import { Text, View } from 'react-native';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
import { Button } from '../button';
|
|
6
|
+
import { BottomSheet, type BottomSheetRef } from './index';
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof BottomSheet> = {
|
|
9
|
+
title: 'Components/BottomSheet',
|
|
10
|
+
component: BottomSheet,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
|
|
15
|
+
type Story = StoryObj<typeof BottomSheet>;
|
|
16
|
+
|
|
17
|
+
function BasicSheet() {
|
|
18
|
+
const ref = useRef<BottomSheetRef>(null);
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
<Button onPress={() => ref.current?.present()}>Open sheet</Button>
|
|
22
|
+
<BottomSheet ref={ref}>
|
|
23
|
+
<View style={{ padding: 24, gap: 12 }}>
|
|
24
|
+
<Text style={{ fontSize: 20, fontWeight: '700' }}>Bottom sheet</Text>
|
|
25
|
+
<Text>
|
|
26
|
+
Pan down to close, or tap the backdrop. This is the default sheet
|
|
27
|
+
(flush, rounded top corners only).
|
|
28
|
+
</Text>
|
|
29
|
+
</View>
|
|
30
|
+
</BottomSheet>
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function DetachedSheet() {
|
|
36
|
+
const ref = useRef<BottomSheetRef>(null);
|
|
37
|
+
return (
|
|
38
|
+
<>
|
|
39
|
+
<Button onPress={() => ref.current?.present()}>Open detached</Button>
|
|
40
|
+
<BottomSheet ref={ref} detached>
|
|
41
|
+
<View style={{ padding: 24, gap: 12 }}>
|
|
42
|
+
<Text style={{ fontSize: 20, fontWeight: '700' }}>Detached</Text>
|
|
43
|
+
<Text>
|
|
44
|
+
Floating card with margins and rounded corners on all sides.
|
|
45
|
+
</Text>
|
|
46
|
+
</View>
|
|
47
|
+
</BottomSheet>
|
|
48
|
+
</>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function NonScrollableSheet() {
|
|
53
|
+
const ref = useRef<BottomSheetRef>(null);
|
|
54
|
+
return (
|
|
55
|
+
<>
|
|
56
|
+
<Button onPress={() => ref.current?.present()}>Open non-scrollable</Button>
|
|
57
|
+
<BottomSheet ref={ref} scrollable={false}>
|
|
58
|
+
<View style={{ padding: 24, gap: 12 }}>
|
|
59
|
+
<Text style={{ fontSize: 20, fontWeight: '700' }}>
|
|
60
|
+
Non-scrollable
|
|
61
|
+
</Text>
|
|
62
|
+
<Text>
|
|
63
|
+
Use when the body owns its own VirtualizedList (FlatList,
|
|
64
|
+
SectionList, etc.).
|
|
65
|
+
</Text>
|
|
66
|
+
</View>
|
|
67
|
+
</BottomSheet>
|
|
68
|
+
</>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const Basic: Story = {
|
|
73
|
+
render: () => <BasicSheet />,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const Detached: Story = {
|
|
77
|
+
render: () => <DetachedSheet />,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const NonScrollable: Story = {
|
|
81
|
+
render: () => <NonScrollableSheet />,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const Composition: Story = {
|
|
85
|
+
render: () => (
|
|
86
|
+
<View style={{ gap: 12, alignItems: 'flex-start' }}>
|
|
87
|
+
<BasicSheet />
|
|
88
|
+
<DetachedSheet />
|
|
89
|
+
<NonScrollableSheet />
|
|
90
|
+
</View>
|
|
91
|
+
),
|
|
92
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
import { Button } from './Button';
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Button> = {
|
|
8
|
+
title: 'Components/Button',
|
|
9
|
+
component: Button,
|
|
10
|
+
args: {
|
|
11
|
+
children: 'Button',
|
|
12
|
+
onPress: () => {},
|
|
13
|
+
},
|
|
14
|
+
argTypes: {
|
|
15
|
+
variant: {
|
|
16
|
+
control: 'select',
|
|
17
|
+
options: ['primary', 'secondary', 'inverse', 'icon', 'ghost', 'text'],
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
control: 'select',
|
|
21
|
+
options: ['small', 'medium', 'large'],
|
|
22
|
+
},
|
|
23
|
+
disabled: { control: 'boolean' },
|
|
24
|
+
loading: { control: 'boolean' },
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default meta;
|
|
29
|
+
|
|
30
|
+
type Story = StoryObj<typeof Button>;
|
|
31
|
+
|
|
32
|
+
export const Basic: Story = {
|
|
33
|
+
args: { children: 'Save' },
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const Primary: Story = {
|
|
37
|
+
args: { variant: 'primary', children: 'Primary' },
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const Secondary: Story = {
|
|
41
|
+
args: { variant: 'secondary', children: 'Secondary' },
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const Ghost: Story = {
|
|
45
|
+
args: { variant: 'ghost', children: 'Ghost' },
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const TextOnly: Story = {
|
|
49
|
+
args: { variant: 'text', children: 'Text button' },
|
|
50
|
+
name: 'Text',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const Inverse: Story = {
|
|
54
|
+
args: { variant: 'inverse', children: 'Inverse' },
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const Variants: Story = {
|
|
58
|
+
render: () => (
|
|
59
|
+
<View style={{ gap: 12, alignItems: 'flex-start' }}>
|
|
60
|
+
<Button variant="primary">Primary</Button>
|
|
61
|
+
<Button variant="secondary">Secondary</Button>
|
|
62
|
+
<Button variant="inverse">Inverse</Button>
|
|
63
|
+
<Button variant="ghost">Ghost</Button>
|
|
64
|
+
<Button variant="text">Text</Button>
|
|
65
|
+
</View>
|
|
66
|
+
),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const Sizes: Story = {
|
|
70
|
+
render: () => (
|
|
71
|
+
<View style={{ gap: 12, alignItems: 'flex-start' }}>
|
|
72
|
+
<Button size="small">Small</Button>
|
|
73
|
+
<Button size="medium">Medium</Button>
|
|
74
|
+
<Button size="large">Large</Button>
|
|
75
|
+
</View>
|
|
76
|
+
),
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const Loading: Story = {
|
|
80
|
+
args: { loading: true, children: 'Submitting' },
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const Disabled: Story = {
|
|
84
|
+
args: { disabled: true, children: 'Disabled' },
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const Composition: Story = {
|
|
88
|
+
render: () => (
|
|
89
|
+
<View style={{ flexDirection: 'row', gap: 12, flexWrap: 'wrap' }}>
|
|
90
|
+
<Button variant="primary">Save</Button>
|
|
91
|
+
<Button variant="secondary">Cancel</Button>
|
|
92
|
+
</View>
|
|
93
|
+
),
|
|
94
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Pressable, Text, View } from 'react-native';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
import { useTheme } from '../theme/use-theme';
|
|
6
|
+
import * as ContextMenu from './index';
|
|
7
|
+
|
|
8
|
+
const meta: Meta = {
|
|
9
|
+
title: 'Components/ContextMenu',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
|
|
14
|
+
type Story = StoryObj;
|
|
15
|
+
|
|
16
|
+
function TriggerSurface() {
|
|
17
|
+
const theme = useTheme();
|
|
18
|
+
return (
|
|
19
|
+
<ContextMenu.Root>
|
|
20
|
+
<ContextMenu.Trigger label="Long-press for actions">
|
|
21
|
+
{({ props }) => (
|
|
22
|
+
<Pressable
|
|
23
|
+
onPress={() => props.onPress?.()}
|
|
24
|
+
onLongPress={() => props.onLongPress?.()}
|
|
25
|
+
accessibilityLabel={props.accessibilityLabel}
|
|
26
|
+
accessibilityHint={props.accessibilityHint}
|
|
27
|
+
style={{
|
|
28
|
+
padding: 24,
|
|
29
|
+
borderRadius: 12,
|
|
30
|
+
backgroundColor: theme.colors.backgroundSecondary,
|
|
31
|
+
borderWidth: 1,
|
|
32
|
+
borderColor: theme.colors.borderLight,
|
|
33
|
+
minWidth: 240,
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<Text style={{ color: theme.colors.text }}>
|
|
38
|
+
Long-press / right-click me
|
|
39
|
+
</Text>
|
|
40
|
+
</Pressable>
|
|
41
|
+
)}
|
|
42
|
+
</ContextMenu.Trigger>
|
|
43
|
+
<ContextMenu.Outer>
|
|
44
|
+
<ContextMenu.Group>
|
|
45
|
+
<ContextMenu.Item label="Open" onPress={() => {}}>
|
|
46
|
+
<ContextMenu.ItemText>Open</ContextMenu.ItemText>
|
|
47
|
+
</ContextMenu.Item>
|
|
48
|
+
<ContextMenu.Item label="Rename" onPress={() => {}}>
|
|
49
|
+
<ContextMenu.ItemText>Rename</ContextMenu.ItemText>
|
|
50
|
+
</ContextMenu.Item>
|
|
51
|
+
<ContextMenu.Item label="Delete" onPress={() => {}}>
|
|
52
|
+
<ContextMenu.ItemText>Delete</ContextMenu.ItemText>
|
|
53
|
+
</ContextMenu.Item>
|
|
54
|
+
</ContextMenu.Group>
|
|
55
|
+
</ContextMenu.Outer>
|
|
56
|
+
</ContextMenu.Root>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const Basic: Story = {
|
|
61
|
+
render: () => <TriggerSurface />,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const Composition: Story = {
|
|
65
|
+
render: () => (
|
|
66
|
+
<View style={{ gap: 16 }}>
|
|
67
|
+
<TriggerSurface />
|
|
68
|
+
<TriggerSurface />
|
|
69
|
+
</View>
|
|
70
|
+
),
|
|
71
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text, View } from 'react-native';
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
4
|
+
|
|
5
|
+
import { Button } from '../button';
|
|
6
|
+
import { Dialog } from './Dialog';
|
|
7
|
+
import { useDialogControl } from './context';
|
|
8
|
+
import { alert } from './alert';
|
|
9
|
+
|
|
10
|
+
const meta: Meta<typeof Dialog> = {
|
|
11
|
+
title: 'Components/Dialog',
|
|
12
|
+
component: Dialog,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
|
|
17
|
+
type Story = StoryObj<typeof Dialog>;
|
|
18
|
+
|
|
19
|
+
function DeclarativeDemo() {
|
|
20
|
+
const control = useDialogControl();
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<Button onPress={() => control.open()}>Open dialog</Button>
|
|
24
|
+
<Dialog
|
|
25
|
+
control={control}
|
|
26
|
+
title="Sign out?"
|
|
27
|
+
description="You'll need to enter your password to sign in again."
|
|
28
|
+
actions={[
|
|
29
|
+
{ label: 'Sign out', color: 'destructive' },
|
|
30
|
+
{ label: 'Cancel', color: 'cancel' },
|
|
31
|
+
]}
|
|
32
|
+
/>
|
|
33
|
+
</>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function CustomChildrenDemo() {
|
|
38
|
+
const control = useDialogControl();
|
|
39
|
+
return (
|
|
40
|
+
<>
|
|
41
|
+
<Button onPress={() => control.open()}>Open custom dialog</Button>
|
|
42
|
+
<Dialog control={control} title="Custom body">
|
|
43
|
+
<View style={{ gap: 12 }}>
|
|
44
|
+
<Text>Render any JSX inside the dialog body.</Text>
|
|
45
|
+
<Button variant="secondary" onPress={() => control.close()}>
|
|
46
|
+
Done
|
|
47
|
+
</Button>
|
|
48
|
+
</View>
|
|
49
|
+
</Dialog>
|
|
50
|
+
</>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function AlertDemo() {
|
|
55
|
+
return (
|
|
56
|
+
<Button
|
|
57
|
+
onPress={() =>
|
|
58
|
+
alert('Delete project?', 'This action cannot be undone.', [
|
|
59
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
60
|
+
{ text: 'Delete', style: 'destructive' },
|
|
61
|
+
])
|
|
62
|
+
}
|
|
63
|
+
>
|
|
64
|
+
Trigger alert()
|
|
65
|
+
</Button>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function ThreeActionDemo() {
|
|
70
|
+
const control = useDialogControl();
|
|
71
|
+
return (
|
|
72
|
+
<>
|
|
73
|
+
<Button onPress={() => control.open()}>Three actions</Button>
|
|
74
|
+
<Dialog
|
|
75
|
+
control={control}
|
|
76
|
+
title="Save changes?"
|
|
77
|
+
description="You have unsaved changes."
|
|
78
|
+
actions={[
|
|
79
|
+
{ label: 'Save', color: 'default' },
|
|
80
|
+
{ label: 'Discard', color: 'destructive' },
|
|
81
|
+
{ label: 'Cancel', color: 'cancel' },
|
|
82
|
+
]}
|
|
83
|
+
/>
|
|
84
|
+
</>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export const Basic: Story = {
|
|
89
|
+
render: () => <DeclarativeDemo />,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const CustomChildren: Story = {
|
|
93
|
+
render: () => <CustomChildrenDemo />,
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const AlertHelper: Story = {
|
|
97
|
+
render: () => <AlertDemo />,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const ThreeAction: Story = {
|
|
101
|
+
render: () => <ThreeActionDemo />,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const Composition: Story = {
|
|
105
|
+
render: () => (
|
|
106
|
+
<View style={{ gap: 12, alignItems: 'flex-start' }}>
|
|
107
|
+
<DeclarativeDemo />
|
|
108
|
+
<CustomChildrenDemo />
|
|
109
|
+
<AlertDemo />
|
|
110
|
+
</View>
|
|
111
|
+
),
|
|
112
|
+
};
|
package/src/fonts/FontLoader.tsx
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React, { useRef } from 'react';
|
|
2
2
|
// Reach for the web variant explicitly. The default `./apply-font-faces`
|
|
3
|
-
// is a no-op stub
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// bundlers — Metro selects `FontLoader.native.tsx` on iOS/Android
|
|
7
|
-
// is safe to take a direct dependency on the web implementation
|
|
3
|
+
// is a no-op stub on native — native loads its fonts via
|
|
4
|
+
// `useFonts(FONT_ASSETS)` in `FontLoader.native.tsx` and has no use for
|
|
5
|
+
// CSS `@font-face` injection. This file (`FontLoader.tsx`) is only picked
|
|
6
|
+
// up by web bundlers — Metro selects `FontLoader.native.tsx` on iOS/Android
|
|
7
|
+
// — so it is safe to take a direct dependency on the web implementation
|
|
8
|
+
// here.
|
|
8
9
|
import { applyFontFaces } from './apply-font-faces.web';
|
|
9
10
|
|
|
10
11
|
export interface FontLoaderProps {
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// is selected by bundlers via the package.json conditions. RN consumers
|
|
3
3
|
// never need font-face injection — useFonts handles loading on native.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
// imports
|
|
7
|
-
//
|
|
8
|
-
//
|
|
5
|
+
// The web variant does NOT pull in any `.woff2` files via asset imports —
|
|
6
|
+
// it imports base64 data URLs from `font-data.web.ts`. This stub stays
|
|
7
|
+
// here so the file split (`*.ts` vs `*.web.ts`) makes the platform
|
|
8
|
+
// intent explicit and so the runtime API surface matches across platforms.
|
|
9
9
|
export function applyFontFaces(): void {
|
|
10
10
|
// intentionally empty
|
|
11
11
|
}
|