Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Svelte demo project #9

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
13 changes: 13 additions & 0 deletions examples/svelte/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example

# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
30 changes: 30 additions & 0 deletions examples/svelte/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module.exports = {
root: true,
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:svelte/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
extraFileExtensions: ['.svelte']
},
env: {
browser: true,
es2017: true,
node: true
},
overrides: [
{
files: ['*.svelte'],
parser: 'svelte-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser'
}
}
]
};
10 changes: 10 additions & 0 deletions examples/svelte/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
2 changes: 2 additions & 0 deletions examples/svelte/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
engine-strict=true
resolution-mode=highest
13 changes: 13 additions & 0 deletions examples/svelte/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example

# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
9 changes: 9 additions & 0 deletions examples/svelte/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"pluginSearchDirs": ["."],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
}
38 changes: 38 additions & 0 deletions examples/svelte/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Web-gphoto2 Svelte Demo
This demo was created using [Svelte](https://svelte.dev/)+[Kit](https://kit.svelte.dev/), [Tailwindcss](https://tailwindcss.com/) and [DaisyUI](https://daisyui.com/).

## Important notes
- Check `vite.config.ts`, it has crucial configuration for using the web-gphoto2 package, see the root README for details.


## Running the demo
Install the dependencies

```bash
npm install
// or
yarn install
```

Start the demo
```bash
npm run dev
// or
yarn dev
```


## Building
To create a production version of your app make sure to install the correct [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. Then run the following command to build your app:
```bash
npm run build
// or
yarn build
```

You can preview the production build with:
```bash
npm run preview
// or
yarn preview
```
40 changes: 40 additions & 0 deletions examples/svelte/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "web-gphoto2-examples-sveltekit",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev --host",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --plugin-search-dir . --check . && eslint .",
"format": "prettier --plugin-search-dir . --write ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "^2.0.0",
"@sveltejs/kit": "^1.20.4",
"@tailwindcss/typography": "^0.5.9",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"autoprefixer": "^10.4.14",
"daisyui": "^3.1.6",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte": "^2.30.0",
"postcss": "^8.4.24",
"postcss-load-config": "^4.0.1",
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.10.1",
"svelte": "^4.0.5",
"svelte-check": "^3.4.3",
"tailwindcss": "^3.3.2",
"tslib": "^2.4.1",
"typescript": "^5.0.0",
"vite": "^4.4.2"
},
"type": "module",
"dependencies": {
"web-gphoto2": "^0.4.1"
}
}
13 changes: 13 additions & 0 deletions examples/svelte/postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const tailwindcss = require("tailwindcss");
const autoprefixer = require("autoprefixer");

const config = {
plugins: [
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss(),
//But others, like autoprefixer, need to run after,
autoprefixer
]
};

module.exports = config;
12 changes: 12 additions & 0 deletions examples/svelte/src/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface Platform {}
}
}

export {};
15 changes: 15 additions & 0 deletions examples/svelte/src/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en" data-theme="dark">

<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>

<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>

</html>
4 changes: 4 additions & 0 deletions examples/svelte/src/app.postcss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* Write your global styles here, in PostCSS syntax */
@tailwind base;
@tailwind components;
@tailwind utilities
71 changes: 71 additions & 0 deletions examples/svelte/src/lib/camera.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { writable, get, type Writable } from 'svelte/store';
import { Camera, type Config } from 'web-gphoto2';


export const imageURL: Writable<string | null> = writable(null);
export const connected: Writable<boolean> = writable(false);
export const config: Writable<Config> = writable();
export const camera = new Camera();

export async function connectCamera() {
try {
await Camera.showPicker();
await camera.connect();
connected.set(true);
await getConfig();
await handleEvents();
} catch (err) {
console.error('Could not connect to camera:', err);
await disconnectCamera();
}
}

export async function disconnectCamera() {
try {
await camera.disconnect();
} catch (err) { }
connected.set(false);
console.log("Disconnected camera")
}

/**
* Handles camera events to update the config.
* Whenever changes to the camera occur (e.g. connecting flash, manually changing aperture, etc.),
* the changes are reflected in the browser.
*/
async function handleEvents() {
while (true) {
await new Promise((resolve) => requestIdleCallback(resolve, { timeout: 500 }));
try {
if (await camera.consumeEvents()) {
await getConfig();
}
} catch (err) {
console.error('Could not consume events:', err);
await disconnectCamera();
break;
}
}
}

export async function getConfig() {
if (!get(connected)) return;
config.set(await camera.getConfig())
}

export async function updateConfig(name: string, value: string) {
if (!get(connected)) return;
await camera.setConfigValue(name, value);
}

export async function captureImage() {
if (!get(connected)) return;
const blob = await camera.captureImageAsFile();
const url = URL.createObjectURL(blob)
imageURL.set(url);
}

export async function capturePreview() {
if (!get(connected)) return;
return await camera.capturePreviewAsBlob();
}
12 changes: 12 additions & 0 deletions examples/svelte/src/lib/components/Card.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
export let title: string;
</script>

<div class="block p-6 border rounded-lg shadow-xl bg-base-200 border-gray-700">
<h5 class="mb-2 text-3xl font-bold tracking-tight text-white text-center">
{title}
</h5>
<div class="h-[1px] bg-gray-400 mx-8 mb-4" />

<slot />
</div>
9 changes: 9 additions & 0 deletions examples/svelte/src/lib/components/Footer.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<footer class="fixed bottom-0 w-full z-50">
<div class="w-full h-[1px] bg-black" />
<p class="text-center">
<a href="https://icheered.nl/" target="_blank">
Demo by <span class="underline text-primary-light dark:text-primary-dark"> ICheered </span>
- © {new Date().getFullYear()}
</a>
</p>
</footer>
12 changes: 12 additions & 0 deletions examples/svelte/src/lib/components/Header.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<h1 class="text-6xl pt-10">Web-gPhoto2 Svelte Demo</h1>
<p class="pb-10">
Don't know how you got here? Check out the <a
class="link link-primary"
href="https://web.dev/porting-libusb-to-webusb/"
>
blog post
</a>
or the
<a class="link link-primary" href="https://github.com/GoogleChromeLabs/web-gphoto2">Github repo</a
>!
</p>
59 changes: 59 additions & 0 deletions examples/svelte/src/lib/components/Setting.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script lang="ts">
import type { Config } from 'web-gphoto2';
export let name: string;
export let config: Config;
export let updateFunction: (name: string, value: string) => void;
</script>

<div class="">
<div class="form-control w-full max-w-xs">
<label class="label pb-0">
<span class="label-text capitalize">{name} - {config.label}</span>
</label>
{#if config.type === 'text' || config.type === 'datetime' || config.readonly}
<input
type="text"
value={config.value}
class="input input-bordered w-full max-w-xs select-none pointer-events-none"
/>
{:else if config.type === 'radio' || config.type === 'menu'}
<select
class="select select-bordered w-full max-w-xs"
bind:value={config.value}
on:change={() => updateFunction(name, config.value)}
>
{#each config.choices as choice}
<option value={choice}>{choice}</option>
{/each}
</select>
{:else if config.type === 'toggle'}
<div
class="h-12 w-80 flex justify-center place-items-center border border-white border-opacity-20 rounded"
>
<input
type="checkbox"
class="toggle"
disabled={config.readonly}
bind:value={config.value}
on:change={() => updateFunction(name, config.value)}
/>
</div>
{:else if config.type === 'range'}
<div
class="h-12 w-80 flex justify-center place-items-center border border-white border-opacity-20 rounded"
>
<input
type="range"
disabled={config.readonly}
min={config.min}
max={config.max}
step={config.step}
bind:value={config.value}
on:input={() => updateFunction(name, config.value)}
class="range"
/>
<div class="w-10 text-center">{config.value}</div>
</div>
{/if}
</div>
</div>
Loading