diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3382270b0..c6ed2849f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,7 +77,16 @@ jobs: with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - cache-dependency-path: formulus/package-lock.json + cache-dependency-path: | + formulus/package-lock.json + packages/tokens/package-lock.json + + - name: Install and build @ode/tokens + working-directory: . + run: | + cd packages/tokens + npm install + npm run build - name: Install dependencies run: npm install @@ -262,19 +271,19 @@ jobs: echo "| Synkronus | ${{ needs.synkronus.result }} |" >> $GITHUB_STEP_SUMMARY echo "| Synkronus CLI | ${{ needs.synkronus-cli.result }} |" >> $GITHUB_STEP_SUMMARY - if [ "${{ needs.formulus.result }}" != "success" ] && [ "${{ needs.formulus.result }}" != "skipped" ]; then + if [ "${{ needs.formulus.result }}" == "failure" ]; then echo "❌ Formulus CI failed" exit 1 fi - if [ "${{ needs.formulus-formplayer.result }}" != "success" ] && [ "${{ needs.formulus-formplayer.result }}" != "skipped" ]; then + if [ "${{ needs.formulus-formplayer.result }}" == "failure" ]; then echo "❌ Formulus Formplayer CI failed" exit 1 fi - if [ "${{ needs.synkronus.result }}" != "success" ] && [ "${{ needs.synkronus.result }}" != "skipped" ]; then + if [ "${{ needs.synkronus.result }}" == "failure" ]; then echo "❌ Synkronus CI failed" exit 1 fi - if [ "${{ needs.synkronus-cli.result }}" != "success" ] && [ "${{ needs.synkronus-cli.result }}" != "skipped" ]; then + if [ "${{ needs.synkronus-cli.result }}" == "failure" ]; then echo "❌ Synkronus CLI CI failed" exit 1 fi diff --git a/.github/workflows/formulus-android.yml b/.github/workflows/formulus-android.yml index 005ab152c..cef3b8cc7 100644 --- a/.github/workflows/formulus-android.yml +++ b/.github/workflows/formulus-android.yml @@ -93,16 +93,16 @@ jobs: packages/tokens/package-lock.json packages/tokens/package.json - - name: Install npm dependencies (formulus) - working-directory: formulus - run: npm ci - - name: Install and build @ode/tokens working-directory: packages/tokens run: | npm install npm run build + - name: Install npm dependencies (formulus) + working-directory: formulus + run: npm ci + - name: Set up Java uses: actions/setup-java@v4 with: diff --git a/Dockerfile b/Dockerfile index 063ffafa4..e87ea16af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,6 +31,7 @@ COPY packages/tokens/package*.json ./packages/tokens/ COPY packages/tokens/package-lock.json ./packages/tokens/ COPY packages/tokens/style-dictionary.config.js ./packages/tokens/ COPY packages/tokens/config.json ./packages/tokens/ +COPY packages/tokens/scripts ./packages/tokens/scripts COPY packages/tokens/src ./packages/tokens/src COPY packages/components/package*.json ./packages/components/ COPY synkronus-portal/package*.json ./synkronus-portal/ diff --git a/formulus/metro.config.js b/formulus/metro.config.js index 52f1cfd15..1e6aae786 100644 --- a/formulus/metro.config.js +++ b/formulus/metro.config.js @@ -1,15 +1,58 @@ import { getDefaultConfig, mergeConfig } from '@react-native/metro-config'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; + const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +/** Monorepo root (parent of formulus) so Metro can resolve @ode/tokens and @ode/components */ +const monorepoRoot = path.resolve(__dirname, '..'); + +/** + * Force a single React/react-native instance so hooks work (avoids "Invalid hook call" / "useState of null"). + * Without this, @ode/components would use its own node_modules/react and we'd have two React copies. + */ +const projectRoot = __dirname; + +/** + * Force react and react-native to always resolve from the app's node_modules + * (avoids incomplete copy in packages/components). react-native-svg only uses + * extraNodeModules so Metro resolves its real entry (lib/commonjs/index.js). + */ +const forcedModules = { + react: path.resolve(projectRoot, 'node_modules/react'), + 'react-native': path.resolve(projectRoot, 'node_modules/react-native'), +}; +const extraModules = { + ...forcedModules, + 'react-native-svg': path.resolve( + projectRoot, + 'node_modules/react-native-svg', + ), +}; + /** * Metro configuration * https://reactnative.dev/docs/metro * * @type {import('@react-native/metro-config').MetroConfig} */ -const config = {}; +const config = { + watchFolders: [monorepoRoot], + resolver: { + unstable_enableSymlinks: true, + unstable_enablePackageExports: true, + extraNodeModules: extraModules, + resolveRequest(context, moduleName, platform) { + if (forcedModules[moduleName]) { + return { + type: 'sourceFile', + filePath: path.join(forcedModules[moduleName], 'index.js'), + }; + } + return context.resolveRequest(context, moduleName, platform); + }, + }, +}; export default mergeConfig(getDefaultConfig(__dirname), config); diff --git a/formulus/package-lock.json b/formulus/package-lock.json index 69284eca0..4f8006803 100644 --- a/formulus/package-lock.json +++ b/formulus/package-lock.json @@ -10,6 +10,8 @@ "dependencies": { "@notifee/react-native": "^9.1.8", "@nozbe/watermelondb": "^0.28.0", + "@ode/components": "file:../packages/components", + "@ode/tokens": "file:../packages/tokens", "@react-native-async-storage/async-storage": "^2.2.0", "@react-native-documents/picker": "^12.0.0", "@react-native-vector-icons/material-design-icons": "^12.4.0", @@ -32,6 +34,7 @@ "react-native-safe-area-context": "^5.6.2", "react-native-screens": "^4.19.0", "react-native-signature-canvas": "^5.0.2", + "react-native-svg": "^15.11.2", "react-native-url-polyfill": "^3.0.0", "react-native-vision-camera": "^4.7.3", "react-native-webview": "^13.16.0", @@ -77,6 +80,37 @@ "node": ">=20" } }, + "../packages/components": { + "name": "@ode/components", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.0", + "@ode/tokens": "file:../tokens", + "react-native-svg": "^15.15.3" + }, + "devDependencies": { + "@types/react": "^19.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "eslint": "^8.57.0", + "prettier": "^3.0.0", + "typescript": "^5.0.4" + }, + "peerDependencies": { + "@ode/tokens": "file:../tokens", + "react": ">=18.0.0", + "react-native": ">=0.70.0" + } + }, + "../packages/tokens": { + "name": "@ode/tokens", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "style-dictionary": "^3.9.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -105,7 +139,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -137,7 +170,6 @@ "integrity": "sha512-fcdRcWahONYo+JRnJg1/AekOacGvKx12Gu0qXJXFi2WBqQA1i7+O5PaxRB7kxE/Op94dExnCiiar6T09pvdHpA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -3297,7 +3329,6 @@ "integrity": "sha512-R/+A8XFqLgN8zNs2twhrOaE7dJbRQhdPX3g46am4RT/x8xGLqDphrXkUIno4cGUZHxbczChBAaAPTdPv73wDZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "file-type": "21.2.0", "iterare": "1.2.1", @@ -3513,6 +3544,14 @@ "dev": true, "license": "MIT" }, + "node_modules/@ode/components": { + "resolved": "../packages/components", + "link": true + }, + "node_modules/@ode/tokens": { + "resolved": "../packages/tokens", + "link": true + }, "node_modules/@openapitools/openapi-generator-cli": { "version": "2.27.0", "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.27.0.tgz", @@ -3592,7 +3631,6 @@ "integrity": "sha512-ocgRFKRLX8b5rEK38SJfpr0AMl6SqseWljk6c5LxCG/zpCfPPNQdXq1OsDvmEwsqO4OEQ6tmOaSm9OgTm6FhbQ==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@react-native-community/cli-clean": "20.0.2", "@react-native-community/cli-config": "20.0.2", @@ -4409,7 +4447,6 @@ "integrity": "sha512-1rjYZf62fCm6QAinHmRAKnJxIypX0VF/zBPd0qWvWABMZugrS0eACuIbk9Wk0StBod4yL8KnwEJyg77ak8xYzQ==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@react-native/js-polyfills": "0.83.1", "@react-native/metro-babel-transformer": "0.83.1", @@ -4521,7 +4558,6 @@ "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.26.tgz", "integrity": "sha512-RhKmeD0E2ejzKS6z8elAfdfwShpcdkYY8zJzvHYLq+wv183BBcElTeyMLcIX6wIn7QutXeI92Yi21t7aUWfqNQ==", "license": "MIT", - "peer": true, "dependencies": { "@react-navigation/core": "^7.13.7", "escape-string-regexp": "^4.0.0", @@ -4906,7 +4942,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.7.tgz", "integrity": "sha512-+054pVMzVTmRQV8BhpGv3UyfZ2Llgl8rdpDTon+cUH9+na0ncBVXj3wTUKh14+Kiz18ziM3b4ikpP5/Pc0rQEQ==", "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -4917,7 +4952,6 @@ "integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -4959,7 +4993,6 @@ "integrity": "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.52.0", @@ -4999,7 +5032,6 @@ "integrity": "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.52.0", "@typescript-eslint/types": "8.52.0", @@ -5568,7 +5600,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5953,7 +5984,6 @@ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", @@ -6223,6 +6253,12 @@ "devOptional": true, "license": "MIT" }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -6264,7 +6300,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -6936,6 +6971,56 @@ "node": ">= 8" } }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -7208,6 +7293,61 @@ "node": ">=0.10.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -7280,6 +7420,18 @@ "node": ">= 0.8" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -7583,7 +7735,6 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -7644,7 +7795,6 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -9788,7 +9938,6 @@ "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "30.2.0", "@jest/types": "30.2.0", @@ -11349,6 +11498,12 @@ "node": ">= 0.4" } }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -12210,6 +12365,18 @@ "node": ">=8" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nullthrows": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", @@ -12787,7 +12954,6 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -13060,7 +13226,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -13119,7 +13284,6 @@ "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.83.1.tgz", "integrity": "sha512-mL1q5HPq5cWseVhWRLl+Fwvi5z1UO+3vGOpjr+sHFwcUletPRZ5Kv+d0tUfqHmvi73/53NjlQqX1Pyn4GguUfA==", "license": "MIT", - "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.83.1", @@ -13212,7 +13376,6 @@ "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.30.0.tgz", "integrity": "sha512-5YsnKHGa0X9C8lb5oCnKm0fLUPM6CRduvUUw2Bav4RIj/C3HcFh4RIUnF8wgG6JQWCL1//gRx4v+LVWgcIQdGA==", "license": "MIT", - "peer": true, "dependencies": { "@egjs/hammerjs": "^2.0.17", "hoist-non-react-statics": "^3.3.0", @@ -13251,7 +13414,6 @@ "resolved": "https://registry.npmjs.org/react-native-nitro-modules/-/react-native-nitro-modules-0.32.2.tgz", "integrity": "sha512-N1F0EgoKEQJDs0clAGZTauXauxBYUN8y8QLEyeBy3WJhXUlzuldllah4CqRu0WVxZGA+5pTcxXsPeXAHDa6Wag==", "license": "MIT", - "peer": true, "peerDependencies": { "react": "*", "react-native": "*" @@ -13295,7 +13457,6 @@ "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==", "license": "MIT", - "peer": true, "peerDependencies": { "react": "*", "react-native": "*" @@ -13306,7 +13467,6 @@ "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.19.0.tgz", "integrity": "sha512-qSDAO3AL5bti0Ri7KZRSVmWlhDr8MV86N5GruiKVQfEL7Zx2nUi3Dl62lqHUAD/LnDvOPuDDsMHCfIpYSv3hPQ==", "license": "MIT", - "peer": true, "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" @@ -13325,6 +13485,21 @@ "react-native-webview": ">=13" } }, + "node_modules/react-native-svg": { + "version": "15.15.3", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.15.3.tgz", + "integrity": "sha512-/k4KYwPBLGcx2f5d4FjE+vCScK7QOX14cl2lIASJ28u4slHHtIhL0SZKU7u9qmRBHxTCKPoPBtN6haT1NENJNA==", + "license": "MIT", + "dependencies": { + "css-select": "^5.1.0", + "css-tree": "^1.1.3", + "warn-once": "0.1.1" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-url-polyfill": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/react-native-url-polyfill/-/react-native-url-polyfill-3.0.0.tgz", @@ -13366,7 +13541,6 @@ "resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.16.0.tgz", "integrity": "sha512-Nh13xKZWW35C0dbOskD7OX01nQQavOzHbCw9XoZmar4eXCo7AvrYJ0jlUfRVVIJzqINxHlpECYLdmAdFsl9xDA==", "license": "MIT", - "peer": true, "dependencies": { "escape-string-regexp": "^4.0.0", "invariant": "2.2.4" @@ -13818,7 +13992,6 @@ "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-19.2.4.tgz", "integrity": "sha512-Ttl5D7Rnmi6JGMUpri4UjB4BAN0FPs4yRDnu2XSsigCWOLm11o8GwRlVsh27ER+4WFqsGtrBuuv5zumUaRCmKw==", "license": "MIT", - "peer": true, "dependencies": { "react-is": "^19.2.4", "scheduler": "^0.27.0" @@ -13860,8 +14033,7 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "dev": true, - "license": "Apache-2.0", - "peer": true + "license": "Apache-2.0" }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", @@ -14142,7 +14314,6 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -15233,7 +15404,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -15323,7 +15493,6 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -15501,7 +15670,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16178,7 +16346,6 @@ "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/formulus/package.json b/formulus/package.json index f51414245..4769f80f9 100644 --- a/formulus/package.json +++ b/formulus/package.json @@ -18,6 +18,8 @@ "prebuild": "npm run generate" }, "dependencies": { + "@ode/components": "file:../packages/components", + "@ode/tokens": "file:../packages/tokens", "@notifee/react-native": "^9.1.8", "@nozbe/watermelondb": "^0.28.0", "@react-native-async-storage/async-storage": "^2.2.0", @@ -42,6 +44,7 @@ "react-native-safe-area-context": "^5.6.2", "react-native-screens": "^4.19.0", "react-native-signature-canvas": "^5.0.2", + "react-native-svg": "^15.11.2", "react-native-url-polyfill": "^3.0.0", "react-native-vision-camera": "^4.7.3", "react-native-webview": "^13.16.0", diff --git a/formulus/src/components/MenuDrawer.tsx b/formulus/src/components/MenuDrawer.tsx index 15893c96e..6f206307d 100644 --- a/formulus/src/components/MenuDrawer.tsx +++ b/formulus/src/components/MenuDrawer.tsx @@ -14,6 +14,7 @@ import { import Icon from '@react-native-vector-icons/material-design-icons'; import { getUserInfo, UserInfo, UserRole } from '../api/synkronus/Auth'; import { colors } from '../theme/colors'; +import Button from './common/Button'; interface MenuItem { icon: React.ComponentProps['name']; @@ -174,16 +175,13 @@ const MenuDrawer: React.FC = ({ {userInfo && ( - - - Logout - + - {isUpdateButtonActive ? ( @@ -583,7 +579,7 @@ const SyncScreen = () => { {isUpdateButtonActive ? 'Updating...' : 'Update App Bundle'} - + {!syncState.isActive && updateAvailable && ( Update available @@ -796,18 +792,6 @@ const styles = StyleSheet.create({ textAlign: 'center', marginBottom: 12, }, - cancelButton: { - backgroundColor: colors.semantic.error[500], - paddingVertical: 8, - paddingHorizontal: 16, - borderRadius: 8, - alignSelf: 'center', - }, - cancelButtonText: { - color: colors.neutral.white, - fontSize: 14, - fontWeight: '600', - }, errorCard: { backgroundColor: colors.semantic.error[50], borderRadius: 12, @@ -832,53 +816,9 @@ const styles = StyleSheet.create({ color: colors.semantic.error[600], marginBottom: 12, }, - dismissButton: { - backgroundColor: colors.semantic.error[500], - paddingVertical: 8, - paddingHorizontal: 16, - borderRadius: 8, - alignSelf: 'flex-end', - }, - dismissButtonText: { - color: colors.neutral.white, - fontSize: 14, - fontWeight: '600', - }, actionsSection: { gap: 12, }, - actionButton: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - gap: 8, - padding: 16, - borderRadius: 12, - shadowColor: colors.neutral.black, - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.1, - shadowRadius: 4, - elevation: 3, - }, - primaryButton: { - backgroundColor: colors.brand.primary[500], - }, - secondaryButton: { - backgroundColor: colors.neutral.white, - borderWidth: 2, - borderColor: colors.brand.primary[500], - }, - buttonDisabled: { - opacity: 0.6, - }, - actionButtonText: { - fontSize: 16, - fontWeight: '600', - color: colors.neutral.white, - }, - secondaryButtonText: { - color: colors.brand.primary[500], - }, hintText: { fontSize: 12, color: colors.neutral[500], diff --git a/formulus/src/screens/WelcomeScreen.tsx b/formulus/src/screens/WelcomeScreen.tsx index 74033edf3..949d6f092 100644 --- a/formulus/src/screens/WelcomeScreen.tsx +++ b/formulus/src/screens/WelcomeScreen.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native'; +import { View, Text, Image, StyleSheet } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useNavigation } from '@react-navigation/native'; import { StackNavigationProp } from '@react-navigation/stack'; import { MainAppStackParamList } from '../types/NavigationTypes'; import { colors } from '../theme/colors'; +import { Button } from '../components/common'; import logo from '../../assets/images/logo.png'; type WelcomeScreenNavigationProp = StackNavigationProp; @@ -30,9 +31,15 @@ const WelcomeScreen = () => { Configure your server to get started - - Get Started - + +