diff --git a/.npmignore b/.npmignore
index 8fd84a6..c0544ab 100644
--- a/.npmignore
+++ b/.npmignore
@@ -8,5 +8,8 @@ reference
.gitignore
webpack.config.js
-# Ignore doc files
-docs
\ No newline at end of file
+# Ignore doc and example file
+docs
+example
+example_old
+
diff --git a/example/App.js b/example/App.js
index f94fedd..ebe71ab 100644
--- a/example/App.js
+++ b/example/App.js
@@ -1,6 +1,9 @@
import Brahmos, { render, Component, useState } from '../src';
import TodoList from './todo-list/TodoList';
-import SierpinskiTriangleDemo from './sierpinski-triangle/SierpinskiTriangle';
+import SierpinskiTriangleDemo from './sierpinski-triangle';
+import ConcurrentModeDemo from './concurrent-mode';
+import SuspenseListDemo from './suspense-list';
+import SVGDemo from './svg-chart';
import './App.scss';
@@ -15,6 +18,21 @@ const examples = [
id: 'sierpinski-triangle',
Component: SierpinskiTriangleDemo,
},
+ {
+ title: 'Concurrent Mode Demo',
+ id: 'concurrent-mode',
+ Component: ConcurrentModeDemo,
+ },
+ {
+ title: 'Suspense List Demo',
+ id: 'suspense-list',
+ Component: SuspenseListDemo,
+ },
+ {
+ title: 'SVG Chart',
+ id: 'svg-chart',
+ Component: SVGDemo,
+ },
];
export default function App() {
diff --git a/example/concurrent-mode/fakeApi.js b/example/concurrent-mode/fakeApi.js
new file mode 100644
index 0000000..291f4d5
--- /dev/null
+++ b/example/concurrent-mode/fakeApi.js
@@ -0,0 +1,149 @@
+export function fetchProfileData(userId) {
+ const userPromise = fetchUser(userId);
+ const postsPromise = fetchPosts(userId);
+ return {
+ userId,
+ user: wrapPromise(userPromise),
+ posts: wrapPromise(postsPromise),
+ };
+}
+
+// Suspense integrations like Relay implement
+// a contract like this to integrate with React.
+// Real implementations can be significantly more complex.
+// Don't copy-paste this into your project!
+function wrapPromise(promise) {
+ let status = 'pending';
+ let result;
+ const suspender = promise.then(
+ (r) => {
+ status = 'success';
+ result = r;
+ },
+ (e) => {
+ status = 'error';
+ result = e;
+ },
+ );
+ return {
+ read() {
+ if (status === 'pending') {
+ throw suspender;
+ } else if (status === 'error') {
+ throw result;
+ } else if (status === 'success') {
+ return result;
+ }
+ },
+ };
+}
+
+export function fetchUser(userId) {
+ console.log('fetch user ' + userId + '...');
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ console.log('fetched user ' + userId);
+ switch (userId) {
+ case 0:
+ resolve({
+ name: 'Ringo Starr',
+ });
+ break;
+ case 1:
+ resolve({
+ name: 'George Harrison',
+ });
+ break;
+ case 2:
+ resolve({
+ name: 'John Lennon',
+ });
+ break;
+ case 3:
+ resolve({
+ name: 'Paul McCartney',
+ });
+ break;
+ default:
+ throw Error('Unknown user.');
+ }
+ }, 2000 * Math.random());
+ });
+}
+
+export function fetchPosts(userId) {
+ console.log('fetch posts for ' + userId + '...');
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ console.log('fetched posts for ' + userId);
+ switch (userId) {
+ case 0:
+ resolve([
+ {
+ id: 0,
+ text: 'I get by with a little help from my friends',
+ },
+ {
+ id: 1,
+ text: "I'd like to be under the sea in an octupus's garden",
+ },
+ {
+ id: 2,
+ text: 'You got that sand all over your feet',
+ },
+ ]);
+ break;
+ case 1:
+ resolve([
+ {
+ id: 0,
+ text: 'Turn off your mind, relax, and float downstream',
+ },
+ {
+ id: 1,
+ text: 'All things must pass',
+ },
+ {
+ id: 2,
+ text: "I look at the world and I notice it's turning",
+ },
+ ]);
+ break;
+ case 2:
+ resolve([
+ {
+ id: 0,
+ text: 'Living is easy with eyes closed',
+ },
+ {
+ id: 1,
+ text: "Nothing's gonna change my world",
+ },
+ {
+ id: 2,
+ text: 'I am the walrus',
+ },
+ ]);
+ break;
+ case 3:
+ resolve([
+ {
+ id: 0,
+ text: 'Woke up, fell out of bed',
+ },
+ {
+ id: 1,
+ text: 'Here, there, and everywhere',
+ },
+ {
+ id: 2,
+ text: 'Two of us sending postcards, writing letters',
+ },
+ ]);
+ break;
+ default:
+ throw Error('Unknown user.');
+ }
+ }, 2000 * Math.random());
+ });
+}
diff --git a/example/concurrent-mode/index.js b/example/concurrent-mode/index.js
new file mode 100644
index 0000000..4045ad9
--- /dev/null
+++ b/example/concurrent-mode/index.js
@@ -0,0 +1,76 @@
+/**
+ * Forked from: https://codesandbox.io/s/jovial-lalande-26yep?file=/src/index.js:0-1646
+ */
+import Brahmos, { useState, useTransition, Suspense } from '../../src';
+
+import { fetchProfileData } from './fakeApi';
+
+function getNextId(id) {
+ return id === 3 ? 0 : id + 1;
+}
+
+const initialResource = fetchProfileData(0);
+
+function App() {
+ const [resource, setResource] = useState(initialResource);
+ const [startTransition, isPending] = useTransition({
+ timeoutMs: 3000,
+ });
+ return (
+ <>
+
+ {isPending ? ' Loading...' : null}
+
+ This demo is forked from concurrent mode demo of React:
+
+ Source:
+
+ https://codesandbox.io/s/jovial-lalande-26yep?file=/src/index.js:0-1646
+
+
+ This demo is forked from Suspense List demo of React:
+
+ Source:
+
+ https://codesandbox.io/s/black-wind-byilt
+
+