Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions apps/example/src/Tests/Tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const Tests = ({ assets }: TestsProps) => {
const [client, hostname] = useClient();
const [drawing, setDrawing] = useState<any>(null);
const [screen, setScreen] = useState<any>(null);

useEffect(() => {
if (client !== null) {
// Define the message handler as a separate function
Expand Down Expand Up @@ -66,16 +66,16 @@ export const Tests = ({ assets }: TestsProps) => {
};

// Use addEventListener instead of onmessage
client.addEventListener('message', handleMessage);
client.addEventListener("message", handleMessage);

// Clean up: remove the specific event listener
return () => {
client.removeEventListener('message', handleMessage);
client.removeEventListener("message", handleMessage);
};
}
return;
}, [assets, client]);

useEffect(() => {
if (drawing && client) {
const it = setTimeout(() => {
Expand Down Expand Up @@ -104,7 +104,7 @@ export const Tests = ({ assets }: TestsProps) => {
}
return;
}, [client, drawing, ref]);

useEffect(() => {
if (screen && client) {
const it = setTimeout(async () => {
Expand All @@ -120,7 +120,7 @@ export const Tests = ({ assets }: TestsProps) => {
}
return;
}, [client, screen]);

return (
<View style={{ flex: 1, backgroundColor: "white" }}>
<Text style={{ color: "black" }}>
Expand Down
1 change: 1 addition & 0 deletions apps/simple-react-app/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SKIP_PREFLIGHT_CHECK=true
29 changes: 29 additions & 0 deletions apps/simple-react-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Simple React App with Skia

This is a simple React application that demonstrates using `@shopify/react-native-skia` from the workspace in a web environment.

## Features

- Basic React app setup with TypeScript
- Integration with react-native-skia for web
- Simple canvas example with circles

## Getting Started

From the monorepo root:

```bash
cd apps/simple-react-app
yarn install
yarn start
```

This will start the development server and open the app in your browser.

## Scripts

- `yarn start` - Start the development server
- `yarn build` - Build for production
- `yarn test` - Run tests
- `yarn lint` - Run ESLint
- `yarn tsc` - Run TypeScript compiler check
54 changes: 54 additions & 0 deletions apps/simple-react-app/craco.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
const path = require("path");

module.exports = {
webpack: {
plugins: {
add: [new NodePolyfillPlugin()]
},
configure: (webpackConfig) => {
// Remove the ModuleScopePlugin which restricts imports to src/
webpackConfig.resolve.plugins = webpackConfig.resolve.plugins.filter(
plugin => plugin.constructor.name !== 'ModuleScopePlugin'
);

// Find and update the babel-loader rule to include workspace packages
const babelRule = webpackConfig.module.rules.find(rule =>
rule.oneOf && Array.isArray(rule.oneOf)
);

if (babelRule) {
const jsRule = babelRule.oneOf.find(rule =>
rule.test && rule.test.toString().includes('jsx')
);

if (jsRule) {
// Extend the JS/JSX rule to include workspace packages
jsRule.include = [
jsRule.include,
path.resolve(__dirname, "../../packages/skia/src")
].filter(Boolean);
}
}

// Add aliases for React Native modules
webpackConfig.resolve.alias = {
...webpackConfig.resolve.alias,
"react-native$": "react-native-web",
"react-native-reanimated": "react-native-reanimated/lib/module/web",
"react-native/Libraries/Image/AssetRegistry": "react-native-web/dist/modules/AssetRegistry",
"@shopify/react-native-skia$": path.resolve(__dirname, "../../packages/skia/src/index.ts"),
"@shopify/react-native-skia/src/web": path.resolve(__dirname, "../../packages/skia/src/web/index.ts")
};

// Ensure canvaskit.wasm is accessible
webpackConfig.resolve.fallback = {
...webpackConfig.resolve.fallback,
fs: false,
path: require.resolve("path-browserify"),
};

return webpackConfig;
}
}
};
47 changes: 47 additions & 0 deletions apps/simple-react-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "simple-react-app",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject",
"lint-disabled": "eslint src --ext .ts,.tsx --max-warnings 0",
"tsc-disabled": "tsc --noEmit"
},
"dependencies": {
"@shopify/react-native-skia": "workspace:*",
"@types/node": "^16.18.0",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-native-reanimated": "3.19.1",
"react-scripts": "5.0.1",
"typescript": "^5.2.2",
"web-vitals": "^2.1.0"
},
"devDependencies": {
"@craco/craco": "^7.1.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.0",
"eslint-config-react-app": "^7.0.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"path-browserify": "^1.0.1",
"react-native-web": "^0.21.1"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
18 changes: 18 additions & 0 deletions apps/simple-react-app/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Simple React app with react-native-skia"
/>
<title>Simple React App with Skia</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
36 changes: 36 additions & 0 deletions apps/simple-react-app/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Canvas, Fill, } from '@shopify/react-native-skia';
function App() {
console.log({ CanvasKit});

const canvases = [];
for (let i = 0; i < 17; i++) {
canvases.push(
<div key={i} style={{ margin: '10px', display: 'inline-block' }}>
<h4>Canvas {i + 1}</h4>
<Canvas style={{ width: 200, height: 200, }}>
<Fill color={`hsl(${(i * 18) % 360}, 70%, 50%)`} />
</Canvas>
</div>
);
}

return (
<div className="App">
<header className="App-header">
<h1>WebGL Canvas Stress Test</h1>
<p>
Testing how many WebGL canvases this browser can support (20 total).
</p>
</header>
<main>
<h2>20 Skia WebGL Canvases</h2>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '10px' }}>
{canvases}
</div>
</main>
</div>
);
}


export default App;
30 changes: 30 additions & 0 deletions apps/simple-react-app/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

.App {
text-align: center;
padding: 20px;
}

.App-header {
background-color: #282c34;
padding: 20px;
color: white;
}

.skia-canvas {
border: 1px solid #ddd;
margin: 20px auto;
display: block;
}
22 changes: 22 additions & 0 deletions apps/simple-react-app/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';

import { LoadSkiaWeb } from "@shopify/react-native-skia/src/web";
//import { version } from 'canvaskit-wasm/package.json';


const version = "0.40.0";
LoadSkiaWeb({
locateFile: (file) => `https://cdn.jsdelivr.net/npm/canvaskit-wasm@${version}/bin/full/${file}`
}).then(async () => {
const App = (await import("./App")).default;
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
});
33 changes: 33 additions & 0 deletions apps/simple-react-app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"compilerOptions": {
"target": "es2015",
"lib": [
"dom",
"dom.iterable",
"es6"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"downlevelIteration": true,
"baseUrl": ".",
"paths": {
"@shopify/react-native-skia": ["../../packages/skia/src/index.ts"],
"@shopify/react-native-skia/src/web": ["../../packages/skia/src/web/index.ts"]
}
},
"include": [
"src",
"../../packages/skia/src"
]
}
Loading
Loading