diff --git a/examples/react/fake-keyring-app/.gitignore b/examples/react/fake-keyring-app/.gitignore
new file mode 100644
index 00000000..a547bf36
--- /dev/null
+++ b/examples/react/fake-keyring-app/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/examples/react/fake-keyring-app/index.html b/examples/react/fake-keyring-app/index.html
new file mode 100644
index 00000000..79c47019
--- /dev/null
+++ b/examples/react/fake-keyring-app/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React
+
+
+
+
+
+
diff --git a/examples/react/fake-keyring-app/package.json b/examples/react/fake-keyring-app/package.json
new file mode 100644
index 00000000..c6aaa3f1
--- /dev/null
+++ b/examples/react/fake-keyring-app/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "fake-keyring-app",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.26",
+ "@types/react-dom": "^18.0.9",
+ "@vitejs/plugin-react": "^3.0.0",
+ "vite": "^4.0.0"
+ }
+}
\ No newline at end of file
diff --git a/examples/react/fake-keyring-app/public/vite.svg b/examples/react/fake-keyring-app/public/vite.svg
new file mode 100644
index 00000000..e7b8dfb1
--- /dev/null
+++ b/examples/react/fake-keyring-app/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/react/fake-keyring-app/src/App.css b/examples/react/fake-keyring-app/src/App.css
new file mode 100644
index 00000000..2c5e2ef5
--- /dev/null
+++ b/examples/react/fake-keyring-app/src/App.css
@@ -0,0 +1,41 @@
+#root {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
diff --git a/examples/react/fake-keyring-app/src/App.jsx b/examples/react/fake-keyring-app/src/App.jsx
new file mode 100644
index 00000000..9ca19f26
--- /dev/null
+++ b/examples/react/fake-keyring-app/src/App.jsx
@@ -0,0 +1,38 @@
+import { useRef, useEffect } from 'react'
+import './App.css'
+
+function log(...args){
+ console.log(window.location.toString() + " ", ...args)
+}
+
+function KeyringUserApp () {
+ const keyringRef = useRef()
+ function requestKeys () {
+ keyringRef.current.contentWindow.postMessage("gimme the keys", "http://localhost:3001")
+ }
+
+ useEffect(function () {
+ window.addEventListener("message", (event) => {
+ log(`app received "${event.data}" from keyring domain`)
+ // TODO: replace this with keyring site URL
+ if (event.origin !== "http://localhost:3001")
+ return;
+
+ log("TODO: stash UCAN somewhere and send it along with requests (?)")
+ }, false);
+ }, [])
+
+ return (
+
+
+
Keyring Playground
+
+
+
+
+ )
+}
+
+export default KeyringUserApp
diff --git a/examples/react/fake-keyring-app/src/assets/react.svg b/examples/react/fake-keyring-app/src/assets/react.svg
new file mode 100644
index 00000000..6c87de9b
--- /dev/null
+++ b/examples/react/fake-keyring-app/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/react/fake-keyring-app/src/index.css b/examples/react/fake-keyring-app/src/index.css
new file mode 100644
index 00000000..917888c1
--- /dev/null
+++ b/examples/react/fake-keyring-app/src/index.css
@@ -0,0 +1,70 @@
+:root {
+ font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ line-height: 24px;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/examples/react/fake-keyring-app/src/main.jsx b/examples/react/fake-keyring-app/src/main.jsx
new file mode 100644
index 00000000..5cc59919
--- /dev/null
+++ b/examples/react/fake-keyring-app/src/main.jsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+
+ ,
+)
diff --git a/examples/react/fake-keyring-app/vite.config.js b/examples/react/fake-keyring-app/vite.config.js
new file mode 100644
index 00000000..335126d5
--- /dev/null
+++ b/examples/react/fake-keyring-app/vite.config.js
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ server: {
+ port: 3000
+ }
+})
diff --git a/examples/react/fake-keyring/.gitignore b/examples/react/fake-keyring/.gitignore
new file mode 100644
index 00000000..a547bf36
--- /dev/null
+++ b/examples/react/fake-keyring/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/examples/react/fake-keyring/index.html b/examples/react/fake-keyring/index.html
new file mode 100644
index 00000000..79c47019
--- /dev/null
+++ b/examples/react/fake-keyring/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React
+
+
+
+
+
+
diff --git a/examples/react/fake-keyring/package.json b/examples/react/fake-keyring/package.json
new file mode 100644
index 00000000..29efcac8
--- /dev/null
+++ b/examples/react/fake-keyring/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "fake-keyring",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/react": "^18.0.26",
+ "@types/react-dom": "^18.0.9",
+ "@vitejs/plugin-react": "^3.0.0",
+ "vite": "^4.0.0"
+ }
+}
\ No newline at end of file
diff --git a/examples/react/fake-keyring/public/vite.svg b/examples/react/fake-keyring/public/vite.svg
new file mode 100644
index 00000000..e7b8dfb1
--- /dev/null
+++ b/examples/react/fake-keyring/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/react/fake-keyring/src/App.css b/examples/react/fake-keyring/src/App.css
new file mode 100644
index 00000000..2c5e2ef5
--- /dev/null
+++ b/examples/react/fake-keyring/src/App.css
@@ -0,0 +1,41 @@
+#root {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
diff --git a/examples/react/fake-keyring/src/App.jsx b/examples/react/fake-keyring/src/App.jsx
new file mode 100644
index 00000000..33744dab
--- /dev/null
+++ b/examples/react/fake-keyring/src/App.jsx
@@ -0,0 +1,33 @@
+import { useEffect } from 'react'
+import './App.css'
+
+function respondToOpener(event, message){
+ log("responding with " + message)
+ window.parent.postMessage(message, event.origin)
+}
+
+function log(...args){
+ console.log(window.location.toString() + " ", ...args)
+}
+
+function KeyringApp () {
+ useEffect(function () {
+ log("adding message listener")
+ window.addEventListener("message", (event) => {
+ log("keyring received", event.data, "from app domain")
+ // TODO: I think we actually need to let anyone message us?
+ if (event.origin !== "http://localhost:3000")
+ return;
+
+ log("TODO: aquire delegation granting keyring agent access to w3up service on app domain (probably needs a full email confirmation flow?)")
+ log("TODO: create UCAN delegating access to w3up on app domain from keyring agent to app domain agent")
+ respondToOpener(event, "TODO: sending UCAN delegation back to app domain")
+ }, false);
+ }, [])
+ return (
+
+
+ )
+}
+
+export default KeyringApp
diff --git a/examples/react/fake-keyring/src/assets/react.svg b/examples/react/fake-keyring/src/assets/react.svg
new file mode 100644
index 00000000..6c87de9b
--- /dev/null
+++ b/examples/react/fake-keyring/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/react/fake-keyring/src/index.css b/examples/react/fake-keyring/src/index.css
new file mode 100644
index 00000000..917888c1
--- /dev/null
+++ b/examples/react/fake-keyring/src/index.css
@@ -0,0 +1,70 @@
+:root {
+ font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ line-height: 24px;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/examples/react/fake-keyring/src/main.jsx b/examples/react/fake-keyring/src/main.jsx
new file mode 100644
index 00000000..5cc59919
--- /dev/null
+++ b/examples/react/fake-keyring/src/main.jsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+
+ ,
+)
diff --git a/examples/react/fake-keyring/vite.config.js b/examples/react/fake-keyring/vite.config.js
new file mode 100644
index 00000000..5e22209c
--- /dev/null
+++ b/examples/react/fake-keyring/vite.config.js
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ server: {
+ port: 3001
+ }
+})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 44590e41..34de0ad0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -78,6 +78,40 @@ importers:
vitest-environment-w3ui: link:packages/vitest-environment-w3ui
vue: 3.2.45
+ examples/react/fake-keyring:
+ specifiers:
+ '@types/react': ^18.0.26
+ '@types/react-dom': ^18.0.9
+ '@vitejs/plugin-react': ^3.0.0
+ react: ^18.2.0
+ react-dom: ^18.2.0
+ vite: ^4.0.0
+ dependencies:
+ react: 18.2.0
+ react-dom: 18.2.0_react@18.2.0
+ devDependencies:
+ '@types/react': 18.0.26
+ '@types/react-dom': 18.0.9
+ '@vitejs/plugin-react': 3.0.0_vite@4.0.3
+ vite: 4.0.3
+
+ examples/react/fake-keyring-app:
+ specifiers:
+ '@types/react': ^18.0.26
+ '@types/react-dom': ^18.0.9
+ '@vitejs/plugin-react': ^3.0.0
+ react: ^18.2.0
+ react-dom: ^18.2.0
+ vite: ^4.0.0
+ dependencies:
+ react: 18.2.0
+ react-dom: 18.2.0_react@18.2.0
+ devDependencies:
+ '@types/react': 18.0.26
+ '@types/react-dom': 18.0.9
+ '@vitejs/plugin-react': 3.0.0_vite@4.0.3
+ vite: 4.0.3
+
examples/react/file-upload:
specifiers:
'@types/react': ^18.0.26
@@ -750,6 +784,20 @@ packages:
semver: 6.3.0
dev: true
+ /@babel/helper-compilation-targets/7.20.7_@babel+core@7.20.5:
+ resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/compat-data': 7.20.5
+ '@babel/core': 7.20.5
+ '@babel/helper-validator-option': 7.18.6
+ browserslist: 4.21.4
+ lru-cache: 5.1.1
+ semver: 6.3.0
+ dev: true
+
/@babel/helper-create-class-features-plugin/7.20.5_@babel+core@7.20.12:
resolution: {integrity: sha512-3RCdA/EmEaikrhayahwToF0fpweU/8o2p8vhc1c/1kftHOdTKuC65kik/TLc+qfbS8JKw4qqJbne4ovICDhmww==}
engines: {node: '>=6.9.0'}
@@ -830,7 +878,7 @@ packages:
'@babel/core': ^7.4.0-0
dependencies:
'@babel/core': 7.20.5
- '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.5
+ '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.5
'@babel/helper-plugin-utils': 7.20.2
debug: 4.3.4
lodash.debounce: 4.0.8
@@ -1341,7 +1389,7 @@ packages:
dependencies:
'@babel/compat-data': 7.20.5
'@babel/core': 7.20.5
- '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.5
+ '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.5
'@babel/helper-plugin-utils': 7.20.2
'@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.20.5
'@babel/plugin-transform-parameters': 7.20.5_@babel+core@7.20.5
@@ -1924,7 +1972,7 @@ packages:
dependencies:
'@babel/core': 7.20.5
'@babel/helper-annotate-as-pure': 7.18.6
- '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.5
+ '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.5
'@babel/helper-environment-visitor': 7.18.9
'@babel/helper-function-name': 7.19.0
'@babel/helper-optimise-call-expression': 7.18.6
@@ -2090,7 +2138,7 @@ packages:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.20.5
- '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.5
+ '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.5
'@babel/helper-function-name': 7.19.0
'@babel/helper-plugin-utils': 7.20.2
dev: true
@@ -2155,7 +2203,7 @@ packages:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.20.5
- '@babel/helper-module-transforms': 7.20.2
+ '@babel/helper-module-transforms': 7.20.11
'@babel/helper-plugin-utils': 7.20.2
transitivePeerDependencies:
- supports-color
@@ -2212,7 +2260,7 @@ packages:
dependencies:
'@babel/core': 7.20.5
'@babel/helper-hoist-variables': 7.18.6
- '@babel/helper-module-transforms': 7.20.2
+ '@babel/helper-module-transforms': 7.20.11
'@babel/helper-plugin-utils': 7.20.2
'@babel/helper-validator-identifier': 7.19.1
transitivePeerDependencies:
@@ -2239,7 +2287,7 @@ packages:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.20.5
- '@babel/helper-module-transforms': 7.20.2
+ '@babel/helper-module-transforms': 7.20.11
'@babel/helper-plugin-utils': 7.20.2
transitivePeerDependencies:
- supports-color
@@ -3844,7 +3892,7 @@ packages:
'@storybook/csf-plugin': 7.0.0-beta.29
'@storybook/csf-tools': 7.0.0-beta.29
'@storybook/global': 5.0.0
- '@storybook/mdx2-csf': 1.0.0-next.4
+ '@storybook/mdx2-csf': 1.0.0-next.5
'@storybook/node-logger': 7.0.0-beta.29
'@storybook/postinstall': 7.0.0-beta.29
'@storybook/preview-api': 7.0.0-beta.29
@@ -4173,7 +4221,7 @@ packages:
'@storybook/client-logger': 7.0.0-beta.29
'@storybook/core-common': 7.0.0-beta.29
'@storybook/csf-plugin': 7.0.0-beta.29
- '@storybook/mdx2-csf': 1.0.0-next.4
+ '@storybook/mdx2-csf': 1.0.0-next.5
'@storybook/node-logger': 7.0.0-beta.29
'@storybook/preview': 7.0.0-beta.29
'@storybook/preview-api': 7.0.0-beta.29
@@ -4392,7 +4440,7 @@ packages:
'@storybook/core-events': 7.0.0-beta.29
'@storybook/csf': 0.0.2-next.8
'@storybook/csf-tools': 7.0.0-beta.29
- '@storybook/docs-mdx': 0.0.1-next.5
+ '@storybook/docs-mdx': 0.0.1-next.6
'@storybook/global': 5.0.0
'@storybook/node-logger': 7.0.0-beta.29
'@storybook/preview-api': 7.0.0-beta.29
@@ -4470,8 +4518,8 @@ packages:
type-fest: 2.19.0
dev: true
- /@storybook/docs-mdx/0.0.1-next.5:
- resolution: {integrity: sha512-EowXFPq4TBZQguKCdU8y7EzpuSv2vSu5gy7pgF/1P5mq7LG9h8YIrerOW9DL4zfp9E0GHIWlSXR5KuFIqqKc/Q==}
+ /@storybook/docs-mdx/0.0.1-next.6:
+ resolution: {integrity: sha512-DjoSIXADmLJtdroXAjUotFiZlcZ2usWhqrS7aeOtZs0DVR0Ws5WQjnwtpDUXt8gryTSd+OZJ0cNsDcqg4JDEvQ==}
dev: true
/@storybook/docs-tools/7.0.0-beta.29:
@@ -4549,8 +4597,8 @@ packages:
resolution: {integrity: sha512-Ha6GJXxEjqP9Z03iV7ehBKgsij0enB7GRcFstJOHjnV8WEDKfF8uPg3SHh2yfueww7P8SWS3Xc3Rzud80fJctQ==}
dev: true
- /@storybook/mdx2-csf/1.0.0-next.4:
- resolution: {integrity: sha512-nvRgYdpYvXsvSgCzKc4LQA1JxtJzmv47IsFAsh1rTz5FoHyK8watLU2WqX9T4w52fpFXBHx7RwGEsCRt0XgZlQ==}
+ /@storybook/mdx2-csf/1.0.0-next.5:
+ resolution: {integrity: sha512-02w0sgGZaK1agT050yCVhJ+o4rLHANWvLKWjQjeAsYbjneLC5ITt+3GDB4jRiWwJboZ8dHW1fGSK1Vg5fA34aQ==}
dev: true
/@storybook/node-logger/7.0.0-beta.29: