@teardown/cli 2.0.66 → 2.0.67

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 (37) hide show
  1. package/package.json +2 -2
  2. package/templates/metro.config.js +7 -35
  3. package/templates/src/components/ui/accordion.tsx +23 -21
  4. package/templates/src/components/ui/card.tsx +28 -26
  5. package/templates/src/components/ui/checkbox.tsx +12 -10
  6. package/templates/src/components/ui/dialog.tsx +30 -28
  7. package/templates/src/components/ui/divider.tsx +6 -6
  8. package/templates/src/components/ui/form-field.tsx +2 -2
  9. package/templates/src/components/ui/pressable-feedback.tsx +2 -2
  10. package/templates/src/components/ui/radio-group.tsx +37 -35
  11. package/templates/src/components/ui/scroll-shadow.tsx +4 -4
  12. package/templates/src/components/ui/select.tsx +31 -29
  13. package/templates/src/components/ui/skeleton-group.tsx +2 -2
  14. package/templates/src/components/ui/skeleton.tsx +2 -2
  15. package/templates/src/components/ui/spinner.tsx +2 -2
  16. package/templates/src/components/ui/tabs.tsx +25 -23
  17. package/templates/src/global.css +86 -70
  18. package/templates/src/navigation/navigation-provider.tsx +8 -1
  19. package/templates/src/navigation/router.tsx +12 -95
  20. package/templates/src/providers/app.provider.tsx +8 -12
  21. package/templates/src/routes/_layout.tsx +2 -4
  22. package/templates/src/routes/home.tsx +112 -0
  23. package/templates/tsconfig.json +10 -12
  24. package/templates/src/components/ui/index.ts +0 -100
  25. package/templates/src/routes/(tabs)/_layout.tsx +0 -42
  26. package/templates/src/routes/(tabs)/explore.tsx +0 -161
  27. package/templates/src/routes/(tabs)/home.tsx +0 -138
  28. package/templates/src/routes/(tabs)/profile.tsx +0 -114
  29. package/templates/src/routes/settings.tsx +0 -184
  30. package/templates/src/screens/auth/index.ts +0 -6
  31. package/templates/src/screens/auth/login.tsx +0 -165
  32. package/templates/src/screens/auth/register.tsx +0 -203
  33. package/templates/src/screens/home.tsx +0 -204
  34. package/templates/src/screens/index.ts +0 -17
  35. package/templates/src/screens/profile.tsx +0 -210
  36. package/templates/src/screens/settings.tsx +0 -216
  37. package/templates/src/screens/welcome.tsx +0 -101
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teardown/cli",
3
- "version": "2.0.66",
3
+ "version": "2.0.67",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -71,7 +71,7 @@
71
71
  },
72
72
  "devDependencies": {
73
73
  "@biomejs/biome": "2.3.11",
74
- "@teardown/tsconfig": "2.0.66",
74
+ "@teardown/tsconfig": "2.0.67",
75
75
  "@types/bun": "1.3.5",
76
76
  "@types/ejs": "^3.1.5",
77
77
  "typescript": "5.9.3"
@@ -11,59 +11,31 @@ const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
11
11
  * - Monorepo/workspace detection and watch folder configuration
12
12
  * - Bun-specific handling (.bun directory blocking)
13
13
  *
14
- * withUniwindConfig() enables:
15
- * - Tailwind CSS 4 support for React Native
16
- * - Automatic className scanning and compilation
17
- * - Hot reloading for style changes
18
14
  *
19
15
  * withTeardownNavigation() automatically handles:
20
16
  * - Type-safe route generation from file-based routes
21
17
  * - Deep linking configuration generation
22
18
  * - Hot-reload support via file watching in development
23
19
  *
20
+ *
21
+ * withUniwindConfig() enables:
22
+ * - Tailwind CSS 4 support for React Native
23
+ * - Automatic className scanning and compilation
24
+ * - Hot reloading for style changes
25
+ *
24
26
  * @type {import("metro-config").MetroConfig}
25
27
  */
26
28
  const config = {};
27
29
 
28
- // First apply Teardown config, then Navigation
29
30
  const teardownConfig = withTeardown(mergeConfig(getDefaultConfig(__dirname), config));
30
31
 
31
32
  const navigationConfig = withTeardownNavigation(teardownConfig, {
32
33
  routesDir: "./src/routes",
33
34
  generatedDir: "./.teardown",
34
- prefixes: ["<%= slug %>://"],
35
35
  verbose: false,
36
36
  });
37
37
 
38
- /**
39
- * Wrap resolvers with null-handling before Uniwind.
40
- * Uniwind doesn't handle null returns from resolvers, so we ensure
41
- * any null returns are converted to Metro's default resolution.
42
- */
43
- const withNullSafeResolver = (inputConfig) => {
44
- const existingResolver = inputConfig.resolver?.resolveRequest;
45
- if (!existingResolver) return inputConfig;
46
-
47
- return {
48
- ...inputConfig,
49
- resolver: {
50
- ...inputConfig.resolver,
51
- resolveRequest: (context, moduleName, platform) => {
52
- const result = existingResolver(context, moduleName, platform);
53
- // If resolver returns null, use Metro's internal resolver
54
- if (result === null) {
55
- return context.resolveRequest(context, moduleName, platform);
56
- }
57
- return result;
58
- },
59
- },
60
- };
61
- };
62
-
63
- // Apply null-safe wrapper before Uniwind (which expects non-null results)
64
- const safeConfig = withNullSafeResolver(navigationConfig);
65
-
66
- module.exports = withUniwindConfig(safeConfig, {
38
+ module.exports = withUniwindConfig(navigationConfig, {
67
39
  cssEntryFile: "./src/global.css",
68
40
  dtsFile: "./src/uniwind-types.d.ts",
69
41
  });
@@ -6,25 +6,25 @@
6
6
  * @example Basic Usage
7
7
  * ```tsx
8
8
  * <Accordion>
9
- * <AccordionItem key="1" title="Section 1">
9
+ * <Accordion.Item key="1" title="Section 1">
10
10
  * <Text>Content for section 1</Text>
11
- * </AccordionItem>
12
- * <AccordionItem key="2" title="Section 2">
11
+ * </Accordion.Item>
12
+ * <Accordion.Item key="2" title="Section 2">
13
13
  * <Text>Content for section 2</Text>
14
- * </AccordionItem>
14
+ * </Accordion.Item>
15
15
  * </Accordion>
16
16
  * ```
17
17
  *
18
18
  * @example With Subtitle
19
19
  * ```tsx
20
20
  * <Accordion>
21
- * <AccordionItem
21
+ * <Accordion.Item
22
22
  * key="1"
23
23
  * title="Account Settings"
24
24
  * subtitle="Manage your account preferences"
25
25
  * >
26
26
  * <Text>Account settings content</Text>
27
- * </AccordionItem>
27
+ * </Accordion.Item>
28
28
  * </Accordion>
29
29
  * ```
30
30
  *
@@ -32,14 +32,14 @@
32
32
  * ```tsx
33
33
  * // Single selection (default)
34
34
  * <Accordion selectionMode="single">
35
- * <AccordionItem key="1" title="Item 1">Content 1</AccordionItem>
36
- * <AccordionItem key="2" title="Item 2">Content 2</AccordionItem>
35
+ * <Accordion.Item key="1" title="Item 1">Content 1</Accordion.Item>
36
+ * <Accordion.Item key="2" title="Item 2">Content 2</Accordion.Item>
37
37
  * </Accordion>
38
38
  *
39
39
  * // Multiple selection
40
40
  * <Accordion selectionMode="multiple">
41
- * <AccordionItem key="1" title="Item 1">Content 1</AccordionItem>
42
- * <AccordionItem key="2" title="Item 2">Content 2</AccordionItem>
41
+ * <Accordion.Item key="1" title="Item 1">Content 1</Accordion.Item>
42
+ * <Accordion.Item key="2" title="Item 2">Content 2</Accordion.Item>
43
43
  * </Accordion>
44
44
  * ```
45
45
  *
@@ -51,17 +51,17 @@
51
51
  * selectedKeys={selectedKeys}
52
52
  * onSelectionChange={setSelectedKeys}
53
53
  * >
54
- * <AccordionItem key="1" title="Item 1">Content 1</AccordionItem>
55
- * <AccordionItem key="2" title="Item 2">Content 2</AccordionItem>
54
+ * <Accordion.Item key="1" title="Item 1">Content 1</Accordion.Item>
55
+ * <Accordion.Item key="2" title="Item 2">Content 2</Accordion.Item>
56
56
  * </Accordion>
57
57
  * ```
58
58
  *
59
59
  * @example Default Expanded
60
60
  * ```tsx
61
61
  * <Accordion defaultExpandedKeys={['1']}>
62
- * <AccordionItem key="1" title="Expanded by default">
62
+ * <Accordion.Item key="1" title="Expanded by default">
63
63
  * This section is expanded initially
64
- * </AccordionItem>
64
+ * </Accordion.Item>
65
65
  * </Accordion>
66
66
  * ```
67
67
  *
@@ -76,10 +76,10 @@
76
76
  * @example Disabled Item
77
77
  * ```tsx
78
78
  * <Accordion>
79
- * <AccordionItem key="1" title="Normal Item">Content</AccordionItem>
80
- * <AccordionItem key="2" title="Disabled Item" isDisabled>
79
+ * <Accordion.Item key="1" title="Normal Item">Content</Accordion.Item>
80
+ * <Accordion.Item key="2" title="Disabled Item" isDisabled>
81
81
  * This item is disabled
82
- * </AccordionItem>
82
+ * </Accordion.Item>
83
83
  * </Accordion>
84
84
  * ```
85
85
  */
@@ -99,13 +99,15 @@ const AccordionRoot = forwardRef<ViewRef, HeroAccordionProps>((props, ref) => {
99
99
  AccordionRoot.displayName = "Accordion";
100
100
 
101
101
  // Accordion Item component
102
- const AccordionItemComponent = forwardRef<ViewRef, HeroAccordionItemProps>((props, ref) => {
102
+ const AccordionItem = forwardRef<ViewRef, HeroAccordionItemProps>((props, ref) => {
103
103
  return <HeroAccordionItem ref={ref} {...props} />;
104
104
  });
105
- AccordionItemComponent.displayName = "AccordionItem";
105
+ AccordionItem.displayName = "Accordion.Item";
106
106
 
107
- export const Accordion = AccordionRoot;
108
- export const AccordionItem = AccordionItemComponent;
107
+ // Compound Accordion component with Object.assign pattern
108
+ export const Accordion = Object.assign(AccordionRoot, {
109
+ Item: AccordionItem,
110
+ });
109
111
 
110
112
  // Re-export types for convenience
111
113
  export type {
@@ -6,36 +6,36 @@
6
6
  * @example Basic Usage
7
7
  * ```tsx
8
8
  * <Card>
9
- * <CardBody>
9
+ * <Card.Body>
10
10
  * <Text>Card content goes here</Text>
11
- * </CardBody>
11
+ * </Card.Body>
12
12
  * </Card>
13
13
  * ```
14
14
  *
15
15
  * @example With Header
16
16
  * ```tsx
17
17
  * <Card>
18
- * <CardHeader>
18
+ * <Card.Header>
19
19
  * <Text>Card Title</Text>
20
- * </CardHeader>
21
- * <CardBody>
20
+ * </Card.Header>
21
+ * <Card.Body>
22
22
  * <Text>Card content goes here</Text>
23
- * </CardBody>
23
+ * </Card.Body>
24
24
  * </Card>
25
25
  * ```
26
26
  *
27
27
  * @example Full Card Structure
28
28
  * ```tsx
29
29
  * <Card>
30
- * <CardHeader>
30
+ * <Card.Header>
31
31
  * <Text>Card Title</Text>
32
- * </CardHeader>
33
- * <CardBody>
32
+ * </Card.Header>
33
+ * <Card.Body>
34
34
  * <Text>Main content area</Text>
35
- * </CardBody>
36
- * <CardFooter>
35
+ * </Card.Body>
36
+ * <Card.Footer>
37
37
  * <Button>Action</Button>
38
- * </CardFooter>
38
+ * </Card.Footer>
39
39
  * </Card>
40
40
  * ```
41
41
  *
@@ -51,18 +51,18 @@
51
51
  * @example Pressable Card
52
52
  * ```tsx
53
53
  * <Card isPressable onPress={() => console.log('Card pressed!')}>
54
- * <CardBody>
54
+ * <Card.Body>
55
55
  * <Text>Pressable Card</Text>
56
- * </CardBody>
56
+ * </Card.Body>
57
57
  * </Card>
58
58
  * ```
59
59
  *
60
60
  * @example Disabled Card
61
61
  * ```tsx
62
62
  * <Card isDisabled>
63
- * <CardBody>
63
+ * <Card.Body>
64
64
  * <Text>Disabled Card</Text>
65
- * </CardBody>
65
+ * </Card.Body>
66
66
  * </Card>
67
67
  * ```
68
68
  */
@@ -89,27 +89,29 @@ const CardRoot = forwardRef<ViewRef, HeroCardProps>((props, ref) => {
89
89
  CardRoot.displayName = "Card";
90
90
 
91
91
  // Card Header component
92
- const CardHeaderComponent = forwardRef<ViewRef, HeroCardHeaderProps>((props, ref) => {
92
+ const CardHeader = forwardRef<ViewRef, HeroCardHeaderProps>((props, ref) => {
93
93
  return <HeroCardHeader ref={ref} {...props} />;
94
94
  });
95
- CardHeaderComponent.displayName = "CardHeader";
95
+ CardHeader.displayName = "Card.Header";
96
96
 
97
97
  // Card Body component
98
- const CardBodyComponent = forwardRef<ViewRef, HeroCardBodyProps>((props, ref) => {
98
+ const CardBody = forwardRef<ViewRef, HeroCardBodyProps>((props, ref) => {
99
99
  return <HeroCardBody ref={ref} {...props} />;
100
100
  });
101
- CardBodyComponent.displayName = "CardBody";
101
+ CardBody.displayName = "Card.Body";
102
102
 
103
103
  // Card Footer component
104
- const CardFooterComponent = forwardRef<ViewRef, HeroCardFooterProps>((props, ref) => {
104
+ const CardFooter = forwardRef<ViewRef, HeroCardFooterProps>((props, ref) => {
105
105
  return <HeroCardFooter ref={ref} {...props} />;
106
106
  });
107
- CardFooterComponent.displayName = "CardFooter";
107
+ CardFooter.displayName = "Card.Footer";
108
108
 
109
- export const Card = CardRoot;
110
- export const CardHeader = CardHeaderComponent;
111
- export const CardBody = CardBodyComponent;
112
- export const CardFooter = CardFooterComponent;
109
+ // Compound Card component with Object.assign pattern
110
+ export const Card = Object.assign(CardRoot, {
111
+ Header: CardHeader,
112
+ Body: CardBody,
113
+ Footer: CardFooter,
114
+ });
113
115
 
114
116
  // Re-export types for convenience
115
117
  export type {
@@ -67,39 +67,39 @@
67
67
  *
68
68
  * @example Checkbox Group
69
69
  * ```tsx
70
- * <CheckboxGroup
70
+ * <Checkbox.Group
71
71
  * label="Select your hobbies"
72
72
  * defaultValue={['reading']}
73
73
  * >
74
74
  * <Checkbox value="reading">Reading</Checkbox>
75
75
  * <Checkbox value="gaming">Gaming</Checkbox>
76
76
  * <Checkbox value="music">Music</Checkbox>
77
- * </CheckboxGroup>
77
+ * </Checkbox.Group>
78
78
  * ```
79
79
  *
80
80
  * @example Controlled Group
81
81
  * ```tsx
82
82
  * const [selected, setSelected] = useState(['reading']);
83
83
  *
84
- * <CheckboxGroup
84
+ * <Checkbox.Group
85
85
  * label="Interests"
86
86
  * value={selected}
87
87
  * onValueChange={setSelected}
88
88
  * >
89
89
  * <Checkbox value="sports">Sports</Checkbox>
90
90
  * <Checkbox value="travel">Travel</Checkbox>
91
- * </CheckboxGroup>
91
+ * </Checkbox.Group>
92
92
  * ```
93
93
  *
94
94
  * @example Horizontal Group
95
95
  * ```tsx
96
- * <CheckboxGroup
96
+ * <Checkbox.Group
97
97
  * label="Options"
98
98
  * orientation="horizontal"
99
99
  * >
100
100
  * <Checkbox value="a">Option A</Checkbox>
101
101
  * <Checkbox value="b">Option B</Checkbox>
102
- * </CheckboxGroup>
102
+ * </Checkbox.Group>
103
103
  * ```
104
104
  */
105
105
 
@@ -118,13 +118,15 @@ const CheckboxRoot = forwardRef<ViewRef, HeroCheckboxProps>((props, ref) => {
118
118
  CheckboxRoot.displayName = "Checkbox";
119
119
 
120
120
  // Checkbox Group component
121
- const CheckboxGroupComponent = forwardRef<ViewRef, HeroCheckboxGroupProps>((props, ref) => {
121
+ const CheckboxGroup = forwardRef<ViewRef, HeroCheckboxGroupProps>((props, ref) => {
122
122
  return <HeroCheckboxGroup ref={ref} {...props} />;
123
123
  });
124
- CheckboxGroupComponent.displayName = "CheckboxGroup";
124
+ CheckboxGroup.displayName = "Checkbox.Group";
125
125
 
126
- export const Checkbox = CheckboxRoot;
127
- export const CheckboxGroup = CheckboxGroupComponent;
126
+ // Compound Checkbox component with Object.assign pattern
127
+ export const Checkbox = Object.assign(CheckboxRoot, {
128
+ Group: CheckboxGroup,
129
+ });
128
130
 
129
131
  // Re-export types for convenience
130
132
  export type {
@@ -10,31 +10,31 @@
10
10
  * <Button onPress={() => setOpen(true)}>Open Dialog</Button>
11
11
  *
12
12
  * <Dialog isOpen={isOpen} onClose={() => setOpen(false)}>
13
- * <DialogHeader>
13
+ * <Dialog.Header>
14
14
  * <Text>Dialog Title</Text>
15
- * </DialogHeader>
16
- * <DialogBody>
15
+ * </Dialog.Header>
16
+ * <Dialog.Body>
17
17
  * <Text>Dialog content goes here</Text>
18
- * </DialogBody>
19
- * <DialogFooter>
18
+ * </Dialog.Body>
19
+ * <Dialog.Footer>
20
20
  * <Button onPress={() => setOpen(false)}>Close</Button>
21
- * </DialogFooter>
21
+ * </Dialog.Footer>
22
22
  * </Dialog>
23
23
  * ```
24
24
  *
25
25
  * @example Simple Alert
26
26
  * ```tsx
27
27
  * <Dialog isOpen={isOpen} onClose={handleClose}>
28
- * <DialogHeader>
28
+ * <Dialog.Header>
29
29
  * <Text>Alert</Text>
30
- * </DialogHeader>
31
- * <DialogBody>
30
+ * </Dialog.Header>
31
+ * <Dialog.Body>
32
32
  * <Text>Are you sure you want to proceed?</Text>
33
- * </DialogBody>
34
- * <DialogFooter>
33
+ * </Dialog.Body>
34
+ * <Dialog.Footer>
35
35
  * <Button variant="light" onPress={handleClose}>Cancel</Button>
36
36
  * <Button color="primary" onPress={handleConfirm}>Confirm</Button>
37
- * </DialogFooter>
37
+ * </Dialog.Footer>
38
38
  * </Dialog>
39
39
  * ```
40
40
  *
@@ -62,21 +62,21 @@
62
62
  * onClose={handleClose}
63
63
  * isDismissable={false}
64
64
  * >
65
- * <DialogBody>
65
+ * <Dialog.Body>
66
66
  * <Text>Click outside won't close this dialog</Text>
67
- * </DialogBody>
67
+ * </Dialog.Body>
68
68
  * </Dialog>
69
69
  * ```
70
70
  *
71
71
  * @example Scrollable Body
72
72
  * ```tsx
73
73
  * <Dialog scrollBehavior="inside">
74
- * <DialogHeader>
74
+ * <Dialog.Header>
75
75
  * <Text>Long Content</Text>
76
- * </DialogHeader>
77
- * <DialogBody>
76
+ * </Dialog.Header>
77
+ * <Dialog.Body>
78
78
  * <Text>Long content that scrolls...</Text>
79
- * </DialogBody>
79
+ * </Dialog.Body>
80
80
  * </Dialog>
81
81
  * ```
82
82
  */
@@ -103,27 +103,29 @@ const DialogRoot = forwardRef<ViewRef, HeroDialogProps>((props, ref) => {
103
103
  DialogRoot.displayName = "Dialog";
104
104
 
105
105
  // Dialog Header component
106
- const DialogHeaderComponent = forwardRef<ViewRef, HeroDialogHeaderProps>((props, ref) => {
106
+ const DialogHeader = forwardRef<ViewRef, HeroDialogHeaderProps>((props, ref) => {
107
107
  return <HeroDialogHeader ref={ref} {...props} />;
108
108
  });
109
- DialogHeaderComponent.displayName = "DialogHeader";
109
+ DialogHeader.displayName = "Dialog.Header";
110
110
 
111
111
  // Dialog Body component
112
- const DialogBodyComponent = forwardRef<ViewRef, HeroDialogBodyProps>((props, ref) => {
112
+ const DialogBody = forwardRef<ViewRef, HeroDialogBodyProps>((props, ref) => {
113
113
  return <HeroDialogBody ref={ref} {...props} />;
114
114
  });
115
- DialogBodyComponent.displayName = "DialogBody";
115
+ DialogBody.displayName = "Dialog.Body";
116
116
 
117
117
  // Dialog Footer component
118
- const DialogFooterComponent = forwardRef<ViewRef, HeroDialogFooterProps>((props, ref) => {
118
+ const DialogFooter = forwardRef<ViewRef, HeroDialogFooterProps>((props, ref) => {
119
119
  return <HeroDialogFooter ref={ref} {...props} />;
120
120
  });
121
- DialogFooterComponent.displayName = "DialogFooter";
121
+ DialogFooter.displayName = "Dialog.Footer";
122
122
 
123
- export const Dialog = DialogRoot;
124
- export const DialogHeader = DialogHeaderComponent;
125
- export const DialogBody = DialogBodyComponent;
126
- export const DialogFooter = DialogFooterComponent;
123
+ // Compound Dialog component with Object.assign pattern
124
+ export const Dialog = Object.assign(DialogRoot, {
125
+ Header: DialogHeader,
126
+ Body: DialogBody,
127
+ Footer: DialogFooter,
128
+ });
127
129
 
128
130
  // Re-export types for convenience
129
131
  export type {
@@ -26,17 +26,17 @@
26
26
  * @example In a Card
27
27
  * ```tsx
28
28
  * <Card>
29
- * <CardHeader>
29
+ * <Card.Header>
30
30
  * <Text>Title</Text>
31
- * </CardHeader>
31
+ * </Card.Header>
32
32
  * <Divider />
33
- * <CardBody>
33
+ * <Card.Body>
34
34
  * <Text>Content</Text>
35
- * </CardBody>
35
+ * </Card.Body>
36
36
  * <Divider />
37
- * <CardFooter>
37
+ * <Card.Footer>
38
38
  * <Button>Action</Button>
39
- * </CardFooter>
39
+ * </Card.Footer>
40
40
  * </Card>
41
41
  * ```
42
42
  *
@@ -57,10 +57,10 @@
57
57
  * label="Preferences"
58
58
  * description="Select all that apply"
59
59
  * >
60
- * <CheckboxGroup>
60
+ * <Checkbox.Group>
61
61
  * <Checkbox value="notifications">Email notifications</Checkbox>
62
62
  * <Checkbox value="updates">Product updates</Checkbox>
63
- * </CheckboxGroup>
63
+ * </Checkbox.Group>
64
64
  * </FormField>
65
65
  * ```
66
66
  *
@@ -17,9 +17,9 @@
17
17
  * pressedOpacity={0.7}
18
18
  * >
19
19
  * <Card>
20
- * <CardBody>
20
+ * <Card.Body>
21
21
  * <Text>Pressable Card</Text>
22
- * </CardBody>
22
+ * </Card.Body>
23
23
  * </Card>
24
24
  * </PressableFeedback>
25
25
  * ```