@ankhorage/surface 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +7 -0
  3. package/dist/components/navigation/DrawerNavigation.d.ts +4 -0
  4. package/dist/components/navigation/DrawerNavigation.d.ts.map +1 -0
  5. package/dist/components/navigation/DrawerNavigation.js +13 -0
  6. package/dist/components/navigation/DrawerNavigation.js.map +1 -0
  7. package/dist/components/navigation/DrawerNavigationItem.d.ts +4 -0
  8. package/dist/components/navigation/DrawerNavigationItem.d.ts.map +1 -0
  9. package/dist/components/navigation/DrawerNavigationItem.js +9 -0
  10. package/dist/components/navigation/DrawerNavigationItem.js.map +1 -0
  11. package/dist/components/navigation/NavigationItem.d.ts +4 -0
  12. package/dist/components/navigation/NavigationItem.d.ts.map +1 -0
  13. package/dist/components/navigation/NavigationItem.js +41 -0
  14. package/dist/components/navigation/NavigationItem.js.map +1 -0
  15. package/dist/components/navigation/NavigationList.d.ts +4 -0
  16. package/dist/components/navigation/NavigationList.d.ts.map +1 -0
  17. package/dist/components/navigation/NavigationList.js +9 -0
  18. package/dist/components/navigation/NavigationList.js.map +1 -0
  19. package/dist/components/navigation/TabBar.d.ts +4 -0
  20. package/dist/components/navigation/TabBar.d.ts.map +1 -0
  21. package/dist/components/navigation/TabBar.js +15 -0
  22. package/dist/components/navigation/TabBar.js.map +1 -0
  23. package/dist/components/navigation/TabBarItem.d.ts +4 -0
  24. package/dist/components/navigation/TabBarItem.d.ts.map +1 -0
  25. package/dist/components/navigation/TabBarItem.js +44 -0
  26. package/dist/components/navigation/TabBarItem.js.map +1 -0
  27. package/dist/components/navigation/helpers.d.ts +15 -0
  28. package/dist/components/navigation/helpers.d.ts.map +1 -0
  29. package/dist/components/navigation/helpers.js +40 -0
  30. package/dist/components/navigation/helpers.js.map +1 -0
  31. package/dist/components/navigation/index.d.ts +8 -0
  32. package/dist/components/navigation/index.d.ts.map +1 -0
  33. package/dist/components/navigation/index.js +7 -0
  34. package/dist/components/navigation/index.js.map +1 -0
  35. package/dist/components/navigation/types.d.ts +51 -0
  36. package/dist/components/navigation/types.d.ts.map +1 -0
  37. package/dist/components/navigation/types.js +2 -0
  38. package/dist/components/navigation/types.js.map +1 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +1 -0
  42. package/dist/index.js.map +1 -1
  43. package/package.json +1 -1
  44. package/src/components/navigation/DrawerNavigation.tsx +25 -0
  45. package/src/components/navigation/DrawerNavigationItem.tsx +17 -0
  46. package/src/components/navigation/NavigationItem.tsx +77 -0
  47. package/src/components/navigation/NavigationList.tsx +24 -0
  48. package/src/components/navigation/TabBar.tsx +25 -0
  49. package/src/components/navigation/TabBarItem.tsx +82 -0
  50. package/src/components/navigation/helpers.test.ts +74 -0
  51. package/src/components/navigation/helpers.ts +72 -0
  52. package/src/components/navigation/index.ts +16 -0
  53. package/src/components/navigation/policy.test.ts +44 -0
  54. package/src/components/navigation/types.ts +59 -0
  55. package/src/index.test.ts +1 -0
  56. package/src/index.ts +18 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @ankhorage/surface
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e7ee603: add router-agnostic chrome primitives
8
+
3
9
  ## 1.0.3
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -39,3 +39,10 @@ import { Box, Text } from '@ankhorage/surface';
39
39
  ## 🧠 Why this exists
40
40
 
41
41
  Bridges the gap between raw primitives and full UI frameworks.
42
+
43
+ ## 🧭 Navigation chrome primitives
44
+
45
+ Surface includes **router-agnostic navigation chrome** building blocks (tab bars, drawer lists, route items).
46
+
47
+ - These components **do not** implement routing, route state, deep linking, or screen switching.
48
+ - Use **Expo Router / React Navigation** for navigation mechanics, and render UI with Surface by passing `active`, `disabled`, and `onPress`.
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { DrawerNavigationProps } from './types';
3
+ export declare function DrawerNavigation({ items, header, footer, compact, testID, }: DrawerNavigationProps): React.JSX.Element;
4
+ //# sourceMappingURL=DrawerNavigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DrawerNavigation.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/DrawerNavigation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAErD,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,MAAM,EACN,MAAM,EACN,OAAe,EACf,MAAM,GACP,EAAE,qBAAqB,qBAYvB"}
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { Stack } from '../../layout';
3
+ import { DrawerNavigationItem } from './DrawerNavigationItem';
4
+ export function DrawerNavigation({ items, header, footer, compact = false, testID, }) {
5
+ return (<Stack gap={compact ? 's' : 'm'} testID={testID}>
6
+ {header}
7
+ <Stack gap={compact ? 'xs' : 's'}>
8
+ {items.map((item) => (<DrawerNavigationItem compact={compact} item={item} key={item.id} testID={testID}/>))}
9
+ </Stack>
10
+ {footer}
11
+ </Stack>);
12
+ }
13
+ //# sourceMappingURL=DrawerNavigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DrawerNavigation.js","sourceRoot":"","sources":["../../../src/components/navigation/DrawerNavigation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,UAAU,gBAAgB,CAAC,EAC/B,KAAK,EACL,MAAM,EACN,MAAM,EACN,OAAO,GAAG,KAAK,EACf,MAAM,GACgB;IACtB,OAAO,CACL,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAC9C;MAAA,CAAC,MAAM,CACP;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAC/B;QAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAG,CACrF,CAAC,CACJ;MAAA,EAAE,KAAK,CACP;MAAA,CAAC,MAAM,CACT;IAAA,EAAE,KAAK,CAAC,CACT,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\n\nimport { Stack } from '../../layout';\nimport { DrawerNavigationItem } from './DrawerNavigationItem';\nimport type { DrawerNavigationProps } from './types';\n\nexport function DrawerNavigation({\n items,\n header,\n footer,\n compact = false,\n testID,\n}: DrawerNavigationProps) {\n return (\n <Stack gap={compact ? 's' : 'm'} testID={testID}>\n {header}\n <Stack gap={compact ? 'xs' : 's'}>\n {items.map((item) => (\n <DrawerNavigationItem compact={compact} item={item} key={item.id} testID={testID} />\n ))}\n </Stack>\n {footer}\n </Stack>\n );\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { DrawerNavigationItemProps } from './types';
3
+ export declare function DrawerNavigationItem({ item, compact, testID }: DrawerNavigationItemProps): React.JSX.Element;
4
+ //# sourceMappingURL=DrawerNavigationItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DrawerNavigationItem.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/DrawerNavigationItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAEzD,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,OAAe,EAAE,MAAM,EAAE,EAAE,yBAAyB,qBAWhG"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { NavigationItem } from './NavigationItem';
3
+ export function DrawerNavigationItem({ item, compact = false, testID }) {
4
+ return (<NavigationItem compact={compact} item={{
5
+ ...item,
6
+ accessibilityRole: item.accessibilityRole ?? 'button',
7
+ }} testID={testID}/>);
8
+ }
9
+ //# sourceMappingURL=DrawerNavigationItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DrawerNavigationItem.js","sourceRoot":"","sources":["../../../src/components/navigation/DrawerNavigationItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,MAAM,UAAU,oBAAoB,CAAC,EAAE,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE,MAAM,EAA6B;IAC/F,OAAO,CACL,CAAC,cAAc,CACb,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,IAAI,CAAC,CAAC;YACJ,GAAG,IAAI;YACP,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,IAAI,QAAQ;SACtD,CAAC,CACF,MAAM,CAAC,CAAC,MAAM,CAAC,EACf,CACH,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\n\nimport { NavigationItem } from './NavigationItem';\nimport type { DrawerNavigationItemProps } from './types';\n\nexport function DrawerNavigationItem({ item, compact = false, testID }: DrawerNavigationItemProps) {\n return (\n <NavigationItem\n compact={compact}\n item={{\n ...item,\n accessibilityRole: item.accessibilityRole ?? 'button',\n }}\n testID={testID}\n />\n );\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { NavigationItemProps } from './types';
3
+ export declare function NavigationItem({ item, compact, testID }: NavigationItemProps): React.JSX.Element;
4
+ //# sourceMappingURL=NavigationItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavigationItem.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/NavigationItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,OAAe,EAAE,MAAM,EAAE,EAAE,mBAAmB,qBAiEpF"}
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+ import { Box } from '../../layout';
4
+ import { ButtonBase } from '../../primitives/button-base';
5
+ import { Icon } from '../../primitives/icon';
6
+ import { Text } from '../../primitives/text';
7
+ import { useTheme } from '../../theme/ThemeContext';
8
+ import { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';
9
+ export function NavigationItem({ item, compact = false, testID }) {
10
+ const { theme } = useTheme();
11
+ const active = Boolean(item.active);
12
+ const disabled = Boolean(item.disabled);
13
+ const resolvedTestID = item.testID ?? (testID ? `${testID}-item-${item.id}` : undefined);
14
+ const resolvedAccessibilityState = resolveNavigationAccessibilityState(active, disabled, item.accessibilityState);
15
+ return (<ButtonBase accessibilityLabel={item.accessibilityLabel} accessibilityRole={item.accessibilityRole ?? 'button'} accessibilityState={resolvedAccessibilityState} disabled={disabled} onPress={item.onPress} testID={resolvedTestID}>
16
+ {(state) => {
17
+ const presentation = resolveNavigationItemPresentation(theme, {
18
+ active,
19
+ disabled,
20
+ state,
21
+ });
22
+ return (<Box px="m" py={compact ? 's' : 'm'} radius="m" style={{
23
+ backgroundColor: presentation.backgroundColor,
24
+ flexDirection: 'row',
25
+ alignItems: 'center',
26
+ opacity: presentation.opacity,
27
+ }}>
28
+ {item.icon ? (<View style={{ marginRight: theme.spacing.s }}>
29
+ <Icon color={presentation.contentColor} name={item.icon.name} provider={item.icon.provider} size={compact ? 's' : 'm'}/>
30
+ </View>) : null}
31
+ <Box flex={1}>
32
+ <Text color={presentation.contentColor} numberOfLines={1} variant={compact ? 'bodySmall' : 'body'} weight="medium">
33
+ {item.label}
34
+ </Text>
35
+ </Box>
36
+ {item.badge ? <View style={{ marginLeft: theme.spacing.s }}>{item.badge}</View> : null}
37
+ </Box>);
38
+ }}
39
+ </ButtonBase>);
40
+ }
41
+ //# sourceMappingURL=NavigationItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavigationItem.js","sourceRoot":"","sources":["../../../src/components/navigation/NavigationItem.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { View } from 'react-native';\n\nimport { Box } from '../../layout';\nimport { ButtonBase } from '../../primitives/button-base';\nimport { Icon } from '../../primitives/icon';\nimport { Text } from '../../primitives/text';\nimport { useTheme } from '../../theme/ThemeContext';\nimport { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';\nimport type { NavigationItemProps } from './types';\n\nexport function NavigationItem({ item, compact = false, testID }: NavigationItemProps) {\n const { theme } = useTheme();\n const active = Boolean(item.active);\n const disabled = Boolean(item.disabled);\n const resolvedTestID = item.testID ?? (testID ? `${testID}-item-${item.id}` : undefined);\n const resolvedAccessibilityState = resolveNavigationAccessibilityState(\n active,\n disabled,\n item.accessibilityState,\n );\n\n return (\n <ButtonBase\n accessibilityLabel={item.accessibilityLabel}\n accessibilityRole={item.accessibilityRole ?? 'button'}\n accessibilityState={resolvedAccessibilityState}\n disabled={disabled}\n onPress={item.onPress}\n testID={resolvedTestID}\n >\n {(state) => {\n const presentation = resolveNavigationItemPresentation(theme, {\n active,\n disabled,\n state,\n });\n\n return (\n <Box\n px=\"m\"\n py={compact ? 's' : 'm'}\n radius=\"m\"\n style={{\n backgroundColor: presentation.backgroundColor,\n flexDirection: 'row',\n alignItems: 'center',\n opacity: presentation.opacity,\n }}\n >\n {item.icon ? (\n <View style={{ marginRight: theme.spacing.s }}>\n <Icon\n color={presentation.contentColor}\n name={item.icon.name}\n provider={item.icon.provider}\n size={compact ? 's' : 'm'}\n />\n </View>\n ) : null}\n <Box flex={1}>\n <Text\n color={presentation.contentColor}\n numberOfLines={1}\n variant={compact ? 'bodySmall' : 'body'}\n weight=\"medium\"\n >\n {item.label}\n </Text>\n </Box>\n {item.badge ? <View style={{ marginLeft: theme.spacing.s }}>{item.badge}</View> : null}\n </Box>\n );\n }}\n </ButtonBase>\n );\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { NavigationListProps } from './types';
3
+ export declare function NavigationList({ items, orientation, compact, testID, }: NavigationListProps): React.JSX.Element;
4
+ //# sourceMappingURL=NavigationList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavigationList.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/NavigationList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,WAAwB,EACxB,OAAe,EACf,MAAM,GACP,EAAE,mBAAmB,qBAYrB"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { Stack } from '../../layout';
3
+ import { NavigationItem } from './NavigationItem';
4
+ export function NavigationList({ items, orientation = 'vertical', compact = false, testID, }) {
5
+ return (<Stack direction={orientation === 'horizontal' ? 'row' : 'column'} gap={compact ? 'xs' : 's'} testID={testID}>
6
+ {items.map((item) => (<NavigationItem compact={compact} item={item} key={item.id} testID={testID}/>))}
7
+ </Stack>);
8
+ }
9
+ //# sourceMappingURL=NavigationList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavigationList.js","sourceRoot":"","sources":["../../../src/components/navigation/NavigationList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,MAAM,UAAU,cAAc,CAAC,EAC7B,KAAK,EACL,WAAW,GAAG,UAAU,EACxB,OAAO,GAAG,KAAK,EACf,MAAM,GACc;IACpB,OAAO,CACL,CAAC,KAAK,CACJ,SAAS,CAAC,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAC3D,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAC1B,MAAM,CAAC,CAAC,MAAM,CAAC,CAEf;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAG,CAC/E,CAAC,CACJ;IAAA,EAAE,KAAK,CAAC,CACT,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\n\nimport { Stack } from '../../layout';\nimport { NavigationItem } from './NavigationItem';\nimport type { NavigationListProps } from './types';\n\nexport function NavigationList({\n items,\n orientation = 'vertical',\n compact = false,\n testID,\n}: NavigationListProps) {\n return (\n <Stack\n direction={orientation === 'horizontal' ? 'row' : 'column'}\n gap={compact ? 'xs' : 's'}\n testID={testID}\n >\n {items.map((item) => (\n <NavigationItem compact={compact} item={item} key={item.id} testID={testID} />\n ))}\n </Stack>\n );\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { TabBarProps } from './types';
3
+ export declare function TabBar({ items, compact, testID }: TabBarProps): React.JSX.Element;
4
+ //# sourceMappingURL=TabBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabBar.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/TabBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,OAAe,EAAE,MAAM,EAAE,EAAE,WAAW,qBAiBrE"}
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { Box } from '../../layout';
3
+ import { useTheme } from '../../theme/ThemeContext';
4
+ import { TabBarItem } from './TabBarItem';
5
+ export function TabBar({ items, compact = false, testID }) {
6
+ const { theme } = useTheme();
7
+ return (<Box style={{
8
+ flexDirection: 'row',
9
+ borderTopColor: theme.semantics.border.default,
10
+ borderTopWidth: 1,
11
+ }} testID={testID}>
12
+ {items.map((item) => (<TabBarItem compact={compact} item={item} key={item.id} testID={testID}/>))}
13
+ </Box>);
14
+ }
15
+ //# sourceMappingURL=TabBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabBar.js","sourceRoot":"","sources":["../../../src/components/navigation/TabBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,MAAM,UAAU,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,MAAM,EAAe;IACpE,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAE7B,OAAO,CACL,CAAC,GAAG,CACF,KAAK,CAAC,CAAC;YACL,aAAa,EAAE,KAAK;YACpB,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO;YAC9C,cAAc,EAAE,CAAC;SAClB,CAAC,CACF,MAAM,CAAC,CAAC,MAAM,CAAC,CAEf;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAG,CAC3E,CAAC,CACJ;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\n\nimport { Box } from '../../layout';\nimport { useTheme } from '../../theme/ThemeContext';\nimport { TabBarItem } from './TabBarItem';\nimport type { TabBarProps } from './types';\n\nexport function TabBar({ items, compact = false, testID }: TabBarProps) {\n const { theme } = useTheme();\n\n return (\n <Box\n style={{\n flexDirection: 'row',\n borderTopColor: theme.semantics.border.default,\n borderTopWidth: 1,\n }}\n testID={testID}\n >\n {items.map((item) => (\n <TabBarItem compact={compact} item={item} key={item.id} testID={testID} />\n ))}\n </Box>\n );\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import type { TabBarItemProps } from './types';
3
+ export declare function TabBarItem({ item, compact, testID }: TabBarItemProps): React.JSX.Element;
4
+ //# sourceMappingURL=TabBarItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabBarItem.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/TabBarItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,OAAe,EAAE,MAAM,EAAE,EAAE,eAAe,qBAsE5E"}
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+ import { Box } from '../../layout';
4
+ import { ButtonBase } from '../../primitives/button-base';
5
+ import { Icon } from '../../primitives/icon';
6
+ import { Text } from '../../primitives/text';
7
+ import { useTheme } from '../../theme/ThemeContext';
8
+ import { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';
9
+ export function TabBarItem({ item, compact = false, testID }) {
10
+ const { theme } = useTheme();
11
+ const active = Boolean(item.active);
12
+ const disabled = Boolean(item.disabled);
13
+ const resolvedTestID = item.testID ?? (testID ? `${testID}-item-${item.id}` : undefined);
14
+ const resolvedAccessibilityState = resolveNavigationAccessibilityState(active, disabled, item.accessibilityState);
15
+ return (<ButtonBase accessibilityLabel={item.accessibilityLabel} accessibilityRole={item.accessibilityRole ?? 'tab'} accessibilityState={resolvedAccessibilityState} disabled={disabled} onPress={item.onPress} style={{ flex: 1 }} testID={resolvedTestID}>
16
+ {(state) => {
17
+ const presentation = resolveNavigationItemPresentation(theme, {
18
+ active,
19
+ disabled,
20
+ state,
21
+ });
22
+ const contentColor = disabled
23
+ ? theme.semantics.content.muted
24
+ : active
25
+ ? theme.semantics.action.primary.base
26
+ : theme.semantics.content.muted;
27
+ return (<Box px="m" py={compact ? 's' : 'm'} style={{
28
+ flex: 1,
29
+ alignItems: 'center',
30
+ justifyContent: 'center',
31
+ backgroundColor: presentation.backgroundColor,
32
+ opacity: presentation.opacity,
33
+ }}>
34
+ {item.icon ? (<View style={{ marginBottom: item.label ? theme.spacing.xs : 0 }}>
35
+ <Icon color={contentColor} name={item.icon.name} provider={item.icon.provider} size={compact ? 's' : 'm'}/>
36
+ </View>) : null}
37
+ {item.label ? (<Text color={contentColor} numberOfLines={1} variant={compact ? 'bodySmall' : 'label'} weight="medium">
38
+ {item.label}
39
+ </Text>) : null}
40
+ </Box>);
41
+ }}
42
+ </ButtonBase>);
43
+ }
44
+ //# sourceMappingURL=TabBarItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabBarItem.js","sourceRoot":"","sources":["../../../src/components/navigation/TabBarItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,mCAAmC,EAAE,iCAAiC,EAAE,MAAM,WAAW,CAAC;AAGnG,MAAM,UAAU,UAAU,CAAC,EAAE,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE,MAAM,EAAmB;IAC3E,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,SAAS,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACzF,MAAM,0BAA0B,GAAG,mCAAmC,CACpE,MAAM,EACN,QAAQ,EACR,IAAI,CAAC,kBAAkB,CACxB,CAAC;IAEF,OAAO,CACL,CAAC,UAAU,CACT,kBAAkB,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAC5C,iBAAiB,CAAC,CAAC,IAAI,CAAC,iBAAiB,IAAI,KAAK,CAAC,CACnD,kBAAkB,CAAC,CAAC,0BAA0B,CAAC,CAC/C,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CACtB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CACnB,MAAM,CAAC,CAAC,cAAc,CAAC,CAEvB;MAAA,CAAC,CAAC,KAAK,EAAE,EAAE;YACT,MAAM,YAAY,GAAG,iCAAiC,CAAC,KAAK,EAAE;gBAC5D,MAAM;gBACN,QAAQ;gBACR,KAAK;aACN,CAAC,CAAC;YACH,MAAM,YAAY,GAAG,QAAQ;gBAC3B,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK;gBAC/B,CAAC,CAAC,MAAM;oBACN,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI;oBACrC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC;YAEpC,OAAO,CACL,CAAC,GAAG,CACF,EAAE,CAAC,GAAG,CACN,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CACxB,KAAK,CAAC,CAAC;oBACL,IAAI,EAAE,CAAC;oBACP,UAAU,EAAE,QAAQ;oBACpB,cAAc,EAAE,QAAQ;oBACxB,eAAe,EAAE,YAAY,CAAC,eAAe;oBAC7C,OAAO,EAAE,YAAY,CAAC,OAAO;iBAC9B,CAAC,CAEF;YAAA,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CACX,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAC/D;gBAAA,CAAC,IAAI,CACH,KAAK,CAAC,CAAC,YAAY,CAAC,CACpB,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CACrB,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAC7B,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAE9B;cAAA,EAAE,IAAI,CAAC,CACR,CAAC,CAAC,CAAC,IAAI,CACR;YAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CACZ,CAAC,IAAI,CACH,KAAK,CAAC,CAAC,YAAY,CAAC,CACpB,aAAa,CAAC,CAAC,CAAC,CAAC,CACjB,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CACzC,MAAM,CAAC,QAAQ,CAEf;gBAAA,CAAC,IAAI,CAAC,KAAK,CACb;cAAA,EAAE,IAAI,CAAC,CACR,CAAC,CAAC,CAAC,IAAI,CACV;UAAA,EAAE,GAAG,CAAC,CACP,CAAC;QACJ,CAAC,CACH;IAAA,EAAE,UAAU,CAAC,CACd,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\nimport { View } from 'react-native';\n\nimport { Box } from '../../layout';\nimport { ButtonBase } from '../../primitives/button-base';\nimport { Icon } from '../../primitives/icon';\nimport { Text } from '../../primitives/text';\nimport { useTheme } from '../../theme/ThemeContext';\nimport { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';\nimport type { TabBarItemProps } from './types';\n\nexport function TabBarItem({ item, compact = false, testID }: TabBarItemProps) {\n const { theme } = useTheme();\n const active = Boolean(item.active);\n const disabled = Boolean(item.disabled);\n const resolvedTestID = item.testID ?? (testID ? `${testID}-item-${item.id}` : undefined);\n const resolvedAccessibilityState = resolveNavigationAccessibilityState(\n active,\n disabled,\n item.accessibilityState,\n );\n\n return (\n <ButtonBase\n accessibilityLabel={item.accessibilityLabel}\n accessibilityRole={item.accessibilityRole ?? 'tab'}\n accessibilityState={resolvedAccessibilityState}\n disabled={disabled}\n onPress={item.onPress}\n style={{ flex: 1 }}\n testID={resolvedTestID}\n >\n {(state) => {\n const presentation = resolveNavigationItemPresentation(theme, {\n active,\n disabled,\n state,\n });\n const contentColor = disabled\n ? theme.semantics.content.muted\n : active\n ? theme.semantics.action.primary.base\n : theme.semantics.content.muted;\n\n return (\n <Box\n px=\"m\"\n py={compact ? 's' : 'm'}\n style={{\n flex: 1,\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: presentation.backgroundColor,\n opacity: presentation.opacity,\n }}\n >\n {item.icon ? (\n <View style={{ marginBottom: item.label ? theme.spacing.xs : 0 }}>\n <Icon\n color={contentColor}\n name={item.icon.name}\n provider={item.icon.provider}\n size={compact ? 's' : 'm'}\n />\n </View>\n ) : null}\n {item.label ? (\n <Text\n color={contentColor}\n numberOfLines={1}\n variant={compact ? 'bodySmall' : 'label'}\n weight=\"medium\"\n >\n {item.label}\n </Text>\n ) : null}\n </Box>\n );\n }}\n </ButtonBase>\n );\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import type { AccessibilityState } from 'react-native';
2
+ import type { InteractionState } from '../../internal/resolvers/resolveInteractiveState';
3
+ import type { SurfaceTheme } from '../../theme/types';
4
+ export declare function resolveNavigationAccessibilityState(active: boolean, disabled: boolean, accessibilityState?: AccessibilityState): AccessibilityState;
5
+ export interface ResolvedNavigationItemPresentation {
6
+ backgroundColor: string;
7
+ contentColor: string;
8
+ opacity: number;
9
+ }
10
+ export declare function resolveNavigationItemPresentation(theme: SurfaceTheme, { active, disabled, state, }: {
11
+ active: boolean;
12
+ disabled: boolean;
13
+ state: InteractionState;
14
+ }): ResolvedNavigationItemPresentation;
15
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AACzF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,wBAAgB,mCAAmC,CACjD,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,OAAO,EACjB,kBAAkB,CAAC,EAAE,kBAAkB,GACtC,kBAAkB,CAYpB;AAED,MAAM,WAAW,kCAAkC;IACjD,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,YAAY,EACnB,EACE,MAAM,EACN,QAAQ,EACR,KAAK,GACN,EAAE;IACD,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,gBAAgB,CAAC;CACzB,GACA,kCAAkC,CA+BpC"}
@@ -0,0 +1,40 @@
1
+ export function resolveNavigationAccessibilityState(active, disabled, accessibilityState) {
2
+ const resolved = { ...(accessibilityState ?? {}) };
3
+ if (active) {
4
+ resolved.selected = true;
5
+ }
6
+ if (disabled) {
7
+ resolved.disabled = true;
8
+ }
9
+ return resolved;
10
+ }
11
+ export function resolveNavigationItemPresentation(theme, { active, disabled, state, }) {
12
+ const interactionState = disabled ? { ...state, hovered: false, pressed: false } : state;
13
+ const opacity = disabled ? 0.72 : 1;
14
+ const contentColor = disabled
15
+ ? theme.semantics.content.muted
16
+ : active
17
+ ? theme.semantics.action.primary.base
18
+ : theme.semantics.content.default;
19
+ if (active) {
20
+ return {
21
+ backgroundColor: interactionState.pressed
22
+ ? theme.semantics.action.primary.softActive
23
+ : interactionState.hovered
24
+ ? theme.semantics.action.primary.softHover
25
+ : theme.semantics.action.primary.softBg,
26
+ contentColor,
27
+ opacity,
28
+ };
29
+ }
30
+ return {
31
+ backgroundColor: interactionState.pressed
32
+ ? theme.semantics.neutral.surfaceActive
33
+ : interactionState.hovered
34
+ ? theme.semantics.neutral.surfaceHover
35
+ : 'transparent',
36
+ contentColor,
37
+ opacity,
38
+ };
39
+ }
40
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/components/navigation/helpers.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,mCAAmC,CACjD,MAAe,EACf,QAAiB,EACjB,kBAAuC;IAEvC,MAAM,QAAQ,GAAuB,EAAE,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,EAAE,CAAC;IAEvE,IAAI,MAAM,EAAE,CAAC;QACX,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAQD,MAAM,UAAU,iCAAiC,CAC/C,KAAmB,EACnB,EACE,MAAM,EACN,QAAQ,EACR,KAAK,GAKN;IAED,MAAM,gBAAgB,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAEzF,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,YAAY,GAAG,QAAQ;QAC3B,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK;QAC/B,CAAC,CAAC,MAAM;YACN,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI;YACrC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC;IAEtC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,eAAe,EAAE,gBAAgB,CAAC,OAAO;gBACvC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU;gBAC3C,CAAC,CAAC,gBAAgB,CAAC,OAAO;oBACxB,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS;oBAC1C,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM;YAC3C,YAAY;YACZ,OAAO;SACR,CAAC;IACJ,CAAC;IAED,OAAO;QACL,eAAe,EAAE,gBAAgB,CAAC,OAAO;YACvC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,aAAa;YACvC,CAAC,CAAC,gBAAgB,CAAC,OAAO;gBACxB,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,YAAY;gBACtC,CAAC,CAAC,aAAa;QACnB,YAAY;QACZ,OAAO;KACR,CAAC;AACJ,CAAC","sourcesContent":["import type { AccessibilityState } from 'react-native';\n\nimport type { InteractionState } from '../../internal/resolvers/resolveInteractiveState';\nimport type { SurfaceTheme } from '../../theme/types';\n\nexport function resolveNavigationAccessibilityState(\n active: boolean,\n disabled: boolean,\n accessibilityState?: AccessibilityState,\n): AccessibilityState {\n const resolved: AccessibilityState = { ...(accessibilityState ?? {}) };\n\n if (active) {\n resolved.selected = true;\n }\n\n if (disabled) {\n resolved.disabled = true;\n }\n\n return resolved;\n}\n\nexport interface ResolvedNavigationItemPresentation {\n backgroundColor: string;\n contentColor: string;\n opacity: number;\n}\n\nexport function resolveNavigationItemPresentation(\n theme: SurfaceTheme,\n {\n active,\n disabled,\n state,\n }: {\n active: boolean;\n disabled: boolean;\n state: InteractionState;\n },\n): ResolvedNavigationItemPresentation {\n const interactionState = disabled ? { ...state, hovered: false, pressed: false } : state;\n\n const opacity = disabled ? 0.72 : 1;\n const contentColor = disabled\n ? theme.semantics.content.muted\n : active\n ? theme.semantics.action.primary.base\n : theme.semantics.content.default;\n\n if (active) {\n return {\n backgroundColor: interactionState.pressed\n ? theme.semantics.action.primary.softActive\n : interactionState.hovered\n ? theme.semantics.action.primary.softHover\n : theme.semantics.action.primary.softBg,\n contentColor,\n opacity,\n };\n }\n\n return {\n backgroundColor: interactionState.pressed\n ? theme.semantics.neutral.surfaceActive\n : interactionState.hovered\n ? theme.semantics.neutral.surfaceHover\n : 'transparent',\n contentColor,\n opacity,\n };\n}\n"]}
@@ -0,0 +1,8 @@
1
+ export { DrawerNavigation } from './DrawerNavigation';
2
+ export { DrawerNavigationItem } from './DrawerNavigationItem';
3
+ export { NavigationItem } from './NavigationItem';
4
+ export { NavigationList } from './NavigationList';
5
+ export { TabBar } from './TabBar';
6
+ export { TabBarItem } from './TabBarItem';
7
+ export type { DrawerNavigationItemProps, DrawerNavigationProps, NavigationItemIcon, NavigationItemProps, NavigationItemSpec, NavigationListProps, TabBarItemProps, TabBarProps, } from './types';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EACV,yBAAyB,EACzB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,WAAW,GACZ,MAAM,SAAS,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { DrawerNavigation } from './DrawerNavigation';
2
+ export { DrawerNavigationItem } from './DrawerNavigationItem';
3
+ export { NavigationItem } from './NavigationItem';
4
+ export { NavigationList } from './NavigationList';
5
+ export { TabBar } from './TabBar';
6
+ export { TabBarItem } from './TabBarItem';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/navigation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { DrawerNavigation } from './DrawerNavigation';\nexport { DrawerNavigationItem } from './DrawerNavigationItem';\nexport { NavigationItem } from './NavigationItem';\nexport { NavigationList } from './NavigationList';\nexport { TabBar } from './TabBar';\nexport { TabBarItem } from './TabBarItem';\nexport type {\n DrawerNavigationItemProps,\n DrawerNavigationProps,\n NavigationItemIcon,\n NavigationItemProps,\n NavigationItemSpec,\n NavigationListProps,\n TabBarItemProps,\n TabBarProps,\n} from './types';\n"]}
@@ -0,0 +1,51 @@
1
+ import type React from 'react';
2
+ import type { AccessibilityRole, AccessibilityState } from 'react-native';
3
+ import type { IconProps } from '../../primitives/icon';
4
+ export type NavigationItemIcon = Pick<IconProps, 'name' | 'provider'>;
5
+ export interface NavigationItemSpec {
6
+ id: string;
7
+ label: React.ReactNode;
8
+ icon?: NavigationItemIcon;
9
+ badge?: React.ReactNode;
10
+ active?: boolean;
11
+ disabled?: boolean;
12
+ onPress?: (() => void) | undefined;
13
+ accessibilityLabel?: string;
14
+ accessibilityRole?: AccessibilityRole;
15
+ accessibilityState?: AccessibilityState;
16
+ testID?: string;
17
+ }
18
+ export interface NavigationItemProps {
19
+ item: NavigationItemSpec;
20
+ compact?: boolean;
21
+ testID?: string;
22
+ }
23
+ export interface NavigationListProps {
24
+ items: readonly NavigationItemSpec[];
25
+ orientation?: 'vertical' | 'horizontal';
26
+ compact?: boolean;
27
+ testID?: string;
28
+ }
29
+ export interface TabBarProps {
30
+ items: readonly NavigationItemSpec[];
31
+ compact?: boolean;
32
+ testID?: string;
33
+ }
34
+ export interface TabBarItemProps {
35
+ item: NavigationItemSpec;
36
+ compact?: boolean;
37
+ testID?: string;
38
+ }
39
+ export interface DrawerNavigationProps {
40
+ items: readonly NavigationItemSpec[];
41
+ header?: React.ReactNode;
42
+ footer?: React.ReactNode;
43
+ compact?: boolean;
44
+ testID?: string;
45
+ }
46
+ export interface DrawerNavigationItemProps {
47
+ item: NavigationItemSpec;
48
+ compact?: boolean;
49
+ testID?: string;
50
+ }
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/navigation/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAE1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC;AAEtE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACnC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACrC,WAAW,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACrC,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/navigation/types.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\nimport type { AccessibilityRole, AccessibilityState } from 'react-native';\n\nimport type { IconProps } from '../../primitives/icon';\n\nexport type NavigationItemIcon = Pick<IconProps, 'name' | 'provider'>;\n\nexport interface NavigationItemSpec {\n id: string;\n label: React.ReactNode;\n icon?: NavigationItemIcon;\n badge?: React.ReactNode;\n active?: boolean;\n disabled?: boolean;\n onPress?: (() => void) | undefined;\n accessibilityLabel?: string;\n accessibilityRole?: AccessibilityRole;\n accessibilityState?: AccessibilityState;\n testID?: string;\n}\n\nexport interface NavigationItemProps {\n item: NavigationItemSpec;\n compact?: boolean;\n testID?: string;\n}\n\nexport interface NavigationListProps {\n items: readonly NavigationItemSpec[];\n orientation?: 'vertical' | 'horizontal';\n compact?: boolean;\n testID?: string;\n}\n\nexport interface TabBarProps {\n items: readonly NavigationItemSpec[];\n compact?: boolean;\n testID?: string;\n}\n\nexport interface TabBarItemProps {\n item: NavigationItemSpec;\n compact?: boolean;\n testID?: string;\n}\n\nexport interface DrawerNavigationProps {\n items: readonly NavigationItemSpec[];\n header?: React.ReactNode;\n footer?: React.ReactNode;\n compact?: boolean;\n testID?: string;\n}\n\nexport interface DrawerNavigationItemProps {\n item: NavigationItemSpec;\n compact?: boolean;\n testID?: string;\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -22,6 +22,8 @@ export type { MenuItem, MenuProps } from './components/menu';
22
22
  export { Menu } from './components/menu';
23
23
  export type { ModalProps } from './components/modal';
24
24
  export { Modal } from './components/modal';
25
+ export type { DrawerNavigationItemProps, DrawerNavigationProps, NavigationItemIcon, NavigationItemProps, NavigationItemSpec, NavigationListProps, TabBarItemProps, TabBarProps, } from './components/navigation';
26
+ export { DrawerNavigation, DrawerNavigationItem, NavigationItem, NavigationList, TabBar, TabBarItem, } from './components/navigation';
25
27
  export type { RadioProps } from './components/radio';
26
28
  export { Radio } from './components/radio';
27
29
  export type { SwitchProps } from './components/switch';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ export { Label } from './components/label';
10
10
  export { ListItem } from './components/list-item';
11
11
  export { Menu } from './components/menu';
12
12
  export { Modal } from './components/modal';
13
+ export { DrawerNavigation, DrawerNavigationItem, NavigationItem, NavigationList, TabBar, TabBarItem, } from './components/navigation';
13
14
  export { Radio } from './components/radio';
14
15
  export { Switch } from './components/switch';
15
16
  export { Tab, TabList, TabPanel, Tabs } from './components/tabs';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEpE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1F,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AAEzB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["export type { BadgeProps } from './components/badge';\nexport { Badge } from './components/badge';\nexport type { ButtonIconSpec, ButtonProps } from './components/button';\nexport { Button } from './components/button';\nexport type { CardProps } from './components/card';\nexport { Card } from './components/card';\nexport type { CheckboxProps } from './components/checkbox';\nexport { Checkbox } from './components/checkbox';\nexport type { DrawerProps } from './components/drawer';\nexport { Drawer } from './components/drawer';\nexport type { FieldProps } from './components/field';\nexport { Field } from './components/field';\nexport type { HelperTextProps } from './components/helper-text';\nexport { HelperText } from './components/helper-text';\nexport type { IconButtonProps } from './components/icon-button';\nexport { IconButton } from './components/icon-button';\nexport type { LabelProps } from './components/label';\nexport { Label } from './components/label';\nexport type { ListItemProps } from './components/list-item';\nexport { ListItem } from './components/list-item';\nexport type { MenuItem, MenuProps } from './components/menu';\nexport { Menu } from './components/menu';\nexport type { ModalProps } from './components/modal';\nexport { Modal } from './components/modal';\nexport type { RadioProps } from './components/radio';\nexport { Radio } from './components/radio';\nexport type { SwitchProps } from './components/switch';\nexport { Switch } from './components/switch';\nexport type { TabListProps, TabPanelProps, TabProps, TabsProps } from './components/tabs';\nexport { Tab, TabList, TabPanel, Tabs } from './components/tabs';\nexport type { TextInputProps } from './components/text-input';\nexport { TextInput } from './components/text-input';\nexport type { TextareaProps } from './components/textarea';\nexport { Textarea } from './components/textarea';\nexport type { ToastOptions, ToastProps, ToastTone } from './components/toast';\nexport { Toast, ToastProvider, useToast } from './components/toast';\nexport type { TooltipProps } from './components/tooltip';\nexport { Tooltip } from './components/tooltip';\nexport type { FontRuntime } from './context/FontContext';\nexport { FontProvider, useFontContext } from './context/FontContext';\nexport type { I18nInstance, TranslationRuntime, Translator } from './context/TranslationContext';\nexport { TranslationProvider, useTranslationContext } from './context/TranslationContext';\nexport * from './core/responsive';\nexport * from './layout';\nexport type { ButtonBaseProps } from './primitives/button-base';\nexport { ButtonBase } from './primitives/button-base';\nexport type { HeadingLevel, HeadingProps } from './primitives/heading';\nexport { Heading } from './primitives/heading';\nexport type { IconProps, IconProvider } from './primitives/icon';\nexport { Icon } from './primitives/icon';\nexport type { TextProps } from './primitives/text';\nexport { Text } from './primitives/text';\nexport * from './theme';\nexport { isDeepEqual } from './utils/deepEqual';\nexport { deepMerge } from './utils/deepMerge';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAW3C,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,MAAM,EACN,UAAU,GACX,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEpE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1F,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AAEzB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["export type { BadgeProps } from './components/badge';\nexport { Badge } from './components/badge';\nexport type { ButtonIconSpec, ButtonProps } from './components/button';\nexport { Button } from './components/button';\nexport type { CardProps } from './components/card';\nexport { Card } from './components/card';\nexport type { CheckboxProps } from './components/checkbox';\nexport { Checkbox } from './components/checkbox';\nexport type { DrawerProps } from './components/drawer';\nexport { Drawer } from './components/drawer';\nexport type { FieldProps } from './components/field';\nexport { Field } from './components/field';\nexport type { HelperTextProps } from './components/helper-text';\nexport { HelperText } from './components/helper-text';\nexport type { IconButtonProps } from './components/icon-button';\nexport { IconButton } from './components/icon-button';\nexport type { LabelProps } from './components/label';\nexport { Label } from './components/label';\nexport type { ListItemProps } from './components/list-item';\nexport { ListItem } from './components/list-item';\nexport type { MenuItem, MenuProps } from './components/menu';\nexport { Menu } from './components/menu';\nexport type { ModalProps } from './components/modal';\nexport { Modal } from './components/modal';\nexport type {\n DrawerNavigationItemProps,\n DrawerNavigationProps,\n NavigationItemIcon,\n NavigationItemProps,\n NavigationItemSpec,\n NavigationListProps,\n TabBarItemProps,\n TabBarProps,\n} from './components/navigation';\nexport {\n DrawerNavigation,\n DrawerNavigationItem,\n NavigationItem,\n NavigationList,\n TabBar,\n TabBarItem,\n} from './components/navigation';\nexport type { RadioProps } from './components/radio';\nexport { Radio } from './components/radio';\nexport type { SwitchProps } from './components/switch';\nexport { Switch } from './components/switch';\nexport type { TabListProps, TabPanelProps, TabProps, TabsProps } from './components/tabs';\nexport { Tab, TabList, TabPanel, Tabs } from './components/tabs';\nexport type { TextInputProps } from './components/text-input';\nexport { TextInput } from './components/text-input';\nexport type { TextareaProps } from './components/textarea';\nexport { Textarea } from './components/textarea';\nexport type { ToastOptions, ToastProps, ToastTone } from './components/toast';\nexport { Toast, ToastProvider, useToast } from './components/toast';\nexport type { TooltipProps } from './components/tooltip';\nexport { Tooltip } from './components/tooltip';\nexport type { FontRuntime } from './context/FontContext';\nexport { FontProvider, useFontContext } from './context/FontContext';\nexport type { I18nInstance, TranslationRuntime, Translator } from './context/TranslationContext';\nexport { TranslationProvider, useTranslationContext } from './context/TranslationContext';\nexport * from './core/responsive';\nexport * from './layout';\nexport type { ButtonBaseProps } from './primitives/button-base';\nexport { ButtonBase } from './primitives/button-base';\nexport type { HeadingLevel, HeadingProps } from './primitives/heading';\nexport { Heading } from './primitives/heading';\nexport type { IconProps, IconProvider } from './primitives/icon';\nexport { Icon } from './primitives/icon';\nexport type { TextProps } from './primitives/text';\nexport { Text } from './primitives/text';\nexport * from './theme';\nexport { isDeepEqual } from './utils/deepEqual';\nexport { deepMerge } from './utils/deepMerge';\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/surface",
3
3
  "type": "module",
4
- "version": "1.0.3",
4
+ "version": "1.1.0",
5
5
  "description": "Stable UI foundation for React Native and React Native Web.",
6
6
  "homepage": "https://github.com/ankhorage/surface#readme",
7
7
  "bugs": {
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+
3
+ import { Stack } from '../../layout';
4
+ import { DrawerNavigationItem } from './DrawerNavigationItem';
5
+ import type { DrawerNavigationProps } from './types';
6
+
7
+ export function DrawerNavigation({
8
+ items,
9
+ header,
10
+ footer,
11
+ compact = false,
12
+ testID,
13
+ }: DrawerNavigationProps) {
14
+ return (
15
+ <Stack gap={compact ? 's' : 'm'} testID={testID}>
16
+ {header}
17
+ <Stack gap={compact ? 'xs' : 's'}>
18
+ {items.map((item) => (
19
+ <DrawerNavigationItem compact={compact} item={item} key={item.id} testID={testID} />
20
+ ))}
21
+ </Stack>
22
+ {footer}
23
+ </Stack>
24
+ );
25
+ }
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+
3
+ import { NavigationItem } from './NavigationItem';
4
+ import type { DrawerNavigationItemProps } from './types';
5
+
6
+ export function DrawerNavigationItem({ item, compact = false, testID }: DrawerNavigationItemProps) {
7
+ return (
8
+ <NavigationItem
9
+ compact={compact}
10
+ item={{
11
+ ...item,
12
+ accessibilityRole: item.accessibilityRole ?? 'button',
13
+ }}
14
+ testID={testID}
15
+ />
16
+ );
17
+ }
@@ -0,0 +1,77 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+
4
+ import { Box } from '../../layout';
5
+ import { ButtonBase } from '../../primitives/button-base';
6
+ import { Icon } from '../../primitives/icon';
7
+ import { Text } from '../../primitives/text';
8
+ import { useTheme } from '../../theme/ThemeContext';
9
+ import { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';
10
+ import type { NavigationItemProps } from './types';
11
+
12
+ export function NavigationItem({ item, compact = false, testID }: NavigationItemProps) {
13
+ const { theme } = useTheme();
14
+ const active = Boolean(item.active);
15
+ const disabled = Boolean(item.disabled);
16
+ const resolvedTestID = item.testID ?? (testID ? `${testID}-item-${item.id}` : undefined);
17
+ const resolvedAccessibilityState = resolveNavigationAccessibilityState(
18
+ active,
19
+ disabled,
20
+ item.accessibilityState,
21
+ );
22
+
23
+ return (
24
+ <ButtonBase
25
+ accessibilityLabel={item.accessibilityLabel}
26
+ accessibilityRole={item.accessibilityRole ?? 'button'}
27
+ accessibilityState={resolvedAccessibilityState}
28
+ disabled={disabled}
29
+ onPress={item.onPress}
30
+ testID={resolvedTestID}
31
+ >
32
+ {(state) => {
33
+ const presentation = resolveNavigationItemPresentation(theme, {
34
+ active,
35
+ disabled,
36
+ state,
37
+ });
38
+
39
+ return (
40
+ <Box
41
+ px="m"
42
+ py={compact ? 's' : 'm'}
43
+ radius="m"
44
+ style={{
45
+ backgroundColor: presentation.backgroundColor,
46
+ flexDirection: 'row',
47
+ alignItems: 'center',
48
+ opacity: presentation.opacity,
49
+ }}
50
+ >
51
+ {item.icon ? (
52
+ <View style={{ marginRight: theme.spacing.s }}>
53
+ <Icon
54
+ color={presentation.contentColor}
55
+ name={item.icon.name}
56
+ provider={item.icon.provider}
57
+ size={compact ? 's' : 'm'}
58
+ />
59
+ </View>
60
+ ) : null}
61
+ <Box flex={1}>
62
+ <Text
63
+ color={presentation.contentColor}
64
+ numberOfLines={1}
65
+ variant={compact ? 'bodySmall' : 'body'}
66
+ weight="medium"
67
+ >
68
+ {item.label}
69
+ </Text>
70
+ </Box>
71
+ {item.badge ? <View style={{ marginLeft: theme.spacing.s }}>{item.badge}</View> : null}
72
+ </Box>
73
+ );
74
+ }}
75
+ </ButtonBase>
76
+ );
77
+ }
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+
3
+ import { Stack } from '../../layout';
4
+ import { NavigationItem } from './NavigationItem';
5
+ import type { NavigationListProps } from './types';
6
+
7
+ export function NavigationList({
8
+ items,
9
+ orientation = 'vertical',
10
+ compact = false,
11
+ testID,
12
+ }: NavigationListProps) {
13
+ return (
14
+ <Stack
15
+ direction={orientation === 'horizontal' ? 'row' : 'column'}
16
+ gap={compact ? 'xs' : 's'}
17
+ testID={testID}
18
+ >
19
+ {items.map((item) => (
20
+ <NavigationItem compact={compact} item={item} key={item.id} testID={testID} />
21
+ ))}
22
+ </Stack>
23
+ );
24
+ }
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+
3
+ import { Box } from '../../layout';
4
+ import { useTheme } from '../../theme/ThemeContext';
5
+ import { TabBarItem } from './TabBarItem';
6
+ import type { TabBarProps } from './types';
7
+
8
+ export function TabBar({ items, compact = false, testID }: TabBarProps) {
9
+ const { theme } = useTheme();
10
+
11
+ return (
12
+ <Box
13
+ style={{
14
+ flexDirection: 'row',
15
+ borderTopColor: theme.semantics.border.default,
16
+ borderTopWidth: 1,
17
+ }}
18
+ testID={testID}
19
+ >
20
+ {items.map((item) => (
21
+ <TabBarItem compact={compact} item={item} key={item.id} testID={testID} />
22
+ ))}
23
+ </Box>
24
+ );
25
+ }
@@ -0,0 +1,82 @@
1
+ import React from 'react';
2
+ import { View } from 'react-native';
3
+
4
+ import { Box } from '../../layout';
5
+ import { ButtonBase } from '../../primitives/button-base';
6
+ import { Icon } from '../../primitives/icon';
7
+ import { Text } from '../../primitives/text';
8
+ import { useTheme } from '../../theme/ThemeContext';
9
+ import { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';
10
+ import type { TabBarItemProps } from './types';
11
+
12
+ export function TabBarItem({ item, compact = false, testID }: TabBarItemProps) {
13
+ const { theme } = useTheme();
14
+ const active = Boolean(item.active);
15
+ const disabled = Boolean(item.disabled);
16
+ const resolvedTestID = item.testID ?? (testID ? `${testID}-item-${item.id}` : undefined);
17
+ const resolvedAccessibilityState = resolveNavigationAccessibilityState(
18
+ active,
19
+ disabled,
20
+ item.accessibilityState,
21
+ );
22
+
23
+ return (
24
+ <ButtonBase
25
+ accessibilityLabel={item.accessibilityLabel}
26
+ accessibilityRole={item.accessibilityRole ?? 'tab'}
27
+ accessibilityState={resolvedAccessibilityState}
28
+ disabled={disabled}
29
+ onPress={item.onPress}
30
+ style={{ flex: 1 }}
31
+ testID={resolvedTestID}
32
+ >
33
+ {(state) => {
34
+ const presentation = resolveNavigationItemPresentation(theme, {
35
+ active,
36
+ disabled,
37
+ state,
38
+ });
39
+ const contentColor = disabled
40
+ ? theme.semantics.content.muted
41
+ : active
42
+ ? theme.semantics.action.primary.base
43
+ : theme.semantics.content.muted;
44
+
45
+ return (
46
+ <Box
47
+ px="m"
48
+ py={compact ? 's' : 'm'}
49
+ style={{
50
+ flex: 1,
51
+ alignItems: 'center',
52
+ justifyContent: 'center',
53
+ backgroundColor: presentation.backgroundColor,
54
+ opacity: presentation.opacity,
55
+ }}
56
+ >
57
+ {item.icon ? (
58
+ <View style={{ marginBottom: item.label ? theme.spacing.xs : 0 }}>
59
+ <Icon
60
+ color={contentColor}
61
+ name={item.icon.name}
62
+ provider={item.icon.provider}
63
+ size={compact ? 's' : 'm'}
64
+ />
65
+ </View>
66
+ ) : null}
67
+ {item.label ? (
68
+ <Text
69
+ color={contentColor}
70
+ numberOfLines={1}
71
+ variant={compact ? 'bodySmall' : 'label'}
72
+ weight="medium"
73
+ >
74
+ {item.label}
75
+ </Text>
76
+ ) : null}
77
+ </Box>
78
+ );
79
+ }}
80
+ </ButtonBase>
81
+ );
82
+ }
@@ -0,0 +1,74 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+
3
+ import { createTheme } from '../../theme/createTheme';
4
+ import { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';
5
+
6
+ describe('navigation helpers', () => {
7
+ it('forces selected and disabled when active/disabled are true', () => {
8
+ expect(
9
+ resolveNavigationAccessibilityState(true, true, {
10
+ selected: false,
11
+ disabled: false,
12
+ }),
13
+ ).toEqual({
14
+ selected: true,
15
+ disabled: true,
16
+ });
17
+ });
18
+
19
+ it('preserves user-provided state when not active/disabled', () => {
20
+ expect(
21
+ resolveNavigationAccessibilityState(false, false, {
22
+ disabled: false,
23
+ selected: false,
24
+ expanded: true,
25
+ }),
26
+ ).toEqual({
27
+ disabled: false,
28
+ selected: false,
29
+ expanded: true,
30
+ });
31
+ });
32
+
33
+ it('resolves active presentation via primary soft semantics', () => {
34
+ const theme = createTheme();
35
+ const state = { pressed: false, hovered: true, focused: false, disabled: false };
36
+ const resolved = resolveNavigationItemPresentation(theme, {
37
+ active: true,
38
+ disabled: false,
39
+ state,
40
+ });
41
+
42
+ expect(resolved.backgroundColor).toBe(theme.semantics.action.primary.softHover);
43
+ expect(resolved.contentColor).toBe(theme.semantics.action.primary.base);
44
+ expect(resolved.opacity).toBe(1);
45
+ });
46
+
47
+ it('resolves inactive presentation via neutral hover/active semantics', () => {
48
+ const theme = createTheme();
49
+ const state = { pressed: true, hovered: true, focused: false, disabled: false };
50
+ const resolved = resolveNavigationItemPresentation(theme, {
51
+ active: false,
52
+ disabled: false,
53
+ state,
54
+ });
55
+
56
+ expect(resolved.backgroundColor).toBe(theme.semantics.neutral.surfaceActive);
57
+ expect(resolved.contentColor).toBe(theme.semantics.content.default);
58
+ expect(resolved.opacity).toBe(1);
59
+ });
60
+
61
+ it('ignores hover/pressed presentation when disabled', () => {
62
+ const theme = createTheme();
63
+ const state = { pressed: true, hovered: true, focused: false, disabled: true };
64
+ const resolved = resolveNavigationItemPresentation(theme, {
65
+ active: true,
66
+ disabled: true,
67
+ state,
68
+ });
69
+
70
+ expect(resolved.backgroundColor).toBe(theme.semantics.action.primary.softBg);
71
+ expect(resolved.contentColor).toBe(theme.semantics.content.muted);
72
+ expect(resolved.opacity).toBe(0.72);
73
+ });
74
+ });
@@ -0,0 +1,72 @@
1
+ import type { AccessibilityState } from 'react-native';
2
+
3
+ import type { InteractionState } from '../../internal/resolvers/resolveInteractiveState';
4
+ import type { SurfaceTheme } from '../../theme/types';
5
+
6
+ export function resolveNavigationAccessibilityState(
7
+ active: boolean,
8
+ disabled: boolean,
9
+ accessibilityState?: AccessibilityState,
10
+ ): AccessibilityState {
11
+ const resolved: AccessibilityState = { ...(accessibilityState ?? {}) };
12
+
13
+ if (active) {
14
+ resolved.selected = true;
15
+ }
16
+
17
+ if (disabled) {
18
+ resolved.disabled = true;
19
+ }
20
+
21
+ return resolved;
22
+ }
23
+
24
+ export interface ResolvedNavigationItemPresentation {
25
+ backgroundColor: string;
26
+ contentColor: string;
27
+ opacity: number;
28
+ }
29
+
30
+ export function resolveNavigationItemPresentation(
31
+ theme: SurfaceTheme,
32
+ {
33
+ active,
34
+ disabled,
35
+ state,
36
+ }: {
37
+ active: boolean;
38
+ disabled: boolean;
39
+ state: InteractionState;
40
+ },
41
+ ): ResolvedNavigationItemPresentation {
42
+ const interactionState = disabled ? { ...state, hovered: false, pressed: false } : state;
43
+
44
+ const opacity = disabled ? 0.72 : 1;
45
+ const contentColor = disabled
46
+ ? theme.semantics.content.muted
47
+ : active
48
+ ? theme.semantics.action.primary.base
49
+ : theme.semantics.content.default;
50
+
51
+ if (active) {
52
+ return {
53
+ backgroundColor: interactionState.pressed
54
+ ? theme.semantics.action.primary.softActive
55
+ : interactionState.hovered
56
+ ? theme.semantics.action.primary.softHover
57
+ : theme.semantics.action.primary.softBg,
58
+ contentColor,
59
+ opacity,
60
+ };
61
+ }
62
+
63
+ return {
64
+ backgroundColor: interactionState.pressed
65
+ ? theme.semantics.neutral.surfaceActive
66
+ : interactionState.hovered
67
+ ? theme.semantics.neutral.surfaceHover
68
+ : 'transparent',
69
+ contentColor,
70
+ opacity,
71
+ };
72
+ }
@@ -0,0 +1,16 @@
1
+ export { DrawerNavigation } from './DrawerNavigation';
2
+ export { DrawerNavigationItem } from './DrawerNavigationItem';
3
+ export { NavigationItem } from './NavigationItem';
4
+ export { NavigationList } from './NavigationList';
5
+ export { TabBar } from './TabBar';
6
+ export { TabBarItem } from './TabBarItem';
7
+ export type {
8
+ DrawerNavigationItemProps,
9
+ DrawerNavigationProps,
10
+ NavigationItemIcon,
11
+ NavigationItemProps,
12
+ NavigationItemSpec,
13
+ NavigationListProps,
14
+ TabBarItemProps,
15
+ TabBarProps,
16
+ } from './types';
@@ -0,0 +1,44 @@
1
+ import { readdirSync, readFileSync } from 'node:fs';
2
+ import { extname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ import { describe, expect, it } from 'bun:test';
6
+
7
+ const navigationDir = fileURLToPath(new URL('.', import.meta.url));
8
+
9
+ const forbiddenPatterns = [
10
+ 'expo-router',
11
+ '@react-navigation',
12
+ 'AppManifest',
13
+ 'NavigatorSpec',
14
+ 'generated app',
15
+ 'templates',
16
+ ] as const;
17
+
18
+ function listNavigationSources() {
19
+ return readdirSync(navigationDir)
20
+ .filter((entry) => {
21
+ const extension = extname(entry);
22
+ if (!(extension === '.ts' || extension === '.tsx')) {
23
+ return false;
24
+ }
25
+
26
+ return !entry.includes('.test.');
27
+ })
28
+ .map((entry) => join(navigationDir, entry));
29
+ }
30
+
31
+ describe('navigation module boundaries', () => {
32
+ it('does not import routers, manifests, or generated app code', () => {
33
+ const sources = listNavigationSources().map((path) => ({
34
+ path,
35
+ content: readFileSync(path, 'utf8'),
36
+ }));
37
+
38
+ sources.forEach(({ content, path }) => {
39
+ forbiddenPatterns.forEach((pattern) => {
40
+ expect(content, path).not.toContain(pattern);
41
+ });
42
+ });
43
+ });
44
+ });
@@ -0,0 +1,59 @@
1
+ import type React from 'react';
2
+ import type { AccessibilityRole, AccessibilityState } from 'react-native';
3
+
4
+ import type { IconProps } from '../../primitives/icon';
5
+
6
+ export type NavigationItemIcon = Pick<IconProps, 'name' | 'provider'>;
7
+
8
+ export interface NavigationItemSpec {
9
+ id: string;
10
+ label: React.ReactNode;
11
+ icon?: NavigationItemIcon;
12
+ badge?: React.ReactNode;
13
+ active?: boolean;
14
+ disabled?: boolean;
15
+ onPress?: (() => void) | undefined;
16
+ accessibilityLabel?: string;
17
+ accessibilityRole?: AccessibilityRole;
18
+ accessibilityState?: AccessibilityState;
19
+ testID?: string;
20
+ }
21
+
22
+ export interface NavigationItemProps {
23
+ item: NavigationItemSpec;
24
+ compact?: boolean;
25
+ testID?: string;
26
+ }
27
+
28
+ export interface NavigationListProps {
29
+ items: readonly NavigationItemSpec[];
30
+ orientation?: 'vertical' | 'horizontal';
31
+ compact?: boolean;
32
+ testID?: string;
33
+ }
34
+
35
+ export interface TabBarProps {
36
+ items: readonly NavigationItemSpec[];
37
+ compact?: boolean;
38
+ testID?: string;
39
+ }
40
+
41
+ export interface TabBarItemProps {
42
+ item: NavigationItemSpec;
43
+ compact?: boolean;
44
+ testID?: string;
45
+ }
46
+
47
+ export interface DrawerNavigationProps {
48
+ items: readonly NavigationItemSpec[];
49
+ header?: React.ReactNode;
50
+ footer?: React.ReactNode;
51
+ compact?: boolean;
52
+ testID?: string;
53
+ }
54
+
55
+ export interface DrawerNavigationItemProps {
56
+ item: NavigationItemSpec;
57
+ compact?: boolean;
58
+ testID?: string;
59
+ }
package/src/index.test.ts CHANGED
@@ -21,6 +21,7 @@ const expectedRootExports = [
21
21
  "export { IconButton } from './components/icon-button';",
22
22
  "export { Label } from './components/label';",
23
23
  "export { ListItem } from './components/list-item';",
24
+ "export {\n DrawerNavigation,\n DrawerNavigationItem,\n NavigationItem,\n NavigationList,\n TabBar,\n TabBarItem,\n} from './components/navigation';",
24
25
  "export { Menu } from './components/menu';",
25
26
  "export { Modal } from './components/modal';",
26
27
  "export { Radio } from './components/radio';",
package/src/index.ts CHANGED
@@ -22,6 +22,24 @@ export type { MenuItem, MenuProps } from './components/menu';
22
22
  export { Menu } from './components/menu';
23
23
  export type { ModalProps } from './components/modal';
24
24
  export { Modal } from './components/modal';
25
+ export type {
26
+ DrawerNavigationItemProps,
27
+ DrawerNavigationProps,
28
+ NavigationItemIcon,
29
+ NavigationItemProps,
30
+ NavigationItemSpec,
31
+ NavigationListProps,
32
+ TabBarItemProps,
33
+ TabBarProps,
34
+ } from './components/navigation';
35
+ export {
36
+ DrawerNavigation,
37
+ DrawerNavigationItem,
38
+ NavigationItem,
39
+ NavigationList,
40
+ TabBar,
41
+ TabBarItem,
42
+ } from './components/navigation';
25
43
  export type { RadioProps } from './components/radio';
26
44
  export { Radio } from './components/radio';
27
45
  export type { SwitchProps } from './components/switch';