newcandies 0.1.55 → 0.1.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/mini-boilerplate/fiesta-widgets-mini/app-env.js +58 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/app-env.ts +18 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/app.config.ts +52 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/assets/adaptive-icon.png +0 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/assets/favicon.png +0 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/assets/fiesta-transparent.png +0 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/assets/fiesta.png +0 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/assets/icon.png +0 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/assets/images/empty-categories.png +0 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/assets/images/empty-subscriptions.png +0 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/assets/images/empty-upcoming-payments.png +0 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/assets/images/onboarding-hero.png +0 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/babel.config.js +7 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/eas.json +21 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/eslint.config.mjs +111 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/global.css +60 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/metro.config.js +10 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/package.json +87 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/skia-stub.d.ts +3 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/app/(tabs)/_layout.tsx +40 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/app/(tabs)/index.tsx +28 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/app/(tabs)/widgets.tsx +13 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/app/+not-found.tsx +16 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/app/_layout.tsx +47 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/app/event/[id].tsx +177 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/buttons/back-button.tsx +44 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/buttons/button.tsx +175 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/buttons/icon-button.tsx +33 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/buttons/pressable.tsx +6 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/inputs/input.tsx +43 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/layout/card.tsx +25 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/layout/safe-area-view.tsx +6 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/layout/screen.tsx +23 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/layout/scroll-view.tsx +6 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/layout/squircle.tsx +8 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/layout/view.tsx +6 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/navigation/stack.tsx +18 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/ui/icon-symbol.tsx +131 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/ui/image.tsx +6 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/ui/loading.tsx +35 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/components/ui/text.tsx +44 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/config/theme.ts +54 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/data/fiesta-data.ts +14 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/features/home/celebration-card.tsx +84 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/features/home/today-hero.tsx +151 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/lib/celebrations.ts +167 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/lib/theme.ts +29 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/lib/utils.ts +7 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/types/index.ts +26 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/src/types/uniwind.d.ts +10 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/tsconfig.json +11 -0
- package/templates/mini-boilerplate/fiesta-widgets-mini/uniwind-types.d.ts +10 -0
- package/templates/registry.json +6 -0
package/package.json
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const process = require("node:process");
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Environment configuration for Fiesta.
|
|
5
|
+
* Supports: local | preview | production
|
|
6
|
+
*
|
|
7
|
+
* @type {'local' | 'preview' | 'production'}
|
|
8
|
+
*/
|
|
9
|
+
const APP_ENV = process.env.EXPO_PUBLIC_APP_ENV ?? "local";
|
|
10
|
+
|
|
11
|
+
const { version } = require("./package.json");
|
|
12
|
+
|
|
13
|
+
// Bundle IDs per environment
|
|
14
|
+
const BUNDLE_IDS = {
|
|
15
|
+
local: "com.fiesta.app.local",
|
|
16
|
+
preview: "com.fiesta.app.preview",
|
|
17
|
+
production: "com.fiesta.app",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Android package names per environment
|
|
21
|
+
const PACKAGES = {
|
|
22
|
+
local: "com.fiesta.app.local",
|
|
23
|
+
preview: "com.fiesta.app.preview",
|
|
24
|
+
production: "com.fiesta.app",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// URL schemes per environment
|
|
28
|
+
const SCHEMES = {
|
|
29
|
+
local: "fiesta.local",
|
|
30
|
+
preview: "fiesta.preview",
|
|
31
|
+
production: "fiesta",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// App names per environment
|
|
35
|
+
const NAMES = {
|
|
36
|
+
local: "Fiesta (Local)",
|
|
37
|
+
preview: "Fiesta (Preview)",
|
|
38
|
+
production: "Fiesta",
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Shared app group IDs for widget storage
|
|
42
|
+
const APP_GROUPS = {
|
|
43
|
+
local: "group.com.fiesta.app.local",
|
|
44
|
+
preview: "group.com.fiesta.app.preview",
|
|
45
|
+
production: "group.com.fiesta.app",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const Env = {
|
|
49
|
+
APP_ENV,
|
|
50
|
+
NAME: NAMES[APP_ENV],
|
|
51
|
+
SCHEME: SCHEMES[APP_ENV],
|
|
52
|
+
BUNDLE_ID: BUNDLE_IDS[APP_ENV],
|
|
53
|
+
PACKAGE: PACKAGES[APP_ENV],
|
|
54
|
+
VERSION: version,
|
|
55
|
+
APP_GROUP: APP_GROUPS[APP_ENV],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
module.exports = Env;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe re-export of app-env.js for use in src/ code.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type AppEnv = "local" | "preview" | "production";
|
|
6
|
+
|
|
7
|
+
interface EnvConfig {
|
|
8
|
+
APP_ENV: AppEnv;
|
|
9
|
+
NAME: string;
|
|
10
|
+
SCHEME: string;
|
|
11
|
+
BUNDLE_ID: string;
|
|
12
|
+
PACKAGE: string;
|
|
13
|
+
APP_GROUP: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const Env = require("./app-env.js") as EnvConfig;
|
|
17
|
+
|
|
18
|
+
export default Env;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ConfigContext, ExpoConfig } from "expo/config";
|
|
2
|
+
|
|
3
|
+
const Env = require("./app-env.js");
|
|
4
|
+
|
|
5
|
+
export default ({ config }: ConfigContext): ExpoConfig => ({
|
|
6
|
+
...config,
|
|
7
|
+
name: Env.NAME,
|
|
8
|
+
slug: "fiesta",
|
|
9
|
+
version: Env.VERSION,
|
|
10
|
+
orientation: "portrait",
|
|
11
|
+
icon: "./assets/icon.png",
|
|
12
|
+
scheme: Env.SCHEME,
|
|
13
|
+
userInterfaceStyle: "automatic",
|
|
14
|
+
ios: {
|
|
15
|
+
supportsTablet: true,
|
|
16
|
+
bundleIdentifier: Env.BUNDLE_ID,
|
|
17
|
+
infoPlist: {
|
|
18
|
+
NSAppTransportSecurity: {
|
|
19
|
+
NSAllowsArbitraryLoads: true,
|
|
20
|
+
NSAllowsLocalNetworking: true,
|
|
21
|
+
},
|
|
22
|
+
ITSAppUsesNonExemptEncryption: false,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
android: {
|
|
26
|
+
adaptiveIcon: {
|
|
27
|
+
foregroundImage: "./assets/adaptive-icon.png",
|
|
28
|
+
backgroundColor: "#ffffff",
|
|
29
|
+
},
|
|
30
|
+
package: Env.PACKAGE,
|
|
31
|
+
},
|
|
32
|
+
web: {
|
|
33
|
+
bundler: "metro",
|
|
34
|
+
output: "static",
|
|
35
|
+
favicon: "./assets/favicon.png",
|
|
36
|
+
},
|
|
37
|
+
plugins: [
|
|
38
|
+
"expo-router",
|
|
39
|
+
"expo-image",
|
|
40
|
+
"expo-font",
|
|
41
|
+
],
|
|
42
|
+
experiments: {
|
|
43
|
+
typedRoutes: true,
|
|
44
|
+
},
|
|
45
|
+
extra: {
|
|
46
|
+
APP_ENV: Env.APP_ENV,
|
|
47
|
+
router: {},
|
|
48
|
+
eas: {
|
|
49
|
+
projectId: "your-project-id-here",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/templates/mini-boilerplate/fiesta-widgets-mini/assets/images/empty-upcoming-payments.png
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cli": {
|
|
3
|
+
"version": ">= 7.0.0"
|
|
4
|
+
},
|
|
5
|
+
"build": {
|
|
6
|
+
"development": {
|
|
7
|
+
"android": {
|
|
8
|
+
"buildType": "apk"
|
|
9
|
+
},
|
|
10
|
+
"developmentClient": true,
|
|
11
|
+
"distribution": "internal"
|
|
12
|
+
},
|
|
13
|
+
"preview": {
|
|
14
|
+
"distribution": "internal"
|
|
15
|
+
},
|
|
16
|
+
"production": {}
|
|
17
|
+
},
|
|
18
|
+
"submit": {
|
|
19
|
+
"production": {}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import antfu from "@antfu/eslint-config";
|
|
2
|
+
import reactCompiler from "eslint-plugin-react-compiler";
|
|
3
|
+
|
|
4
|
+
export default antfu(
|
|
5
|
+
{
|
|
6
|
+
type: "app",
|
|
7
|
+
typescript: {
|
|
8
|
+
parserOptions: {
|
|
9
|
+
project: null,
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
react: true,
|
|
13
|
+
stylistic: {
|
|
14
|
+
indent: 2,
|
|
15
|
+
quotes: "double",
|
|
16
|
+
semi: true,
|
|
17
|
+
},
|
|
18
|
+
ignores: [
|
|
19
|
+
"**/node_modules/**",
|
|
20
|
+
"**/dist/**",
|
|
21
|
+
"**/build/**",
|
|
22
|
+
"**/.expo/**",
|
|
23
|
+
"**/ios/**",
|
|
24
|
+
"**/android/**",
|
|
25
|
+
"**/coverage/**",
|
|
26
|
+
"**/.maestro/**",
|
|
27
|
+
"**/*.md",
|
|
28
|
+
"**/*.d.ts",
|
|
29
|
+
"**/babel.config.js",
|
|
30
|
+
"**/metro.config.js",
|
|
31
|
+
"**/app.config.ts",
|
|
32
|
+
"**/env.ts",
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "react-compiler",
|
|
37
|
+
files: ["**/*.{ts,tsx}"],
|
|
38
|
+
plugins: {
|
|
39
|
+
"react-compiler": reactCompiler,
|
|
40
|
+
},
|
|
41
|
+
rules: {
|
|
42
|
+
"react-compiler/react-compiler": "error",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "react-rules",
|
|
47
|
+
files: ["**/*.{ts,tsx}"],
|
|
48
|
+
rules: {
|
|
49
|
+
"react/react-in-jsx-scope": "off",
|
|
50
|
+
"react/prop-types": "off",
|
|
51
|
+
"react/display-name": "off",
|
|
52
|
+
"react-hooks/rules-of-hooks": "error",
|
|
53
|
+
"react-hooks/exhaustive-deps": "warn",
|
|
54
|
+
"react-refresh/only-export-components": "off",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "disable-typed-rules",
|
|
59
|
+
files: ["**/*.{ts,tsx,js}"],
|
|
60
|
+
rules: {
|
|
61
|
+
"@typescript-eslint/no-require-imports": "off",
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "custom-rules",
|
|
66
|
+
rules: {
|
|
67
|
+
"no-console": "off",
|
|
68
|
+
"curly": ["error", "all"],
|
|
69
|
+
"style/brace-style": ["error", "1tbs", { allowSingleLine: true }],
|
|
70
|
+
"style/operator-linebreak": ["error", "after"],
|
|
71
|
+
"style/max-statements-per-line": "off",
|
|
72
|
+
"style/jsx-one-expression-per-line": "off",
|
|
73
|
+
"style/multiline-ternary": "off",
|
|
74
|
+
"style/arrow-parens": "off",
|
|
75
|
+
"antfu/if-newline": "off",
|
|
76
|
+
"prefer-const": "error",
|
|
77
|
+
"no-var": "error",
|
|
78
|
+
"eqeqeq": ["error", "always"],
|
|
79
|
+
"ts/no-explicit-any": "warn",
|
|
80
|
+
"ts/no-require-imports": "off",
|
|
81
|
+
"ts/no-use-before-define": "off",
|
|
82
|
+
"ts/consistent-type-definitions": "off",
|
|
83
|
+
"perfectionist/sort-imports": "off",
|
|
84
|
+
"perfectionist/sort-named-imports": "off",
|
|
85
|
+
"unused-imports/no-unused-vars": [
|
|
86
|
+
"warn",
|
|
87
|
+
{
|
|
88
|
+
vars: "all",
|
|
89
|
+
varsIgnorePattern: "^_",
|
|
90
|
+
args: "after-used",
|
|
91
|
+
argsIgnorePattern: "^_",
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "config-files",
|
|
98
|
+
files: ["**/app.config.ts", "**/env.ts", "**/env.js"],
|
|
99
|
+
rules: {
|
|
100
|
+
"antfu/no-import-dist": "off",
|
|
101
|
+
"node/prefer-global/process": "off",
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: "api-client",
|
|
106
|
+
files: ["**/lib/api/client.ts"],
|
|
107
|
+
rules: {
|
|
108
|
+
"node/prefer-global/process": "off",
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@import "uniwind";
|
|
3
|
+
|
|
4
|
+
@theme {
|
|
5
|
+
--font-system:
|
|
6
|
+
system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
7
|
+
"Helvetica Neue", Arial, sans-serif;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@layer theme {
|
|
11
|
+
@variant light {
|
|
12
|
+
:root {
|
|
13
|
+
--color-background: #ffffff;
|
|
14
|
+
--color-background-element: #f5f5f7;
|
|
15
|
+
--color-foreground: #000000;
|
|
16
|
+
--color-text: #1d1d1f;
|
|
17
|
+
--color-text-secondary: #86868b;
|
|
18
|
+
|
|
19
|
+
--color-primary: #000000;
|
|
20
|
+
--color-primary-foreground: #ffffff;
|
|
21
|
+
|
|
22
|
+
--color-muted: #f0f0f0;
|
|
23
|
+
--color-muted-foreground: #a8a8a8;
|
|
24
|
+
|
|
25
|
+
--color-card: #ffffff;
|
|
26
|
+
--color-card-foreground: #1d1d1f;
|
|
27
|
+
|
|
28
|
+
--color-border: #e5e5e5;
|
|
29
|
+
--color-destructive: #ff3b30;
|
|
30
|
+
|
|
31
|
+
--color-success: #34c759;
|
|
32
|
+
--color-warning: #ff9500;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@variant dark {
|
|
37
|
+
:root {
|
|
38
|
+
--color-background: #000000;
|
|
39
|
+
--color-background-element: #1c1c1e;
|
|
40
|
+
--color-foreground: #ffffff;
|
|
41
|
+
--color-text: #f5f5f7;
|
|
42
|
+
--color-text-secondary: #8e8e93;
|
|
43
|
+
|
|
44
|
+
--color-primary: #ffffff;
|
|
45
|
+
--color-primary-foreground: #000000;
|
|
46
|
+
|
|
47
|
+
--color-muted: #2c2c2e;
|
|
48
|
+
--color-muted-foreground: #636366;
|
|
49
|
+
|
|
50
|
+
--color-card: #1c1c1e;
|
|
51
|
+
--color-card-foreground: #f5f5f7;
|
|
52
|
+
|
|
53
|
+
--color-border: #38383a;
|
|
54
|
+
--color-destructive: #ff453a;
|
|
55
|
+
|
|
56
|
+
--color-success: #30d158;
|
|
57
|
+
--color-warning: #ff9f0a;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const { getDefaultConfig } = require("expo/metro-config");
|
|
2
|
+
const { withUniwindConfig } = require("uniwind/metro");
|
|
3
|
+
|
|
4
|
+
/** @type {import('expo/metro-config').MetroConfig} */
|
|
5
|
+
const config = getDefaultConfig(__dirname);
|
|
6
|
+
|
|
7
|
+
module.exports = withUniwindConfig(config, {
|
|
8
|
+
cssEntryFile: "./global.css",
|
|
9
|
+
dtsFile: "./src/types/uniwind.d.ts",
|
|
10
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fiesta",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"main": "expo-router/entry",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "expo start",
|
|
8
|
+
"ios": "expo run:ios",
|
|
9
|
+
"android": "expo run:android",
|
|
10
|
+
"prebuild": "expo prebuild",
|
|
11
|
+
"lint": "eslint .",
|
|
12
|
+
"lint:fix": "eslint . --fix",
|
|
13
|
+
"type-check": "tsc --noEmit",
|
|
14
|
+
"build:local": "eas build --profile local",
|
|
15
|
+
"build:preview": "eas build --profile preview",
|
|
16
|
+
"build:production": "eas build --profile production",
|
|
17
|
+
"submit": "eas submit"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@expo/vector-icons": "^15.0.2",
|
|
21
|
+
"@react-native-segmented-control/segmented-control": "^2.5.7",
|
|
22
|
+
"@shopify/flash-list": "2.0.2",
|
|
23
|
+
"@tanstack/react-query": "^5.90.20",
|
|
24
|
+
"clsx": "^2.1.1",
|
|
25
|
+
"date-fns": "^4.1.0",
|
|
26
|
+
"expo": "^55.0.0",
|
|
27
|
+
"expo-application": "~55.0.8",
|
|
28
|
+
"expo-build-properties": "~55.0.9",
|
|
29
|
+
"expo-constants": "~55.0.7",
|
|
30
|
+
"expo-dev-client": "~55.0.9",
|
|
31
|
+
"expo-font": "~55.0.4",
|
|
32
|
+
"expo-image": "~55.0.5",
|
|
33
|
+
"expo-linear-gradient": "~55.0.8",
|
|
34
|
+
"expo-linking": "~55.0.7",
|
|
35
|
+
"expo-router": "~55.0.2",
|
|
36
|
+
"expo-status-bar": "~55.0.4",
|
|
37
|
+
"expo-symbols": "~55.0.4",
|
|
38
|
+
"expo-system-ui": "~55.0.9",
|
|
39
|
+
"number-flow-react-native": "^0.4.0",
|
|
40
|
+
"openapi-fetch": "^0.15.2",
|
|
41
|
+
"pressto": "^0.6.1",
|
|
42
|
+
"react": "19.2.0",
|
|
43
|
+
"react-dom": "19.2.0",
|
|
44
|
+
"react-hook-form": "^7.71.1",
|
|
45
|
+
"react-native": "0.83.2",
|
|
46
|
+
"react-native-gesture-handler": "~2.30.0",
|
|
47
|
+
"react-native-keyboard-controller": "^1.20.7",
|
|
48
|
+
"react-native-nitro-modules": "^0.33.9",
|
|
49
|
+
"react-native-reanimated": "~4.2.1",
|
|
50
|
+
"react-native-safe-area-context": "~5.6.2",
|
|
51
|
+
"react-native-screen-transitions": "^3.3.0",
|
|
52
|
+
"react-native-screens": "~4.23.0",
|
|
53
|
+
"react-native-svg": "15.15.3",
|
|
54
|
+
"react-native-trays": "^0.11.0",
|
|
55
|
+
"react-native-worklets": "0.7.2",
|
|
56
|
+
"rn-squircle": "^1.2.4",
|
|
57
|
+
"sonner-native": "^0.23.0",
|
|
58
|
+
"tailwind-merge": "^3.4.0",
|
|
59
|
+
"tailwind-variants": "^3.2.2",
|
|
60
|
+
"uniwind": "^1.3.1",
|
|
61
|
+
"voltra": "1.3.0-rc.1"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@antfu/eslint-config": "^7.6.1",
|
|
65
|
+
"@babel/core": "^7.26.10",
|
|
66
|
+
"@eslint-react/eslint-plugin": "^2.13.0",
|
|
67
|
+
"@rozenite/metro": "^1.3.0",
|
|
68
|
+
"@rozenite/tanstack-query-plugin": "^1.3.0",
|
|
69
|
+
"@types/react": "~19.2.10",
|
|
70
|
+
"eslint": "^10.0.2",
|
|
71
|
+
"eslint-plugin-react-compiler": "^19.1.0-rc.2",
|
|
72
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
73
|
+
"eslint-plugin-react-refresh": "^0.5.2",
|
|
74
|
+
"tailwindcss": "^4.0.0",
|
|
75
|
+
"typescript": "~5.9.2"
|
|
76
|
+
},
|
|
77
|
+
"overrides": {
|
|
78
|
+
"expo-file-system": "~55.0.5"
|
|
79
|
+
},
|
|
80
|
+
"expo": {
|
|
81
|
+
"install": {
|
|
82
|
+
"exclude": [
|
|
83
|
+
"eslint-config-expo"
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
|
|
2
|
+
import { NativeTabs } from "expo-router/unstable-native-tabs";
|
|
3
|
+
import { View } from "react-native";
|
|
4
|
+
|
|
5
|
+
import { useThemeColors } from "@/config/theme";
|
|
6
|
+
|
|
7
|
+
const VectorIcon = NativeTabs.Trigger.VectorIcon;
|
|
8
|
+
|
|
9
|
+
export default function TabLayout() {
|
|
10
|
+
const colors = useThemeColors();
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<View style={{ flex: 1 }}>
|
|
14
|
+
<NativeTabs
|
|
15
|
+
backgroundColor={colors.background}
|
|
16
|
+
tintColor={colors.primary}
|
|
17
|
+
iconColor={{
|
|
18
|
+
default: colors.mutedForeground,
|
|
19
|
+
selected: colors.primary,
|
|
20
|
+
}}
|
|
21
|
+
indicatorColor={colors.muted}
|
|
22
|
+
rippleColor={colors.primary}
|
|
23
|
+
>
|
|
24
|
+
<NativeTabs.Trigger name="index">
|
|
25
|
+
<NativeTabs.Trigger.Icon
|
|
26
|
+
src={<VectorIcon family={MaterialIcons} name="event" />}
|
|
27
|
+
/>
|
|
28
|
+
<NativeTabs.Trigger.Label hidden>Home</NativeTabs.Trigger.Label>
|
|
29
|
+
</NativeTabs.Trigger>
|
|
30
|
+
|
|
31
|
+
<NativeTabs.Trigger name="widgets">
|
|
32
|
+
<NativeTabs.Trigger.Icon
|
|
33
|
+
src={<VectorIcon family={MaterialIcons} name="widgets" />}
|
|
34
|
+
/>
|
|
35
|
+
<NativeTabs.Trigger.Label hidden>Widgets</NativeTabs.Trigger.Label>
|
|
36
|
+
</NativeTabs.Trigger>
|
|
37
|
+
</NativeTabs>
|
|
38
|
+
</View>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import Screen from "@/components/layout/screen";
|
|
2
|
+
import ScrollView from "@/components/layout/scroll-view";
|
|
3
|
+
import View from "@/components/layout/view";
|
|
4
|
+
import { FIESTA_EVENTS } from "@/data/fiesta-data";
|
|
5
|
+
import CelebrationCard from "@/features/home/celebration-card";
|
|
6
|
+
import TodayHero from "@/features/home/today-hero";
|
|
7
|
+
import { getUpcomingCelebrations } from "@/lib/celebrations";
|
|
8
|
+
|
|
9
|
+
export default function HomeScreen() {
|
|
10
|
+
const upcoming = getUpcomingCelebrations(FIESTA_EVENTS, 4);
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<Screen>
|
|
14
|
+
<ScrollView
|
|
15
|
+
className="flex-1"
|
|
16
|
+
contentContainerStyle={{ paddingBottom: 120 }}
|
|
17
|
+
>
|
|
18
|
+
<TodayHero />
|
|
19
|
+
|
|
20
|
+
<View className="mt-6">
|
|
21
|
+
{upcoming.map((event) => (
|
|
22
|
+
<CelebrationCard key={event.id} event={event} />
|
|
23
|
+
))}
|
|
24
|
+
</View>
|
|
25
|
+
</ScrollView>
|
|
26
|
+
</Screen>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import Screen from "@/components/layout/screen";
|
|
2
|
+
import View from "@/components/layout/view";
|
|
3
|
+
import Text from "@/components/ui/text";
|
|
4
|
+
|
|
5
|
+
export default function WidgetsScreen() {
|
|
6
|
+
return (
|
|
7
|
+
<Screen>
|
|
8
|
+
<View className="flex-1 items-center justify-center">
|
|
9
|
+
<Text variant="subtitle">Widgets coming soon</Text>
|
|
10
|
+
</View>
|
|
11
|
+
</Screen>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { View, Text } from "react-native";
|
|
2
|
+
import { Link, Stack } from "expo-router";
|
|
3
|
+
|
|
4
|
+
export default function NotFound() {
|
|
5
|
+
return (
|
|
6
|
+
<>
|
|
7
|
+
<Stack.Screen options={{ title: "Not Found" }} />
|
|
8
|
+
<View className="flex-1 items-center justify-center bg-background">
|
|
9
|
+
<Text className="text-foreground text-lg">This screen does not exist.</Text>
|
|
10
|
+
<Link href="/" className="mt-4 text-primary">
|
|
11
|
+
<Text>Go to home</Text>
|
|
12
|
+
</Link>
|
|
13
|
+
</View>
|
|
14
|
+
</>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import "../../global.css";
|
|
2
|
+
|
|
3
|
+
import { StatusBar } from "expo-status-bar";
|
|
4
|
+
import { PressablesConfig } from "pressto";
|
|
5
|
+
import Transition from "react-native-screen-transitions";
|
|
6
|
+
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
|
7
|
+
import { KeyboardProvider } from "react-native-keyboard-controller";
|
|
8
|
+
import { enableFreeze } from "react-native-screens";
|
|
9
|
+
import { Toaster } from "sonner-native";
|
|
10
|
+
|
|
11
|
+
import { Appearance } from "react-native";
|
|
12
|
+
import { Uniwind } from "uniwind";
|
|
13
|
+
|
|
14
|
+
import Stack from "@/components/navigation/stack";
|
|
15
|
+
|
|
16
|
+
enableFreeze(true);
|
|
17
|
+
|
|
18
|
+
Uniwind.setTheme(Appearance.getColorScheme() === "dark" ? "dark" : "light");
|
|
19
|
+
|
|
20
|
+
export default function RootLayout() {
|
|
21
|
+
return (
|
|
22
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
23
|
+
<KeyboardProvider>
|
|
24
|
+
<PressablesConfig
|
|
25
|
+
defaultProps={{
|
|
26
|
+
rippleColor: "transparent",
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
<StatusBar style="auto" />
|
|
30
|
+
<Stack>
|
|
31
|
+
<Stack.Screen name="(tabs)" />
|
|
32
|
+
<Stack.Screen
|
|
33
|
+
name="event/[id]"
|
|
34
|
+
options={({ route }) => {
|
|
35
|
+
const sharedTag = (route.params as Record<string, string> | undefined)?.sharedBoundTag;
|
|
36
|
+
return sharedTag
|
|
37
|
+
? Transition.Presets.SharedXImage({ sharedBoundTag: sharedTag })
|
|
38
|
+
: Transition.Presets.ElasticCard({ elasticFactor: 0.25 });
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
</Stack>
|
|
42
|
+
<Toaster position="top-center" offset={60} />
|
|
43
|
+
</PressablesConfig>
|
|
44
|
+
</KeyboardProvider>
|
|
45
|
+
</GestureHandlerRootView>
|
|
46
|
+
);
|
|
47
|
+
}
|