@ankhorage/zora 4.5.0 → 6.0.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 (206) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +13 -10
  3. package/dist/components/button/resolveButtonThemeRecipe.d.ts +1 -1
  4. package/dist/components/date-picker/DatePicker.d.ts.map +1 -1
  5. package/dist/components/date-picker/DatePicker.js +92 -86
  6. package/dist/components/date-picker/DatePicker.js.map +1 -1
  7. package/dist/components/date-picker/meta.d.ts +1 -1
  8. package/dist/components/date-picker/meta.js +1 -1
  9. package/dist/components/date-picker/meta.js.map +1 -1
  10. package/dist/components/heading/resolveHeadingThemeRecipe.d.ts +1 -1
  11. package/dist/components/text/resolveTextThemeRecipe.d.ts +1 -1
  12. package/dist/components/time-picker/TimePicker.d.ts +1 -3
  13. package/dist/components/time-picker/TimePicker.d.ts.map +1 -1
  14. package/dist/components/time-picker/TimePicker.js +55 -32
  15. package/dist/components/time-picker/TimePicker.js.map +1 -1
  16. package/dist/components/time-picker/meta.d.ts +1 -1
  17. package/dist/components/time-picker/meta.js +1 -1
  18. package/dist/components/time-picker/meta.js.map +1 -1
  19. package/dist/features/bottom-sheet/public.d.ts +3 -0
  20. package/dist/features/bottom-sheet/public.d.ts.map +1 -0
  21. package/dist/features/bottom-sheet/public.js +2 -0
  22. package/dist/features/bottom-sheet/public.js.map +1 -0
  23. package/dist/index.d.ts +0 -14
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +0 -7
  26. package/dist/index.js.map +1 -1
  27. package/dist/metadata/componentMeta.d.ts.map +1 -1
  28. package/dist/metadata/componentMeta.js +0 -15
  29. package/dist/metadata/componentMeta.js.map +1 -1
  30. package/dist/registry.d.ts.map +1 -1
  31. package/dist/registry.js +0 -15
  32. package/dist/registry.js.map +1 -1
  33. package/dist/theme/ZoraProvider.d.ts +1 -1
  34. package/dist/theme/ZoraProvider.d.ts.map +1 -1
  35. package/dist/theme/ZoraProvider.js +3 -2
  36. package/dist/theme/ZoraProvider.js.map +1 -1
  37. package/dist/theme/useZoraTheme.d.ts +1 -1
  38. package/package.json +16 -3
  39. package/src/audit.test.ts +0 -29
  40. package/src/components/date-picker/DatePicker.tsx +197 -129
  41. package/src/components/date-picker/meta.ts +1 -1
  42. package/src/components/time-picker/TimePicker.tsx +147 -60
  43. package/src/components/time-picker/meta.ts +1 -1
  44. package/src/expo57Migration.test.ts +56 -0
  45. package/src/features/bottom-sheet/public.test.ts +39 -0
  46. package/src/features/bottom-sheet/public.ts +5 -0
  47. package/src/index.ts +0 -25
  48. package/src/interactionPolicy.test.ts +0 -17
  49. package/src/metadata/componentMeta.ts +0 -15
  50. package/src/platformAcceptance.test.ts +1 -1
  51. package/src/registry.ts +0 -15
  52. package/src/showcaseCoverage.test.ts +0 -6
  53. package/src/theme/ZoraProvider.tsx +3 -2
  54. package/src/theme/themeScopeStructure.test.ts +0 -4
  55. package/dist/components/action-sheet/ActionSheet.d.ts +0 -7
  56. package/dist/components/action-sheet/ActionSheet.d.ts.map +0 -1
  57. package/dist/components/action-sheet/ActionSheet.js +0 -11
  58. package/dist/components/action-sheet/ActionSheet.js.map +0 -1
  59. package/dist/components/action-sheet/ActionSheetItem.d.ts +0 -7
  60. package/dist/components/action-sheet/ActionSheetItem.d.ts.map +0 -1
  61. package/dist/components/action-sheet/ActionSheetItem.js +0 -17
  62. package/dist/components/action-sheet/ActionSheetItem.js.map +0 -1
  63. package/dist/components/action-sheet/index.d.ts +0 -4
  64. package/dist/components/action-sheet/index.d.ts.map +0 -1
  65. package/dist/components/action-sheet/index.js +0 -3
  66. package/dist/components/action-sheet/index.js.map +0 -1
  67. package/dist/components/action-sheet/meta.d.ts +0 -17
  68. package/dist/components/action-sheet/meta.d.ts.map +0 -1
  69. package/dist/components/action-sheet/meta.js +0 -17
  70. package/dist/components/action-sheet/meta.js.map +0 -1
  71. package/dist/components/action-sheet/types.d.ts +0 -13
  72. package/dist/components/action-sheet/types.d.ts.map +0 -1
  73. package/dist/components/action-sheet/types.js +0 -2
  74. package/dist/components/action-sheet/types.js.map +0 -1
  75. package/dist/components/drawer/Drawer.d.ts +0 -7
  76. package/dist/components/drawer/Drawer.d.ts.map +0 -1
  77. package/dist/components/drawer/Drawer.js +0 -36
  78. package/dist/components/drawer/Drawer.js.map +0 -1
  79. package/dist/components/drawer/index.d.ts +0 -3
  80. package/dist/components/drawer/index.d.ts.map +0 -1
  81. package/dist/components/drawer/index.js +0 -2
  82. package/dist/components/drawer/index.js.map +0 -1
  83. package/dist/components/drawer/meta.d.ts +0 -9
  84. package/dist/components/drawer/meta.d.ts.map +0 -1
  85. package/dist/components/drawer/meta.js +0 -9
  86. package/dist/components/drawer/meta.js.map +0 -1
  87. package/dist/components/drawer/types.d.ts +0 -10
  88. package/dist/components/drawer/types.d.ts.map +0 -1
  89. package/dist/components/drawer/types.js +0 -2
  90. package/dist/components/drawer/types.js.map +0 -1
  91. package/dist/components/navigation-item/NavigationItem.d.ts +0 -7
  92. package/dist/components/navigation-item/NavigationItem.d.ts.map +0 -1
  93. package/dist/components/navigation-item/NavigationItem.js +0 -21
  94. package/dist/components/navigation-item/NavigationItem.js.map +0 -1
  95. package/dist/components/navigation-item/index.d.ts +0 -3
  96. package/dist/components/navigation-item/index.d.ts.map +0 -1
  97. package/dist/components/navigation-item/index.js +0 -2
  98. package/dist/components/navigation-item/index.js.map +0 -1
  99. package/dist/components/navigation-item/meta.d.ts +0 -9
  100. package/dist/components/navigation-item/meta.d.ts.map +0 -1
  101. package/dist/components/navigation-item/meta.js +0 -9
  102. package/dist/components/navigation-item/meta.js.map +0 -1
  103. package/dist/components/navigation-item/types.d.ts +0 -23
  104. package/dist/components/navigation-item/types.d.ts.map +0 -1
  105. package/dist/components/navigation-item/types.js +0 -2
  106. package/dist/components/navigation-item/types.js.map +0 -1
  107. package/dist/components/navigation-list/NavigationList.d.ts +0 -7
  108. package/dist/components/navigation-list/NavigationList.d.ts.map +0 -1
  109. package/dist/components/navigation-list/NavigationList.js +0 -29
  110. package/dist/components/navigation-list/NavigationList.js.map +0 -1
  111. package/dist/components/navigation-list/index.d.ts +0 -3
  112. package/dist/components/navigation-list/index.d.ts.map +0 -1
  113. package/dist/components/navigation-list/index.js +0 -2
  114. package/dist/components/navigation-list/index.js.map +0 -1
  115. package/dist/components/navigation-list/meta.d.ts +0 -9
  116. package/dist/components/navigation-list/meta.d.ts.map +0 -1
  117. package/dist/components/navigation-list/meta.js +0 -9
  118. package/dist/components/navigation-list/meta.js.map +0 -1
  119. package/dist/components/navigation-list/types.d.ts +0 -15
  120. package/dist/components/navigation-list/types.d.ts.map +0 -1
  121. package/dist/components/navigation-list/types.js +0 -2
  122. package/dist/components/navigation-list/types.js.map +0 -1
  123. package/dist/internal/resolveZoraNavigationItems.d.ts +0 -65
  124. package/dist/internal/resolveZoraNavigationItems.d.ts.map +0 -1
  125. package/dist/internal/resolveZoraNavigationItems.js +0 -56
  126. package/dist/internal/resolveZoraNavigationItems.js.map +0 -1
  127. package/dist/patterns/responsive-panel/ResponsivePanel.d.ts +0 -16
  128. package/dist/patterns/responsive-panel/ResponsivePanel.d.ts.map +0 -1
  129. package/dist/patterns/responsive-panel/ResponsivePanel.js +0 -101
  130. package/dist/patterns/responsive-panel/ResponsivePanel.js.map +0 -1
  131. package/dist/patterns/responsive-panel/index.d.ts +0 -3
  132. package/dist/patterns/responsive-panel/index.d.ts.map +0 -1
  133. package/dist/patterns/responsive-panel/index.js +0 -3
  134. package/dist/patterns/responsive-panel/index.js.map +0 -1
  135. package/dist/patterns/responsive-panel/meta.d.ts +0 -9
  136. package/dist/patterns/responsive-panel/meta.d.ts.map +0 -1
  137. package/dist/patterns/responsive-panel/meta.js +0 -9
  138. package/dist/patterns/responsive-panel/meta.js.map +0 -1
  139. package/dist/patterns/responsive-panel/types.d.ts +0 -23
  140. package/dist/patterns/responsive-panel/types.d.ts.map +0 -1
  141. package/dist/patterns/responsive-panel/types.js +0 -2
  142. package/dist/patterns/responsive-panel/types.js.map +0 -1
  143. package/dist/patterns/zora-drawer-content/ZoraDrawerContent.d.ts +0 -9
  144. package/dist/patterns/zora-drawer-content/ZoraDrawerContent.d.ts.map +0 -1
  145. package/dist/patterns/zora-drawer-content/ZoraDrawerContent.js +0 -31
  146. package/dist/patterns/zora-drawer-content/ZoraDrawerContent.js.map +0 -1
  147. package/dist/patterns/zora-drawer-content/index.d.ts +0 -3
  148. package/dist/patterns/zora-drawer-content/index.d.ts.map +0 -1
  149. package/dist/patterns/zora-drawer-content/index.js +0 -2
  150. package/dist/patterns/zora-drawer-content/index.js.map +0 -1
  151. package/dist/patterns/zora-drawer-content/meta.d.ts +0 -9
  152. package/dist/patterns/zora-drawer-content/meta.d.ts.map +0 -1
  153. package/dist/patterns/zora-drawer-content/meta.js +0 -9
  154. package/dist/patterns/zora-drawer-content/meta.js.map +0 -1
  155. package/dist/patterns/zora-drawer-content/types.d.ts +0 -15
  156. package/dist/patterns/zora-drawer-content/types.d.ts.map +0 -1
  157. package/dist/patterns/zora-drawer-content/types.js +0 -2
  158. package/dist/patterns/zora-drawer-content/types.js.map +0 -1
  159. package/dist/patterns/zora-tab-bar/ZoraTabBar.d.ts +0 -9
  160. package/dist/patterns/zora-tab-bar/ZoraTabBar.d.ts.map +0 -1
  161. package/dist/patterns/zora-tab-bar/ZoraTabBar.js +0 -89
  162. package/dist/patterns/zora-tab-bar/ZoraTabBar.js.map +0 -1
  163. package/dist/patterns/zora-tab-bar/index.d.ts +0 -3
  164. package/dist/patterns/zora-tab-bar/index.d.ts.map +0 -1
  165. package/dist/patterns/zora-tab-bar/index.js +0 -2
  166. package/dist/patterns/zora-tab-bar/index.js.map +0 -1
  167. package/dist/patterns/zora-tab-bar/meta.d.ts +0 -9
  168. package/dist/patterns/zora-tab-bar/meta.d.ts.map +0 -1
  169. package/dist/patterns/zora-tab-bar/meta.js +0 -9
  170. package/dist/patterns/zora-tab-bar/meta.js.map +0 -1
  171. package/dist/patterns/zora-tab-bar/types.d.ts +0 -19
  172. package/dist/patterns/zora-tab-bar/types.d.ts.map +0 -1
  173. package/dist/patterns/zora-tab-bar/types.js +0 -2
  174. package/dist/patterns/zora-tab-bar/types.js.map +0 -1
  175. package/src/components/action-sheet/ActionSheet.tsx +0 -14
  176. package/src/components/action-sheet/ActionSheetItem.tsx +0 -30
  177. package/src/components/action-sheet/index.ts +0 -3
  178. package/src/components/action-sheet/meta.ts +0 -19
  179. package/src/components/action-sheet/types.ts +0 -23
  180. package/src/components/drawer/Drawer.tsx +0 -59
  181. package/src/components/drawer/index.ts +0 -2
  182. package/src/components/drawer/meta.ts +0 -10
  183. package/src/components/drawer/types.ts +0 -17
  184. package/src/components/navigation-item/NavigationItem.tsx +0 -41
  185. package/src/components/navigation-item/index.ts +0 -6
  186. package/src/components/navigation-item/meta.ts +0 -10
  187. package/src/components/navigation-item/types.ts +0 -26
  188. package/src/components/navigation-list/NavigationList.tsx +0 -68
  189. package/src/components/navigation-list/index.ts +0 -2
  190. package/src/components/navigation-list/meta.ts +0 -10
  191. package/src/components/navigation-list/types.ts +0 -17
  192. package/src/internal/resolveZoraNavigationItems.test.ts +0 -174
  193. package/src/internal/resolveZoraNavigationItems.ts +0 -157
  194. package/src/navigationExports.test.ts +0 -15
  195. package/src/patterns/responsive-panel/ResponsivePanel.tsx +0 -172
  196. package/src/patterns/responsive-panel/index.ts +0 -2
  197. package/src/patterns/responsive-panel/meta.ts +0 -10
  198. package/src/patterns/responsive-panel/types.ts +0 -25
  199. package/src/patterns/zora-drawer-content/ZoraDrawerContent.tsx +0 -60
  200. package/src/patterns/zora-drawer-content/index.ts +0 -2
  201. package/src/patterns/zora-drawer-content/meta.ts +0 -10
  202. package/src/patterns/zora-drawer-content/types.ts +0 -20
  203. package/src/patterns/zora-tab-bar/ZoraTabBar.tsx +0 -157
  204. package/src/patterns/zora-tab-bar/index.ts +0 -2
  205. package/src/patterns/zora-tab-bar/meta.ts +0 -10
  206. package/src/patterns/zora-tab-bar/types.ts +0 -18
@@ -1,174 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
- import React from 'react';
3
-
4
- import {
5
- createDrawerItemPressHandler,
6
- createTabBarItemPressHandler,
7
- resolveNavigationItems,
8
- resolveRouteLabel,
9
- type ZoraNavigationDescriptor,
10
- type ZoraNavigationState,
11
- type ZoraResolvedNavigationItem,
12
- type ZoraRouteLabelSource,
13
- } from './resolveZoraNavigationItems';
14
-
15
- describe('resolveRouteLabel', () => {
16
- test('prefers routeMap label over descriptor label', () => {
17
- const descriptor: ZoraNavigationDescriptor = {
18
- options: {
19
- title: 'Home Title',
20
- tabBarLabel: 'Home Tab',
21
- },
22
- };
23
-
24
- const result = resolveRouteLabel({
25
- kind: 'tab',
26
- route: { key: 'k1', name: 'home' },
27
- metadata: { label: 'Home Map' },
28
- descriptor,
29
- });
30
-
31
- const expectedSource: ZoraRouteLabelSource = 'routeMap';
32
- expect(result).toEqual({ label: 'Home Map', source: expectedSource });
33
- });
34
-
35
- test('uses descriptor label/title as fallback for label only', () => {
36
- const descriptor: ZoraNavigationDescriptor = {
37
- options: {
38
- title: 'Settings Title',
39
- tabBarLabel: undefined,
40
- },
41
- };
42
-
43
- const result = resolveRouteLabel({
44
- kind: 'tab',
45
- route: { key: 'k2', name: 'settings' },
46
- metadata: undefined,
47
- descriptor,
48
- });
49
-
50
- expect(result).toEqual({ label: 'Settings Title', source: 'descriptor' });
51
- });
52
-
53
- test('falls back to route name if nothing else provided', () => {
54
- const result = resolveRouteLabel({
55
- kind: 'drawer',
56
- route: { key: 'k3', name: 'profile' },
57
- metadata: undefined,
58
- descriptor: undefined,
59
- });
60
-
61
- expect(result).toEqual({ label: 'profile', source: 'name' });
62
- });
63
-
64
- test('uses descriptor title instead of invoking a callable Expo tab label', () => {
65
- const result = resolveRouteLabel({
66
- route: { key: 'k4', name: 'home' },
67
- metadata: undefined,
68
- descriptor: { options: { tabBarLabel: () => 'callable', title: 'Home title' } },
69
- kind: 'tab',
70
- });
71
-
72
- expect(result).toEqual({ label: 'Home title', source: 'descriptor' });
73
- });
74
- });
75
-
76
- describe('resolveNavigationItems', () => {
77
- test('maps active index + routeMap disabled state without using descriptors for icons/badges', () => {
78
- const state: ZoraNavigationState = {
79
- index: 1,
80
- routes: [
81
- { key: 'r1', name: 'home' },
82
- { key: 'r2', name: 'settings' },
83
- ],
84
- };
85
-
86
- const items = resolveNavigationItems({
87
- state,
88
- kind: 'tab',
89
- descriptors: {
90
- r1: { options: { tabBarLabel: 'Home Opt', title: 'Home Title' } },
91
- r2: { options: { tabBarLabel: 'Settings Opt' } },
92
- },
93
- routeMap: {
94
- settings: { disabled: true, badge: React.createElement('span', null, '3') },
95
- },
96
- });
97
-
98
- expect(items).toHaveLength(2);
99
- expect(items[0]).toMatchObject({ active: false, disabled: false });
100
- expect(items[1]).toMatchObject({ active: true, disabled: true });
101
- expect(items[1]?.metadata?.badge).toBeDefined();
102
- });
103
- });
104
-
105
- describe('press handler helpers', () => {
106
- test('tab press handler is undefined for disabled or active items', () => {
107
- const handlerDisabled = createTabBarItemPressHandler({
108
- item: {
109
- route: { key: 'k1', name: 'home' },
110
- metadata: { disabled: true },
111
- label: 'Home',
112
- active: false,
113
- disabled: true,
114
- },
115
- navigation: { navigate: () => undefined },
116
- });
117
- expect(handlerDisabled).toBeUndefined();
118
-
119
- const handlerActive = createTabBarItemPressHandler({
120
- item: {
121
- route: { key: 'k1', name: 'home' },
122
- metadata: undefined,
123
- label: 'Home',
124
- active: true,
125
- disabled: false,
126
- },
127
- navigation: { navigate: () => undefined },
128
- });
129
- expect(handlerActive).toBeUndefined();
130
- });
131
-
132
- test('tab press handler respects preventDefault', () => {
133
- let navigatedTo: string | null = null;
134
- const handler = createTabBarItemPressHandler({
135
- item: {
136
- route: { key: 'k1', name: 'home' },
137
- metadata: undefined,
138
- label: 'Home',
139
- active: false,
140
- disabled: false,
141
- },
142
- navigation: {
143
- emit: () => ({ defaultPrevented: true }),
144
- navigate: (name) => {
145
- navigatedTo = name;
146
- },
147
- },
148
- });
149
-
150
- expect(handler).toBeDefined();
151
- handler?.();
152
- expect(navigatedTo).toBeNull();
153
- });
154
-
155
- test('drawer press handler navigates and closes drawer', () => {
156
- const calls: string[] = [];
157
- const handler = createDrawerItemPressHandler({
158
- item: {
159
- route: { key: 'k1', name: 'home' },
160
- metadata: undefined,
161
- label: 'Home',
162
- active: false,
163
- disabled: false,
164
- } satisfies ZoraResolvedNavigationItem,
165
- navigation: {
166
- navigate: (name) => calls.push(`navigate:${name}`),
167
- closeDrawer: () => calls.push('close'),
168
- },
169
- });
170
-
171
- handler?.();
172
- expect(calls).toEqual(['navigate:home', 'close']);
173
- });
174
- });
@@ -1,157 +0,0 @@
1
- import type React from 'react';
2
-
3
- import type {
4
- ZoraNavigationRouteMetadata,
5
- ZoraNavigationRouteState,
6
- } from '../components/navigation-item';
7
- import type { ZoraNavigationRouteMap } from '../components/navigation-list';
8
-
9
- interface ZoraNavigationDescriptorOptions {
10
- title?: string;
11
- tabBarLabel?: unknown;
12
- drawerLabel?: unknown;
13
- }
14
-
15
- export interface ZoraNavigationDescriptor {
16
- options?: ZoraNavigationDescriptorOptions;
17
- }
18
-
19
- export type ZoraNavigationDescriptors = Readonly<
20
- Record<string, ZoraNavigationDescriptor | undefined>
21
- >;
22
-
23
- export interface ZoraNavigationState {
24
- index: number;
25
- routes: readonly ZoraNavigationRouteState[];
26
- }
27
-
28
- interface ZoraTabPressEvent {
29
- type: 'tabPress';
30
- target: string;
31
- canPreventDefault: true;
32
- }
33
-
34
- interface ZoraTabPressEventResult {
35
- defaultPrevented: boolean;
36
- }
37
-
38
- export interface ZoraTabBarNavigation {
39
- emit?: (event: ZoraTabPressEvent) => ZoraTabPressEventResult;
40
- navigate: (name: string) => void;
41
- }
42
-
43
- export interface ZoraDrawerNavigation {
44
- navigate: (name: string) => void;
45
- closeDrawer?: () => void;
46
- }
47
-
48
- export interface ZoraResolvedNavigationItem {
49
- route: ZoraNavigationRouteState;
50
- metadata?: ZoraNavigationRouteMetadata;
51
- label: React.ReactNode;
52
- active: boolean;
53
- disabled: boolean;
54
- }
55
-
56
- export type ZoraRouteLabelSource = 'routeMap' | 'descriptor' | 'name';
57
-
58
- export function resolveRouteLabel({
59
- route,
60
- metadata,
61
- descriptor,
62
- kind,
63
- }: {
64
- route: ZoraNavigationRouteState;
65
- metadata: ZoraNavigationRouteMetadata | undefined;
66
- descriptor: ZoraNavigationDescriptor | undefined;
67
- kind: 'tab' | 'drawer';
68
- }): { label: React.ReactNode; source: ZoraRouteLabelSource } {
69
- if (metadata?.label !== undefined) {
70
- return { label: metadata.label, source: 'routeMap' };
71
- }
72
-
73
- const options = descriptor?.options;
74
- const configuredLabel = kind === 'tab' ? options?.tabBarLabel : options?.drawerLabel;
75
- const fallback =
76
- configuredLabel === undefined || typeof configuredLabel === 'function'
77
- ? options?.title
78
- : configuredLabel;
79
-
80
- if (fallback !== undefined) {
81
- return { label: fallback as React.ReactNode, source: 'descriptor' };
82
- }
83
-
84
- return { label: route.name, source: 'name' };
85
- }
86
-
87
- export function resolveNavigationItems({
88
- state,
89
- descriptors,
90
- routeMap,
91
- kind,
92
- }: {
93
- state: ZoraNavigationState;
94
- descriptors?: ZoraNavigationDescriptors | undefined;
95
- routeMap?: ZoraNavigationRouteMap | undefined;
96
- kind: 'tab' | 'drawer';
97
- }): readonly ZoraResolvedNavigationItem[] {
98
- const activeRoute = state.routes[state.index];
99
-
100
- return state.routes.map((route) => {
101
- const metadata = routeMap?.[route.name];
102
- const descriptor = descriptors?.[route.key];
103
- const { label } = resolveRouteLabel({ route, metadata, descriptor, kind });
104
- const disabled = Boolean(metadata?.disabled);
105
-
106
- return {
107
- route,
108
- metadata,
109
- label,
110
- active: activeRoute ? activeRoute.key === route.key : false,
111
- disabled,
112
- };
113
- });
114
- }
115
-
116
- export function createTabBarItemPressHandler({
117
- item,
118
- navigation,
119
- }: {
120
- item: ZoraResolvedNavigationItem;
121
- navigation: ZoraTabBarNavigation;
122
- }): (() => void) | undefined {
123
- if (item.disabled || item.active) {
124
- return undefined;
125
- }
126
-
127
- return () => {
128
- const result = navigation.emit?.({
129
- type: 'tabPress',
130
- target: item.route.key,
131
- canPreventDefault: true,
132
- });
133
-
134
- if (result?.defaultPrevented) {
135
- return;
136
- }
137
-
138
- navigation.navigate(item.route.name);
139
- };
140
- }
141
-
142
- export function createDrawerItemPressHandler({
143
- item,
144
- navigation,
145
- }: {
146
- item: ZoraResolvedNavigationItem;
147
- navigation: ZoraDrawerNavigation;
148
- }): (() => void) | undefined {
149
- if (item.disabled) {
150
- return undefined;
151
- }
152
-
153
- return () => {
154
- navigation.navigate(item.route.name);
155
- navigation.closeDrawer?.();
156
- };
157
- }
@@ -1,15 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
-
4
- import { describe, expect, test } from 'bun:test';
5
-
6
- describe('navigation exports', () => {
7
- test('exports navigation chrome from src/index.ts', () => {
8
- const source = readFileSync(join(process.cwd(), 'src', 'index.ts'), 'utf8');
9
-
10
- expect(source).toContain('export { NavigationItem }');
11
- expect(source).toContain('export { NavigationList }');
12
- expect(source).toContain('export { ZoraTabBar }');
13
- expect(source).toContain('export { ZoraDrawerContent }');
14
- });
15
- });
@@ -1,172 +0,0 @@
1
- import React from 'react';
2
- import { ScrollView, StyleSheet, View } from 'react-native';
3
-
4
- import { Drawer } from '../../components/drawer';
5
- import { Modal } from '../../components/modal';
6
- import type { ZoraContentWidth } from '../../internal/recipes';
7
- import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
8
- import { Panel } from '../panel';
9
- import type { ResponsivePanelProps, ResponsivePanelScroll, ResponsivePanelSize } from './types';
10
-
11
- function resolvePanelWidth(size: ResponsivePanelSize): number {
12
- switch (size) {
13
- case 'compact':
14
- return 300;
15
- case 'wide':
16
- return 420;
17
- case 'extraWide':
18
- return 560;
19
- case 'default':
20
- default:
21
- return 360;
22
- }
23
- }
24
-
25
- function resolveModalWidth(size: ResponsivePanelSize | undefined): ZoraContentWidth | undefined {
26
- switch (size) {
27
- case 'compact':
28
- return 'narrow';
29
- case 'wide':
30
- case 'extraWide':
31
- return 'wide';
32
- case 'default':
33
- return 'default';
34
- default:
35
- return undefined;
36
- }
37
- }
38
-
39
- function renderPanelBody(children: React.ReactNode, scroll: ResponsivePanelScroll) {
40
- if (children == null) return null;
41
-
42
- if (scroll === 'content') {
43
- return (
44
- <ScrollView
45
- contentContainerStyle={styles.scrollContent}
46
- keyboardShouldPersistTaps="handled"
47
- showsVerticalScrollIndicator
48
- style={styles.scrollBody}
49
- >
50
- {children}
51
- </ScrollView>
52
- );
53
- }
54
-
55
- return children;
56
- }
57
-
58
- function ResponsivePanelInner({
59
- themeId: _themeId,
60
- mode: _mode,
61
- title,
62
- description,
63
- actions,
64
- footer,
65
- children,
66
- open,
67
- onOpenChange,
68
- side = 'right',
69
- desktopMode = 'inline',
70
- mobileMode = 'drawer',
71
- compact = true,
72
- size,
73
- scroll = 'none',
74
- testID,
75
- interactionPolicy,
76
- }: ResponsivePanelProps) {
77
- if (!open) return null;
78
-
79
- const passive = interactionPolicy === 'passive';
80
- const body = renderPanelBody(children, scroll);
81
-
82
- // For now, we assume desktopMode determines the rendering.
83
- // In a real app, this would react to window size.
84
- if (desktopMode === 'floating') {
85
- if (mobileMode === 'modal') {
86
- const modalWidth = resolveModalWidth(size);
87
-
88
- return (
89
- <Modal
90
- description={description}
91
- footer={footer}
92
- interactionPolicy={interactionPolicy}
93
- onDismiss={() => {
94
- if (passive) return;
95
-
96
- onOpenChange(false);
97
- }}
98
- testID={testID}
99
- title={title}
100
- visible={open}
101
- width={modalWidth}
102
- >
103
- {body}
104
- </Modal>
105
- );
106
- }
107
-
108
- return (
109
- <Drawer
110
- description={description}
111
- footer={footer}
112
- interactionPolicy={interactionPolicy}
113
- onDismiss={() => {
114
- if (passive) return;
115
-
116
- onOpenChange(false);
117
- }}
118
- position={side}
119
- testID={testID}
120
- title={title}
121
- visible={open}
122
- >
123
- {body}
124
- </Drawer>
125
- );
126
- }
127
-
128
- const panel = (
129
- <Panel
130
- actions={actions}
131
- compact={compact}
132
- description={description}
133
- footer={footer}
134
- interactionPolicy={interactionPolicy}
135
- testID={testID}
136
- title={title}
137
- >
138
- {body}
139
- </Panel>
140
- );
141
-
142
- if (size === undefined) return panel;
143
-
144
- return <View style={[styles.inlineSizedPanel, { width: resolvePanelWidth(size) }]}>{panel}</View>;
145
- }
146
-
147
- const styles = StyleSheet.create({
148
- inlineSizedPanel: {
149
- maxWidth: '100%',
150
- },
151
- scrollBody: {
152
- flexGrow: 0,
153
- maxHeight: '100%',
154
- },
155
- scrollContent: {
156
- flexGrow: 1,
157
- },
158
- });
159
-
160
- /***
161
- * Adaptive secondary surface that can render as an inline panel, drawer, or modal.
162
- *
163
- * Use `ResponsivePanel` for tool panes and admin/detail flows that need the same
164
- * content to work across compact mobile screens and wider desktop layouts.
165
- *
166
-
167
- * @example Scrollable wide panel
168
- * ```tsx
169
- * <ResponsivePanel open title="APIs" size="wide" scroll="content">...</ResponsivePanel>
170
- * ```
171
- */
172
- export const ResponsivePanel = withZoraThemeScope(ResponsivePanelInner);
@@ -1,2 +0,0 @@
1
- export * from './ResponsivePanel';
2
- export * from './types';
@@ -1,10 +0,0 @@
1
- import type { ZoraComponentMeta } from '../../metadata';
2
-
3
- export const responsivePanelMeta = {
4
- name: 'ResponsivePanel',
5
- category: 'pattern',
6
- directManifestNode: false,
7
- allowedChildren: [],
8
- note: 'Responsive panel pattern; not represented as a manifest node in v1.',
9
- props: {},
10
- } as const satisfies ZoraComponentMeta;
@@ -1,25 +0,0 @@
1
- import type React from 'react';
2
-
3
- import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
4
-
5
- export type ResponsivePanelSide = 'left' | 'right';
6
- export type ResponsivePanelDesktopMode = 'inline' | 'floating';
7
- export type ResponsivePanelMobileMode = 'drawer' | 'modal';
8
- export type ResponsivePanelSize = 'compact' | 'default' | 'wide' | 'extraWide';
9
- export type ResponsivePanelScroll = 'none' | 'content';
10
-
11
- export interface ResponsivePanelProps extends ZoraBaseProps {
12
- title?: React.ReactNode;
13
- description?: React.ReactNode;
14
- actions?: React.ReactNode;
15
- footer?: React.ReactNode;
16
- children?: React.ReactNode;
17
- open: boolean;
18
- onOpenChange: (open: boolean) => void;
19
- side?: ResponsivePanelSide;
20
- desktopMode?: ResponsivePanelDesktopMode;
21
- mobileMode?: ResponsivePanelMobileMode;
22
- compact?: boolean;
23
- size?: ResponsivePanelSize;
24
- scroll?: ResponsivePanelScroll;
25
- }
@@ -1,60 +0,0 @@
1
- import { DrawerNavigation as SurfaceDrawerNavigation } from '@ankhorage/surface';
2
- import React from 'react';
3
-
4
- import {
5
- createDrawerItemPressHandler,
6
- resolveNavigationItems,
7
- } from '../../internal/resolveZoraNavigationItems';
8
- import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
9
- import type { ZoraDrawerContentProps } from './types';
10
-
11
- function ZoraDrawerContentInner({
12
- themeId: _themeId,
13
- mode: _mode,
14
- interactionPolicy,
15
- state,
16
- navigation,
17
- descriptors,
18
- routeMap,
19
- compact = false,
20
- header,
21
- footer,
22
- testID,
23
- }: ZoraDrawerContentProps) {
24
- const resolved = resolveNavigationItems({
25
- state,
26
- descriptors,
27
- routeMap,
28
- kind: 'drawer',
29
- });
30
-
31
- const items = resolved.map((item) => ({
32
- id: item.route.key,
33
- label: item.label,
34
- icon: item.metadata?.icon,
35
- badge: item.metadata?.badge,
36
- active: item.active,
37
- disabled: item.disabled,
38
- onPress: createDrawerItemPressHandler({ item, navigation }),
39
- accessibilityLabel: item.metadata?.accessibilityLabel,
40
- testID: item.metadata?.testID,
41
- }));
42
-
43
- return (
44
- <SurfaceDrawerNavigation
45
- compact={compact}
46
- footer={footer}
47
- header={header}
48
- interactionPolicy={interactionPolicy}
49
- items={items}
50
- testID={testID}
51
- />
52
- );
53
- }
54
-
55
- /***
56
- * Standard drawer content pattern for ZORA navigation lists.
57
- *
58
-
59
- */
60
- export const ZoraDrawerContent = withZoraThemeScope(ZoraDrawerContentInner);
@@ -1,2 +0,0 @@
1
- export type { ZoraDrawerContentProps } from './types';
2
- export { ZoraDrawerContent } from './ZoraDrawerContent';
@@ -1,10 +0,0 @@
1
- import type { ZoraComponentMeta } from '../../metadata';
2
-
3
- export const zoraDrawerContentMeta = {
4
- name: 'ZoraDrawerContent',
5
- category: 'pattern',
6
- directManifestNode: false,
7
- allowedChildren: [],
8
- note: 'Navigation chrome pattern; not represented as a manifest node in v1.',
9
- props: {},
10
- } as const satisfies ZoraComponentMeta;
@@ -1,20 +0,0 @@
1
- import type React from 'react';
2
-
3
- import type { ZoraNavigationRouteMap } from '../../components/navigation-list';
4
- import type {
5
- ZoraDrawerNavigation,
6
- ZoraNavigationDescriptors,
7
- ZoraNavigationState,
8
- } from '../../internal/resolveZoraNavigationItems';
9
- import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
10
-
11
- export interface ZoraDrawerContentProps extends ZoraBaseProps {
12
- state: ZoraNavigationState;
13
- navigation: ZoraDrawerNavigation;
14
- descriptors?: ZoraNavigationDescriptors | undefined;
15
- routeMap?: ZoraNavigationRouteMap | undefined;
16
- compact?: boolean;
17
- header?: React.ReactNode;
18
- footer?: React.ReactNode;
19
- testID?: string;
20
- }