From e87783dcf29c06e2414f43c46326072f098a3df2 Mon Sep 17 00:00:00 2001 From: Pete Watters <2938440+pete-watters@users.noreply.github.com> Date: Tue, 17 Sep 2024 11:11:20 +0100 Subject: [PATCH] feat: add collectibles widget, ref leather-io/issues#222 --- apps/mobile/src/components/home/home.tsx | 6 + .../collectibles/collectibles-header.tsx | 32 ++ .../collectibles-widget.layout.tsx | 31 ++ .../collectibles/collectibles-widget.tsx | 35 +++ .../collectibles/collectibles.mocks.tsx | 293 ++++++++++++++++++ .../components/collectible-card-layout.tsx | 15 + .../components/collectible-card.tsx | 35 +++ .../components/collectible-html.tsx | 15 + .../components/collectible-image.tsx | 15 + .../components/collectible-text.tsx | 45 +++ apps/mobile/src/locales/en/messages.po | 12 +- .../src/locales/pseudo-locale/messages.po | 8 +- packages/ui/native.ts | 2 +- packages/ui/src/components/box/box.native.tsx | 2 + 14 files changed, 539 insertions(+), 7 deletions(-) create mode 100644 apps/mobile/src/components/widgets/collectibles/collectibles-header.tsx create mode 100644 apps/mobile/src/components/widgets/collectibles/collectibles-widget.layout.tsx create mode 100644 apps/mobile/src/components/widgets/collectibles/collectibles-widget.tsx create mode 100644 apps/mobile/src/components/widgets/collectibles/collectibles.mocks.tsx create mode 100644 apps/mobile/src/components/widgets/collectibles/components/collectible-card-layout.tsx create mode 100644 apps/mobile/src/components/widgets/collectibles/components/collectible-card.tsx create mode 100644 apps/mobile/src/components/widgets/collectibles/components/collectible-html.tsx create mode 100644 apps/mobile/src/components/widgets/collectibles/components/collectible-image.tsx create mode 100644 apps/mobile/src/components/widgets/collectibles/components/collectible-text.tsx diff --git a/apps/mobile/src/components/home/home.tsx b/apps/mobile/src/components/home/home.tsx index 6a5341d92..03adc73db 100644 --- a/apps/mobile/src/components/home/home.tsx +++ b/apps/mobile/src/components/home/home.tsx @@ -1,4 +1,6 @@ import { AccountsWidget } from '@/components/widgets/accounts/accounts-widget'; +import { CollectiblesWidget } from '@/components/widgets/collectibles/collectibles-widget'; +import { mockCollectibles } from '@/components/widgets/collectibles/collectibles.mocks'; import { TokensWidget } from '@/components/widgets/tokens/tokens-widget'; import { getMockTokens, mockTotalBalance } from '@/components/widgets/tokens/tokens.mocks'; import { useAccounts } from '@/store/accounts/accounts.read'; @@ -16,6 +18,10 @@ export function Home() { + ); } diff --git a/apps/mobile/src/components/widgets/collectibles/collectibles-header.tsx b/apps/mobile/src/components/widgets/collectibles/collectibles-header.tsx new file mode 100644 index 000000000..9d8b8af7e --- /dev/null +++ b/apps/mobile/src/components/widgets/collectibles/collectibles-header.tsx @@ -0,0 +1,32 @@ +import React from 'react'; + +import { t } from '@lingui/macro'; + +import { Box, ChevronRightIcon, Chip, SheetRef, Text } from '@leather.io/ui/native'; + +import { FiatBalance } from '../components/balance/fiat-balance'; + +interface CollectiblesHeaderProps { + collectibleCount: number; + sheetRef: React.RefObject; + totalBalance: string; +} + +function CollectiblesHeaderText() { + return {t`My collectibles`}; +} + +export function CollectiblesHeader({ collectibleCount, totalBalance }: CollectiblesHeaderProps) { + const hasCollectibles = collectibleCount > 0; + if (!hasCollectibles) return ; + return ( + + + + + + + + + ); +} diff --git a/apps/mobile/src/components/widgets/collectibles/collectibles-widget.layout.tsx b/apps/mobile/src/components/widgets/collectibles/collectibles-widget.layout.tsx new file mode 100644 index 000000000..b454fdca1 --- /dev/null +++ b/apps/mobile/src/components/widgets/collectibles/collectibles-widget.layout.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { ScrollView } from 'react-native-gesture-handler'; + +import { useTheme } from '@shopify/restyle'; + +import { Box, SheetRef, Theme } from '@leather.io/ui/native'; + +import { Widget } from '../widget'; + +interface CollectiblesWidgetProps { + balance?: React.ReactNode; + children: React.ReactNode; + header?: React.ReactNode; + sheetRef?: React.RefObject; +} + +export function CollectiblesWidgetLayout({ children, header }: CollectiblesWidgetProps) { + const theme = useTheme(); + return ( + + {header} + + {children} + + + ); +} diff --git a/apps/mobile/src/components/widgets/collectibles/collectibles-widget.tsx b/apps/mobile/src/components/widgets/collectibles/collectibles-widget.tsx new file mode 100644 index 000000000..c0cc0586c --- /dev/null +++ b/apps/mobile/src/components/widgets/collectibles/collectibles-widget.tsx @@ -0,0 +1,35 @@ +import React, { useRef } from 'react'; + +import { SheetRef } from '@leather.io/ui/native'; + +import { TokenBalance } from '../components/balance/token-balance'; +import { CollectiblesHeader } from './collectibles-header'; +import { CollectiblesWidgetLayout } from './collectibles-widget.layout'; +import { type Collectible } from './collectibles.mocks'; +import { CollectiblesCard } from './components/collectible-card'; + +interface CollectiblesWidgetProps { + collectibles: Collectible[]; + totalBalance: string; +} + +export function CollectiblesWidget({ collectibles, totalBalance }: CollectiblesWidgetProps) { + const sheetRef = useRef(null); + + return ( + + } + balance={collectibles.length > 0 && } + > + {collectibles.map((collectible: Collectible, index: number) => ( + + ))} + + ); +} diff --git a/apps/mobile/src/components/widgets/collectibles/collectibles.mocks.tsx b/apps/mobile/src/components/widgets/collectibles/collectibles.mocks.tsx new file mode 100644 index 000000000..769ba58f5 --- /dev/null +++ b/apps/mobile/src/components/widgets/collectibles/collectibles.mocks.tsx @@ -0,0 +1,293 @@ +/* eslint-disable */ + +// provided by useTotalBalance hook in extension/src/app/common/hooks/balance/use-total-balance.tsx + +export const mockTotalBalance = { + totalUsdBalance: '$126.74', + totalBtcBalance: '0.00215005', + totalStxBalance: '0.0024', +}; + +export interface Ordinal { + id: string; + number: number; + output: string; + txid: string; + offset: string; + address: string; + preview: string; + title: string; + genesisBlockHeight: number; + genesisBlockHash: string; + genesisTimestamp: number; + value: string; + mimeType: string; + name: string; + src: string; +} + +const mockOrdinals: Ordinal[] = [ + { + id: 'a494e48bf7120c959239e8c544bc821ca4fb5a46e5fff79938943d434f252949i0', + number: 74703951, + output: '0', + txid: 'a494e48bf7120c959239e8c544bc821ca4fb5a46e5fff79938943d434f252949', + offset: '0', + address: 'bc1pwz9n62p9dhjpqcpdmfcrewdnz3nk8jcved242vd2lj9fgvtvwnwscvdyre', + preview: + 'https://ordinals.hiro.so/inscription/a494e48bf7120c959239e8c544bc821ca4fb5a46e5fff79938943d434f252949i0', + title: 'Inscription 74703951', + genesisBlockHeight: 857719, + genesisBlockHash: '00000000000000000002bc6789fc6742da4958d003d3abff740687a863613a46', + genesisTimestamp: 1724219117, + value: '546', + mimeType: 'html', + name: 'inscription', + src: 'https://ordinals.com/preview/a494e48bf7120c959239e8c544bc821ca4fb5a46e5fff79938943d434f252949i0', + }, + { + id: '335209b72c452f52199ae09e8ce586a451ce452c73326f01f958d8aa8417e062i0', + number: 73858867, + output: '0', + txid: '335209b72c452f52199ae09e8ce586a451ce452c73326f01f958d8aa8417e062', + offset: '0', + address: 'bc1pwz9n62p9dhjpqcpdmfcrewdnz3nk8jcved242vd2lj9fgvtvwnwscvdyre', + preview: + 'https://ordinals.hiro.so/inscription/335209b72c452f52199ae09e8ce586a451ce452c73326f01f958d8aa8417e062i0', + title: 'Inscription 73858867', + genesisBlockHeight: 855754, + genesisBlockHash: '000000000000000000021972c2000a8d347dbac1a2540112fadf81219b188796', + genesisTimestamp: 1723027746, + value: '546', + mimeType: 'text', + name: 'inscription', + src: 'https://bis-ord-content.fra1.cdn.digitaloceanspaces.com/ordinals/335209b72c452f52199ae09e8ce586a451ce452c73326f01f958d8aa8417e062i0', + }, + // ... (other ordinals) + // on leather dev wallet all seem to be mimeType: 'text' / 'html +]; + +export interface StacksNft { + token_uri: string; + metadata: { + sip: number; + name: string; + description: string; + image: string; + cached_image: string; + cached_thumbnail_image: string; + attributes?: Array<{ + trait_type: string; + value: string; + display_type?: string; + }>; + properties?: { + collection?: string; + collectionId?: string; + [key: string]: any; + }; + }; +} + +const mockStacksNfts: StacksNft[] = [ + { + token_uri: 'ipfs://ipfs/QmQ63rXC9F7GyLYoYNyqxeiYvbBUvmHmL36PrfYNxpw5sT/90.json', + metadata: { + sip: 16, + name: 'BlockSurvey #90', + description: 'Worlds First Software License as an NFT', + image: 'ipfs://QmZXkLMrN2ejpzGv1wk4HgcuL6XbyLVieW3Zm9wyAoDk18/90.png', + cached_image: + 'https://assets.hiro.so/api/mainnet/token-metadata-api/SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.blocksurvey/90.png', + cached_thumbnail_image: + 'https://assets.hiro.so/api/mainnet/token-metadata-api/SPNWZ5V2TPWGQGVDR6T7B6RQ4XMGZ4PXTEE0VQ0S.blocksurvey/90-thumb.png', + attributes: [ + { + trait_type: 'NightBackground', + value: 'MidnightMoss', + display_type: '', + }, + { + trait_type: 'NightLogo', + value: 'AtomicTangerine', + display_type: '', + }, + { + trait_type: 'SignatureWhite', + value: 'SignatureWhite', + display_type: '', + }, + ], + }, + }, + { + token_uri: 'ipfs://ipfs/QmWRQyaVxUjHGjBUoZqGcNjL37VN99jcFwmoB1wZnpjJEg/', + metadata: { + sip: 16, + name: 'Portals-ALEX-Anniversary-Series', + description: 'From proof-of-concept to bringing Bitcoin value to the multi-chain.\n', + image: 'ipfs://ipfs/QmUgHdbTy5LYi4wijf9YJgGs89SCAKNbXascvzuFgAsMB9', + cached_image: + 'https://assets.hiro.so/api/mainnet/token-metadata-api/SP3N7Y3K01Y24G9JC1XXA13RQXXCY721WAVBMMD38.alex-anniversary-series/1452.png', + cached_thumbnail_image: + 'https://assets.hiro.so/api/mainnet/token-metadata-api/SP3N7Y3K01Y24G9JC1XXA13RQXXCY721WAVBMMD38.alex-anniversary-series/1452-thumb.png', + properties: { + collection: 'ALEX Anniversary Series', + }, + }, + }, + { + token_uri: 'ipfs://QmYTX3u58v2Ero2drdtqhL6rPE5qnv51EJZ6WSu3LKqUBN/crashpunks-5559.json', + metadata: { + sip: 16, + name: 'Crash Punk 5559', + description: '', + image: 'ipfs://Qmb84UcaMr1MUwNbYBnXWHM3kEaDcYrKuPWwyRLVTNKELC/5559.png', + cached_image: + 'https://assets.hiro.so/api/mainnet/token-metadata-api/SP3QSAJQ4EA8WXEDSRRKMZZ29NH91VZ6C5X88FGZQ.crashpunks-v2/5559.png', + cached_thumbnail_image: + 'https://assets.hiro.so/api/mainnet/token-metadata-api/SP3QSAJQ4EA8WXEDSRRKMZZ29NH91VZ6C5X88FGZQ.crashpunks-v2/5559-thumb.png', + attributes: [ + { + trait_type: 'Background', + value: 'Blue', + display_type: 'string', + }, + { + trait_type: 'Outfit Back', + value: 'Stacks Hoodie Back', + display_type: 'string', + }, + { + trait_type: 'Neck', + value: 'Neck Metal', + display_type: 'string', + }, + { + trait_type: 'Outfit Front', + value: 'Stacks Hoodie', + display_type: 'string', + }, + { + trait_type: 'Head', + value: 'Head Tan', + display_type: 'string', + }, + { + trait_type: 'Piercings', + value: 'Piercings', + display_type: 'string', + }, + { + trait_type: 'Mouth', + value: 'Lips Bare', + display_type: 'string', + }, + { + trait_type: 'Eyes', + value: 'RoboEyes Blue', + display_type: 'string', + }, + { + trait_type: 'Hair', + value: 'Bob Silver', + display_type: 'string', + }, + ], + properties: { + collection: 'Crash Punks', + collectionId: 'grace.btc/crash_punks', + dna: '5c2f54662bb494b5e4ebc195070d9ce624c5a849', + total_supply: '9216', + external_url: + 'https://thisisnumberone.com/nfts/SP3QSAJQ4EA8WXEDSRRKMZZ29NH91VZ6C5X88FGZQ.crashpunks-v2/5559', + }, + }, + }, + { + token_uri: 'ipfs://ipfs/QmZYoSr94MKdarScJZSsyBYxBgMJchUQqqbtLxxxR86wZN/', + metadata: { + sip: 16, + name: 'WORRY - NFT - MUSIC', + description: + 'Musical NFT Collection \nWorry is a self-reflective song done by Brythreesixty also known as 3hunnatheartist. Worry is an emotional state of being anxious and troubled over actual or potential problems. The greatest weapon is positivity. Welcome to my Bullish state of Mind. This collection is a gift to the community. Enjoy \n\nhttps://gamma.io/3hunnatheartist.btc\nhttps://gamma.io/brythreesixty\n\nhttps://twitter.com/brythreesixty\nhttps://twitter.com/3hunnatheartist\n\nhttps://discord.gg/hRqeVRFG', + image: '', + cached_image: '', + cached_thumbnail_image: '', + }, + }, + { + token_uri: 'ipfs://QmbMdASbHZb5XHizZJsFPL9hdmuDgekUHH9Ya1DnuSxfHj/1547.json', + metadata: { + sip: 16, + name: 'StacksMFers #1547', + description: 'Just a bunch of mfers on stacks', + image: 'ipfs://QmUL7yELAmF1wnbqt6yaNLmCVbBa7BSbSNXYKijpku2r45/1547.png', + cached_image: + 'https://assets.hiro.so/api/mainnet/token-metadata-api/SP2N3BAG4GBF8NHRPH6AY4YYH1SP6NK5TGCY7RDFA.stacks-mfers/1547.png', + cached_thumbnail_image: + 'https://assets.hiro.so/api/mainnet/token-metadata-api/SP2N3BAG4GBF8NHRPH6AY4YYH1SP6NK5TGCY7RDFA.stacks-mfers/1547-thumb.png', + attributes: [ + { + trait_type: 'BG', + value: 'Pixels', + display_type: '', + }, + { + trait_type: 'Type', + value: 'Plain', + display_type: '', + }, + { + trait_type: 'Eyes', + value: 'Greenglasses', + display_type: '', + }, + { + trait_type: 'Mouth', + value: 'Smile', + display_type: '', + }, + { + trait_type: 'Beard', + value: 'None', + display_type: '', + }, + { + trait_type: 'Shirt', + value: 'GreenHoodie', + display_type: '', + }, + { + trait_type: 'Accessory', + value: 'None', + display_type: '', + }, + { + trait_type: 'LongHair', + value: 'LongBlue', + display_type: '', + }, + { + trait_type: 'Hat under', + value: 'RedBandana', + display_type: '', + }, + { + trait_type: 'Headphones', + value: 'Red', + display_type: '', + }, + { + trait_type: 'Smoke', + value: 'None', + display_type: '', + }, + ], + }, + }, +]; + +export type Collectible = Ordinal | StacksNft; + +export const mockCollectibles: (Ordinal | StacksNft)[] = [...mockOrdinals, ...mockStacksNfts]; diff --git a/apps/mobile/src/components/widgets/collectibles/components/collectible-card-layout.tsx b/apps/mobile/src/components/widgets/collectibles/components/collectible-card-layout.tsx new file mode 100644 index 000000000..b620d95ca --- /dev/null +++ b/apps/mobile/src/components/widgets/collectibles/components/collectible-card-layout.tsx @@ -0,0 +1,15 @@ +import { BaseTheme, BoxProps } from '@shopify/restyle'; + +import { Box, Theme } from '@leather.io/ui/native'; + +type CollectiblesCardLayoutProps = BoxProps & { + children: React.ReactNode; +}; + +export function CollectiblesCardLayout({ children, ...props }: CollectiblesCardLayoutProps) { + return ( + + {children} + + ); +} diff --git a/apps/mobile/src/components/widgets/collectibles/components/collectible-card.tsx b/apps/mobile/src/components/widgets/collectibles/components/collectible-card.tsx new file mode 100644 index 000000000..04ff622ac --- /dev/null +++ b/apps/mobile/src/components/widgets/collectibles/components/collectible-card.tsx @@ -0,0 +1,35 @@ +import React from 'react'; + +import { t } from '@lingui/macro'; + +import { type Collectible } from '../collectibles.mocks'; +import { CollectibleHtml } from './collectible-html'; +import { CollectibleImage } from './collectible-image'; +import { CollectibleText } from './collectible-text'; + +interface CollectiblesCardProps { + collectible: Collectible; +} + +export function CollectiblesCard({ collectible }: CollectiblesCardProps) { + const isOrdinal = 'name' in collectible; + + const imageSource = isOrdinal ? collectible.src : collectible.metadata.cached_thumbnail_image; + + if (isOrdinal) { + switch (collectible.mimeType) { + case 'text': + return ; + case 'html': + return ; + // Add more cases for other mimeTypes as needed + } + } + + return ( + + ); +} diff --git a/apps/mobile/src/components/widgets/collectibles/components/collectible-html.tsx b/apps/mobile/src/components/widgets/collectibles/components/collectible-html.tsx new file mode 100644 index 000000000..27c7f3b57 --- /dev/null +++ b/apps/mobile/src/components/widgets/collectibles/components/collectible-html.tsx @@ -0,0 +1,15 @@ +import { WebView } from 'react-native-webview'; + +import { CollectiblesCardLayout } from './collectible-card-layout'; + +interface CollectibleHtmlProps { + src: string; +} + +export function CollectibleHtml({ src }: CollectibleHtmlProps) { + return ( + + + + ); +} diff --git a/apps/mobile/src/components/widgets/collectibles/components/collectible-image.tsx b/apps/mobile/src/components/widgets/collectibles/components/collectible-image.tsx new file mode 100644 index 000000000..d74e18be9 --- /dev/null +++ b/apps/mobile/src/components/widgets/collectibles/components/collectible-image.tsx @@ -0,0 +1,15 @@ +import { Image } from 'react-native'; + +import { Box } from '@leather.io/ui/native'; + +interface CollectibleImageProps { + alt: string; + source: string; +} +export function CollectibleImage({ alt, source }: CollectibleImageProps) { + return ( + + {alt} + + ); +} diff --git a/apps/mobile/src/components/widgets/collectibles/components/collectible-text.tsx b/apps/mobile/src/components/widgets/collectibles/components/collectible-text.tsx new file mode 100644 index 000000000..a0239ac84 --- /dev/null +++ b/apps/mobile/src/components/widgets/collectibles/components/collectible-text.tsx @@ -0,0 +1,45 @@ +// FIXME: Lifted from extension +// // TODO: migrate `collectible-type` components to monorepo +// FIXME when using real data sanitization is needed +// import { sanitize } from 'dompurify'; +import { useEffect, useState } from 'react'; + +import { Text } from '@leather.io/ui/native'; + +import { CollectiblesCardLayout } from './collectible-card-layout'; + +interface CollectibleTextProps { + src: string; +} + +export function CollectibleText({ src }: CollectibleTextProps) { + const [content, setContent] = useState(null); + + useEffect(() => { + const fetchContent = async () => { + try { + const response = await fetch(src); + if (!response.ok) { + throw new Error('Network response was not ok'); + } + const data = await response.json(); + setContent(JSON.stringify(data, null, 2)); + } catch (err) { + // eslint-disable-next-line no-console, lingui/no-unlocalized-strings + console.log('Error fetching content:', err); + } + }; + + fetchContent(); + }, [src]); + + return ( + + + {/* FIXME when using real data sanitization is needed */} + {/* {sanitize(children)} */} + {content} + + + ); +} diff --git a/apps/mobile/src/locales/en/messages.po b/apps/mobile/src/locales/en/messages.po index 2b38aad80..2d78b63de 100644 --- a/apps/mobile/src/locales/en/messages.po +++ b/apps/mobile/src/locales/en/messages.po @@ -172,7 +172,7 @@ msgstr "Avatar" #: src/components/create-new-wallet/mnemonic-display.tsx:13 #: src/components/recover-wallet/recover-wallet-sheet.tsx:28 msgid "BIP39 passphrase" -msgstr "BIP39 passphrase<<<<<<< HEAD" +msgstr "BIP39 passphrase" #: src/components/widgets/tokens/tokens.mocks.tsx:50 msgid "Bitcoin" @@ -180,11 +180,11 @@ msgstr "Bitcoin" #: src/components/widgets/tokens/tokens.mocks.tsx:27 msgid "Bitcoin blockchain" -msgstr "Bitcoin blockchain>>>>>>> bbb518c (feat: add tokens widget, ref leather-io/issues#221)" +msgstr "Bitcoin blockchain" #: src/app/wallet/developer-console/index.tsx:90 msgid "Bitcoin Scrach Pad" -msgstr "Bitcoin Scrach Pad=======" +msgstr "Bitcoin Scrach Pad" #: src/app/wallet/settings/display/index.tsx:44 #: src/features/settings/bitcoin-unit-sheet/bitcoin-unit-sheet.tsx:29 @@ -490,7 +490,11 @@ msgstr "Must use physical device for Push Notifications" #: src/components/widgets/accounts/accounts-header.tsx:14 msgid "My accounts" -msgstr "My accounts<<<<<<< HEAD" +msgstr "My account" + +#: src/components/widgets/collectibles/collectibles-header.tsx:16 +msgid "My collectibles" +msgstr "My collectibles" #: src/components/widgets/tokens/tokens-header.tsx:18 msgid "My tokens" diff --git a/apps/mobile/src/locales/pseudo-locale/messages.po b/apps/mobile/src/locales/pseudo-locale/messages.po index 08a40a2f6..c12b2b9f4 100644 --- a/apps/mobile/src/locales/pseudo-locale/messages.po +++ b/apps/mobile/src/locales/pseudo-locale/messages.po @@ -172,7 +172,7 @@ msgstr "" #: src/components/create-new-wallet/mnemonic-display.tsx:13 #: src/components/recover-wallet/recover-wallet-sheet.tsx:28 msgid "BIP39 passphrase" -msgstr "<<<<<<< HEAD" +msgstr "" #: src/components/widgets/tokens/tokens.mocks.tsx:50 msgid "Bitcoin" @@ -490,7 +490,11 @@ msgstr "" #: src/components/widgets/accounts/accounts-header.tsx:14 msgid "My accounts" -msgstr "<<<<<<< HEAD" +msgstr "" + +#: src/components/widgets/collectibles/collectibles-header.tsx:16 +msgid "My collectibles" +msgstr "" #: src/components/widgets/tokens/tokens-header.tsx:18 msgid "My tokens" diff --git a/packages/ui/native.ts b/packages/ui/native.ts index 06696ec47..4bd3942cb 100644 --- a/packages/ui/native.ts +++ b/packages/ui/native.ts @@ -3,7 +3,7 @@ export { Avatar } from './src/components/avatar/avatar.native'; export { BulletSeparator } from './src/components/bullet-separator/bullet-separator.native'; export { BtcAvatarIcon } from './src/components/avatar/btc-avatar-icon.native'; export { StxAvatarIcon } from './src/components/avatar/stx-avatar-icon.native'; -export { Box } from './src/components/box/box.native'; +export { Box, type BoxProps } from './src/components/box/box.native'; export { BlurView } from './src/components/blur-view/blur-view.native'; export { Chip } from './src/components/chip/chip.native'; export { HStack } from './src/components/box/hstack.native'; diff --git a/packages/ui/src/components/box/box.native.tsx b/packages/ui/src/components/box/box.native.tsx index bfa5e734b..7ac8e9a2e 100644 --- a/packages/ui/src/components/box/box.native.tsx +++ b/packages/ui/src/components/box/box.native.tsx @@ -2,4 +2,6 @@ import { createBox } from '@shopify/restyle'; import { type Theme } from '../../theme-native'; +export type { BoxProps } from '@shopify/restyle'; + export const Box = createBox();