ismot radames commited on
Commit
4e0a699
·
0 Parent(s):

Duplicate from huggingface-projects/color-palette-generator-sd

Browse files

Co-authored-by: Radamés Ajna <[email protected]>

This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +31 -0
  2. .gitignore +19 -0
  3. Makefile +11 -0
  4. README.md +14 -0
  5. app.py +163 -0
  6. extract.py +31 -0
  7. frontend/.env.example +2 -0
  8. frontend/.eslintignore +13 -0
  9. frontend/.eslintrc.cjs +20 -0
  10. frontend/.gitignore +12 -0
  11. frontend/.npmrc +1 -0
  12. frontend/.prettierignore +13 -0
  13. frontend/.prettierrc +8 -0
  14. frontend/README.md +38 -0
  15. frontend/package.json +45 -0
  16. frontend/postcss.config.cjs +6 -0
  17. frontend/src/app.css +3 -0
  18. frontend/src/app.d.ts +15 -0
  19. frontend/src/app.html +13 -0
  20. frontend/src/lib/ArrowLeft.svelte +13 -0
  21. frontend/src/lib/ArrowRight.svelte +13 -0
  22. frontend/src/lib/ColorPalette.svelte +50 -0
  23. frontend/src/lib/Palette.svelte +92 -0
  24. frontend/src/lib/store.ts +3 -0
  25. frontend/src/lib/types.ts +15 -0
  26. frontend/src/lib/utils.ts +118 -0
  27. frontend/src/routes/+layout.svelte +5 -0
  28. frontend/src/routes/+layout.ts +1 -0
  29. frontend/src/routes/+page.svelte +307 -0
  30. frontend/static/favicon.png +0 -0
  31. frontend/static/robots.txt +3 -0
  32. frontend/static/svelte-welcome.png +0 -0
  33. frontend/static/svelte-welcome.webp +0 -0
  34. frontend/svelte.config.js +26 -0
  35. frontend/tailwind.config.cjs +6 -0
  36. frontend/tsconfig.json +17 -0
  37. frontend/vite.config.dev.ts +18 -0
  38. frontend/vite.config.ts +8 -0
  39. requirements.txt +8 -0
  40. run.py +3 -0
  41. static/_app/immutable/assets/_layout-e397cbf6.css +1 -0
  42. static/_app/immutable/assets/_page-fd1176fc.css +1 -0
  43. static/_app/immutable/chunks/0-17a4fec1.js +1 -0
  44. static/_app/immutable/chunks/1-26e94021.js +1 -0
  45. static/_app/immutable/chunks/2-fc64cbc2.js +1 -0
  46. static/_app/immutable/chunks/_layout-1daba58d.js +1 -0
  47. static/_app/immutable/chunks/index-3bda1050.js +1 -0
  48. static/_app/immutable/chunks/index-5559954d.js +1 -0
  49. static/_app/immutable/chunks/singletons-e4c31a41.js +1 -0
  50. static/_app/immutable/components/error.svelte-c31c95c4.js +1 -0
.gitattributes ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ftz filter=lfs diff=lfs merge=lfs -text
6
+ *.gz filter=lfs diff=lfs merge=lfs -text
7
+ *.h5 filter=lfs diff=lfs merge=lfs -text
8
+ *.joblib filter=lfs diff=lfs merge=lfs -text
9
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
10
+ *.model filter=lfs diff=lfs merge=lfs -text
11
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
12
+ *.npy filter=lfs diff=lfs merge=lfs -text
13
+ *.npz filter=lfs diff=lfs merge=lfs -text
14
+ *.onnx filter=lfs diff=lfs merge=lfs -text
15
+ *.ot filter=lfs diff=lfs merge=lfs -text
16
+ *.parquet filter=lfs diff=lfs merge=lfs -text
17
+ *.pickle filter=lfs diff=lfs merge=lfs -text
18
+ *.pkl filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pt filter=lfs diff=lfs merge=lfs -text
21
+ *.pth filter=lfs diff=lfs merge=lfs -text
22
+ *.rar filter=lfs diff=lfs merge=lfs -text
23
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
24
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
25
+ *.tflite filter=lfs diff=lfs merge=lfs -text
26
+ *.tgz filter=lfs diff=lfs merge=lfs -text
27
+ *.wasm filter=lfs diff=lfs merge=lfs -text
28
+ *.xz filter=lfs diff=lfs merge=lfs -text
29
+ *.zip filter=lfs diff=lfs merge=lfs -text
30
+ *.zst filter=lfs diff=lfs merge=lfs -text
31
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ node_modules
3
+ /build
4
+ /.svelte-kit
5
+ /package
6
+ .env
7
+ .env.*
8
+ !.env.example
9
+
10
+ # Ignore files for PNPM, NPM and YARN
11
+ pnpm-lock.yaml
12
+ package-lock.json
13
+ yarn.lock
14
+ venv/
15
+ __pycache__/
16
+ flagged/
17
+ data
18
+ data.db
19
+ data.json
Makefile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ build-client:
2
+ cd frontend && npm install && PUBLIC_DEV_MODE=PROD npm run build && rm -rf ../static && cp -r build/ ../static/
3
+ build-dev:
4
+ cd frontend && npm install && PUBLIC_DEV_MODE=DEV npm run build-dev && rm -rf ../static && cp -r build/ ../static/
5
+ run-front-dev:
6
+ cd frontend && npm install && PUBLIC_DEV_MODE=DEV npm run dev
7
+ run-dev:
8
+ rm -rf .data/ && FLASK_DEBUG=development python app.py
9
+ run-prod:
10
+ python app.py
11
+ build-all: run-prod
README.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Sd Color Palette Generator
3
+ emoji: 📖🎨⚙️
4
+ colorFrom: yellow
5
+ colorTo: gray
6
+ sdk: gradio
7
+ sdk_version: 3.3
8
+ app_file: run.py
9
+ fullWidth: true
10
+ pinned: false
11
+ duplicated_from: huggingface-projects/color-palette-generator-sd
12
+ ---
13
+
14
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+ import json
4
+ from flask import Flask, request, jsonify, g
5
+ from flask_expects_json import expects_json
6
+ from flask_cors import CORS
7
+ from PIL import Image
8
+ from huggingface_hub import Repository
9
+ from flask_apscheduler import APScheduler
10
+ import shutil
11
+ import sqlite3
12
+ import subprocess
13
+ from jsonschema import ValidationError
14
+
15
+ MODE = os.environ.get('FLASK_ENV', 'production')
16
+ IS_DEV = MODE == 'development'
17
+ app = Flask(__name__, static_url_path='/static')
18
+ app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False
19
+
20
+ schema = {
21
+ "type": "object",
22
+ "properties": {
23
+ "prompt": {"type": "string"},
24
+ "images": {
25
+ "type": "array",
26
+ "items": {
27
+ "type": "object",
28
+ "minProperties": 2,
29
+ "maxProperties": 2,
30
+ "properties": {
31
+ "colors": {
32
+ "type": "array",
33
+ "items": {
34
+ "type": "string"
35
+ },
36
+ "maxItems": 5,
37
+ "minItems": 5
38
+ },
39
+ "imgURL": {"type": "string"}}
40
+ }
41
+ }
42
+ },
43
+ "minProperties": 2,
44
+ "maxProperties": 2
45
+ }
46
+
47
+ CORS(app)
48
+
49
+ DB_FILE = Path("./data.db")
50
+ TOKEN = os.environ.get('HUGGING_FACE_HUB_TOKEN')
51
+ repo = Repository(
52
+ local_dir="data",
53
+ repo_type="dataset",
54
+ clone_from="huggingface-projects/color-palettes-sd",
55
+ use_auth_token=TOKEN
56
+ )
57
+ repo.git_pull()
58
+ # copy db on db to local path
59
+ shutil.copyfile("./data/data.db", DB_FILE)
60
+
61
+ db = sqlite3.connect(DB_FILE)
62
+ try:
63
+ data = db.execute("SELECT * FROM palettes").fetchall()
64
+ if IS_DEV:
65
+ print(f"Loaded {len(data)} palettes from local db")
66
+ db.close()
67
+ except sqlite3.OperationalError:
68
+ db.execute(
69
+ 'CREATE TABLE palettes (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, data json, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL)')
70
+ db.commit()
71
+
72
+
73
+ def get_db():
74
+ db = getattr(g, '_database', None)
75
+ if db is None:
76
+ db = g._database = sqlite3.connect(DB_FILE)
77
+ db.row_factory = sqlite3.Row
78
+ return db
79
+
80
+
81
+ @app.teardown_appcontext
82
+ def close_connection(exception):
83
+ db = getattr(g, '_database', None)
84
+ if db is not None:
85
+ db.close()
86
+
87
+
88
+ def update_repository():
89
+ repo.git_pull()
90
+ # copy db on db to local path
91
+ shutil.copyfile(DB_FILE, "./data/data.db")
92
+
93
+ with sqlite3.connect("./data/data.db") as db:
94
+ db.row_factory = sqlite3.Row
95
+ palettes = db.execute("SELECT * FROM palettes").fetchall()
96
+ data = [{'id': row['id'], 'data': json.loads(
97
+ row['data']), 'created_at': row['created_at']} for row in palettes]
98
+
99
+ with open('./data/data.json', 'w') as f:
100
+ json.dump(data, f, separators=(',', ':'))
101
+
102
+ print("Updating repository")
103
+ subprocess.Popen(
104
+ "git add . && git commit --amend -m 'update' && git push --force", cwd="./data", shell=True)
105
+ repo.push_to_hub(blocking=False)
106
+
107
+
108
+ @app.route('/')
109
+ def index():
110
+ return app.send_static_file('index.html')
111
+
112
+
113
+ @app.route('/force_push')
114
+ def push():
115
+ if (request.headers['token'] == TOKEN):
116
+ update_repository()
117
+ return jsonify({'success': True})
118
+ else:
119
+ return "Error", 401
120
+
121
+
122
+ def getAllData():
123
+ palettes = get_db().execute("SELECT * FROM palettes").fetchall()
124
+ data = [{'id': row['id'], 'data': json.loads(
125
+ row['data']), 'created_at': row['created_at']} for row in palettes]
126
+ return data
127
+
128
+
129
+ @app.route('/data')
130
+ def getdata():
131
+ return jsonify(getAllData())
132
+
133
+
134
+ @app.route('/new_palette', methods=['POST'])
135
+ @expects_json(schema)
136
+ def create():
137
+ data = g.data
138
+ db = get_db()
139
+ cursor = db.cursor()
140
+ cursor.execute("INSERT INTO palettes(data) VALUES (?)", [json.dumps(data)])
141
+ db.commit()
142
+ return jsonify(getAllData())
143
+
144
+
145
+ @app.errorhandler(400)
146
+ def bad_request(error):
147
+ if isinstance(error.description, ValidationError):
148
+ original_error = error.description
149
+ return jsonify({'error': original_error.message}), 400
150
+ return error
151
+
152
+
153
+ if __name__ == '__main__':
154
+ if not IS_DEV:
155
+ print("Starting scheduler -- Running Production")
156
+ scheduler = APScheduler()
157
+ scheduler.add_job(id='Update Dataset Repository',
158
+ func=update_repository, trigger='interval', hours=1)
159
+ scheduler.start()
160
+ else:
161
+ print("Not Starting scheduler -- Running Development")
162
+ app.run(host='0.0.0.0', port=int(
163
+ os.environ.get('PORT', 7860)), debug=True, use_reloader=IS_DEV)
extract.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from colorthief import ColorThief
2
+ from pathlib import Path
3
+ import json
4
+ from PIL import Image
5
+
6
+
7
+ images_path = Path('frontend/static/images')
8
+ images = images_path.glob("*.[jpeg jpg png]*")
9
+ print(images)
10
+ data = {}
11
+ for image in images:
12
+ print(image.stem)
13
+ image_pil = Image.open(image)
14
+ color_thief = ColorThief(image)
15
+ image_pil.save(Path.joinpath(images_path, (image.stem + ".jpg")), optimize=True, quality=95)
16
+ prompt = image.stem.split("-")[2]
17
+ try:
18
+ type(data[prompt]) == list
19
+ except:
20
+ data[prompt] = []
21
+
22
+ colors = color_thief.get_palette(color_count=5, quality=1)
23
+ colors_hex = ['#%02x%02x%02x' % (color) for color in colors]
24
+ data[prompt].append({
25
+ "colors": colors_hex,
26
+ "imgURL": "static/images/" + image.stem + ".jpg"
27
+ })
28
+ prompts = [{"prompt": prompt, "images": values}
29
+ for (prompt, values) in data.items()]
30
+ with open('frontend/static/data.json', 'w') as f:
31
+ json.dump(prompts, f)
frontend/.env.example ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ PUBLIC_WS_ENDPOINT="wss://spaces.huggingface.tech/stabilityai/stable-diffusion-1/queue/join"
2
+ PUBLIC_API=""
frontend/.eslintignore ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ node_modules
3
+ /build
4
+ /.svelte-kit
5
+ /package
6
+ .env
7
+ .env.*
8
+ !.env.example
9
+
10
+ # Ignore files for PNPM, NPM and YARN
11
+ pnpm-lock.yaml
12
+ package-lock.json
13
+ yarn.lock
frontend/.eslintrc.cjs ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module.exports = {
2
+ root: true,
3
+ parser: '@typescript-eslint/parser',
4
+ extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
5
+ plugins: ['svelte3', '@typescript-eslint'],
6
+ ignorePatterns: ['*.cjs'],
7
+ overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
8
+ settings: {
9
+ 'svelte3/typescript': () => require('typescript')
10
+ },
11
+ parserOptions: {
12
+ sourceType: 'module',
13
+ ecmaVersion: 2020
14
+ },
15
+ env: {
16
+ browser: true,
17
+ es2017: true,
18
+ node: true
19
+ }
20
+ };
frontend/.gitignore ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ node_modules
3
+ /build
4
+ /.svelte-kit
5
+ /package
6
+ .env
7
+ .env.*
8
+ !.env.example
9
+ .vercel
10
+ .output
11
+ venv/
12
+ __pycache__/
frontend/.npmrc ADDED
@@ -0,0 +1 @@
 
 
1
+ engine-strict=true
frontend/.prettierignore ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .DS_Store
2
+ node_modules
3
+ /build
4
+ /.svelte-kit
5
+ /package
6
+ .env
7
+ .env.*
8
+ !.env.example
9
+
10
+ # Ignore files for PNPM, NPM and YARN
11
+ pnpm-lock.yaml
12
+ package-lock.json
13
+ yarn.lock
frontend/.prettierrc ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "useTabs": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "none",
5
+ "printWidth": 100,
6
+ "pluginSearchDirs": ["."],
7
+ "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
8
+ }
frontend/README.md ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # create-svelte
2
+
3
+ Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
4
+
5
+ ## Creating a project
6
+
7
+ If you're seeing this, you've probably already done this step. Congrats!
8
+
9
+ ```bash
10
+ # create a new project in the current directory
11
+ npm create svelte@latest
12
+
13
+ # create a new project in my-app
14
+ npm create svelte@latest my-app
15
+ ```
16
+
17
+ ## Developing
18
+
19
+ Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
20
+
21
+ ```bash
22
+ npm run dev
23
+
24
+ # or start the server and open the app in a new browser tab
25
+ npm run dev -- --open
26
+ ```
27
+
28
+ ## Building
29
+
30
+ To create a production version of your app:
31
+
32
+ ```bash
33
+ npm run build
34
+ ```
35
+
36
+ You can preview the production build with `npm run preview`.
37
+
38
+ > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
frontend/package.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "frontend",
3
+ "version": "0.0.1",
4
+ "scripts": {
5
+ "dev": "NODE_ENV=development vite --config vite.config.dev.ts dev",
6
+ "build-dev": "vite build --mode development",
7
+ "build": "vite build",
8
+ "preview": "vite preview",
9
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
10
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
11
+ "lint": "prettier --check . && eslint .",
12
+ "format": "prettier --write ."
13
+ },
14
+ "devDependencies": {
15
+ "@sveltejs/adapter-static": "^1.0.0-next.43",
16
+ "@sveltejs/kit": "next",
17
+ "@tailwindcss/forms": "^0.5.3",
18
+ "@tailwindcss/line-clamp": "^0.4.2",
19
+ "@types/cookie": "^0.5.1",
20
+ "@types/d3-color": "^3.1.0",
21
+ "@typescript-eslint/eslint-plugin": "^5.27.0",
22
+ "@typescript-eslint/parser": "^5.27.0",
23
+ "autoprefixer": "^10.4.11",
24
+ "d3-color": "^3.1.0",
25
+ "eslint": "^8.16.0",
26
+ "eslint-config-prettier": "^8.3.0",
27
+ "eslint-plugin-svelte3": "^4.0.0",
28
+ "postcss": "^8.4.16",
29
+ "prettier": "^2.6.2",
30
+ "prettier-plugin-svelte": "^2.7.0",
31
+ "svelte": "^3.46.0",
32
+ "svelte-check": "^2.7.1",
33
+ "svelte-preprocess": "^4.10.7",
34
+ "tailwindcss": "^3.1.8",
35
+ "tslib": "^2.3.1",
36
+ "typescript": "^4.7.4",
37
+ "vite": "^3.1.0"
38
+ },
39
+ "type": "module",
40
+ "dependencies": {
41
+ "@fontsource/fira-mono": "^4.5.0",
42
+ "quantize": "^1.0.2",
43
+ "scroll-into-view-if-needed": "^2.2.29"
44
+ }
45
+ }
frontend/postcss.config.cjs ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ }
frontend/src/app.css ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
frontend/src/app.d.ts ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // See https://kit.svelte.dev/docs/types#app
2
+ // for information about these interfaces
3
+ // and what to do when importing types
4
+
5
+ declare global {
6
+ namespace App {
7
+ // interface Locals {}
8
+ // interface PageData {}
9
+ // interface PageError {}
10
+ // interface Platform {}
11
+ interface Window {
12
+ parentIFrame: unknown;
13
+ }
14
+ }
15
+ }
frontend/src/app.html ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <link rel="icon" href="%sveltekit.assets%/favicon.png" />
6
+ <meta name="viewport" content="width=device-width" />
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script>
8
+ %sveltekit.head%
9
+ </head>
10
+ <body class="dark:bg-[rgb(11,15,25)] bg-white dark:text-white text-black">
11
+ <div>%sveltekit.body%</div>
12
+ </body>
13
+ </html>
frontend/src/lib/ArrowLeft.svelte ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <svg
2
+ class="mr-1.5"
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ xmlns:xlink="http://www.w3.org/1999/xlink"
5
+ aria-hidden="true"
6
+ focusable="false"
7
+ role="img"
8
+ width="1em"
9
+ height="1em"
10
+ preserveAspectRatio="xMidYMid meet"
11
+ viewBox="0 0 32 32"
12
+ ><path d="M10 16L20 6l1.4 1.4l-8.6 8.6l8.6 8.6L20 26z" fill="currentColor" /></svg
13
+ >
frontend/src/lib/ArrowRight.svelte ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <svg
2
+ class="ml-1.5 transform rotate-180"
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ xmlns:xlink="http://www.w3.org/1999/xlink"
5
+ aria-hidden="true"
6
+ focusable="false"
7
+ role="img"
8
+ width="1em"
9
+ height="1em"
10
+ preserveAspectRatio="xMidYMid meet"
11
+ viewBox="0 0 32 32"
12
+ ><path d="M10 16L20 6l1.4 1.4l-8.6 8.6l8.6 8.6L20 26z" fill="currentColor" /></svg
13
+ >
frontend/src/lib/ColorPalette.svelte ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import type { Color } from 'd3-color';
3
+ import * as d3 from 'd3-color';
4
+
5
+ export let colors: Color[];
6
+ const n = colors.length;
7
+ function getLabelColor(c: Color): string {
8
+ const color = d3.hcl(c);
9
+ if (color.l > 50) {
10
+ return d3.hcl(color.h, color.c, 0).formatHex();
11
+ }
12
+ return d3.hcl(color.h, color.c, 100).formatHex();
13
+ }
14
+ let isCopying = -1;
15
+
16
+ async function copyStringToClipboard(text: string, n: number) {
17
+ // usingo Clipboard API
18
+ if (isCopying > -1) return;
19
+ isCopying = n;
20
+ // await navigator.permissions.query({ name: 'clipboard-write' });
21
+ await navigator.clipboard.write([
22
+ new ClipboardItem({ 'text/plain': new Blob([text], { type: 'text/plain' }) })
23
+ ]);
24
+ setTimeout(() => {
25
+ isCopying = -1;
26
+ }, 800);
27
+ }
28
+ </script>
29
+
30
+ <div class="flex flex-col items-center">
31
+ <div class="flex">
32
+ {#each colors as color, i}
33
+ <div
34
+ class="{isCopying === i ? '' : 'cursor-pointer'} aspect-square relative"
35
+ style="background-color: {color.formatHex()}"
36
+ on:click={() => copyStringToClipboard(color.formatHex(), i)}
37
+ >
38
+ <svg class="block max-w-full aspect-square" width="100" viewBox="0 0 50 50">
39
+ <rect x="0" y="0" width="50" height="50" fill={color.formatHex()} />
40
+ </svg>
41
+ <span
42
+ title="Copy single color"
43
+ class="absolute bottom-0 text-center text-xs pl-1 font-bold uppercase"
44
+ style="color:{getLabelColor(color)}"
45
+ >{isCopying === i ? 'copied' : color.formatHex()}</span
46
+ >
47
+ </div>
48
+ {/each}
49
+ </div>
50
+ </div>
frontend/src/lib/Palette.svelte ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import * as d3 from 'd3-color';
3
+ import { createEventDispatcher } from 'svelte';
4
+ import type { ColorsPrompt } from '$lib/types';
5
+ import ColorPalette from '$lib/ColorPalette.svelte';
6
+
7
+ const dispatch = createEventDispatcher();
8
+
9
+ export let promptData: ColorsPrompt;
10
+
11
+ let seletecdImage = 0;
12
+
13
+ $: prompt = promptData?.prompt;
14
+ $: colors = promptData?.images[seletecdImage]?.colors.map((e) => d3.rgb(e)) || [];
15
+ $: imageSrc = promptData?.images[seletecdImage]?.imgURL;
16
+ let isCopying = false;
17
+
18
+ async function copyStringToClipboard(text: string) {
19
+ // usingo Clipboard API
20
+ if (isCopying) return;
21
+ isCopying = true;
22
+ // await navigator.permissions.query({ name: 'clipboard-write' });
23
+ await navigator.clipboard.write([
24
+ new ClipboardItem({ 'text/plain': new Blob([text], { type: 'text/plain' }) })
25
+ ]);
26
+ setTimeout(() => {
27
+ isCopying = false;
28
+ }, 1000);
29
+ }
30
+ </script>
31
+
32
+ <div class="grid grid-cols-6 gap-3">
33
+ <blockquote
34
+ class="row-start-1 mx-auto col-span-6 italic font-semibold max-w-prose text-base text-center line-clamp-3 my-3"
35
+ title={prompt}
36
+ >
37
+ <p>{prompt}</p>
38
+ </blockquote>
39
+ <div class="row-start-3 md:row-start-2 col-span-6 md:col-span-4 flex items-center justify-center">
40
+ {#if colors}
41
+ <ColorPalette {colors} />
42
+ {/if}
43
+ </div>
44
+ <div class="row-start-2 col-span-6 md:col-span-2 flex justify-center md:justify-end pb-3">
45
+ <div class="relative">
46
+ <img
47
+ loading="lazy"
48
+ class="relative max-w-[100px] w-full aspect-square"
49
+ src={imageSrc}
50
+ alt={prompt}
51
+ />
52
+ <div class="absolute flex justify-around w-full">
53
+ {#each promptData.images as image, i}
54
+ <button
55
+ class="{seletecdImage === i
56
+ ? 'bg-black dark:bg-white'
57
+ : 'bg-white dark:bg-black'} dark:bg-slate-300 rounded-full h-3 w-3 m-1 border border-black dark:border-white"
58
+ on:click={() => (seletecdImage = i)}
59
+ on:mousemove={() => (seletecdImage = i)}
60
+ />
61
+ {/each}
62
+ </div>
63
+ </div>
64
+ </div>
65
+ <div
66
+ class="row-start-4 col-span-6 md:col-span-2 md:col-start-5 flex justify-center md:justify-end"
67
+ >
68
+ <div class="flex justify-center items-center">
69
+ <button
70
+ class="button"
71
+ title="Send this prompt to input so you can remix it"
72
+ on:click={() => dispatch('remix', { prompt })}
73
+ >
74
+ Remix
75
+ </button>
76
+ <button
77
+ class="button"
78
+ title="Copy all colors to clipboard"
79
+ disabled={isCopying}
80
+ on:click={() => copyStringToClipboard(colors.map((color) => color.formatHex()).join(', '))}
81
+ >
82
+ {isCopying ? 'Copied' : 'Copy'}
83
+ </button>
84
+ </div>
85
+ </div>
86
+ </div>
87
+
88
+ <style lang="postcss" scoped>
89
+ .button {
90
+ @apply min-w-[9ch] bg-black text-white border-2 dark:border-white border-black rounded-2xl ml-2 px-2 py-2 shadow-sm text-xs font-bold focus:outline-none focus:border-gray-400;
91
+ }
92
+ </style>
frontend/src/lib/store.ts ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ import { writable } from 'svelte/store';
2
+ export const loadingState = writable<string>('');
3
+ export const isLoading = writable<boolean>(false);
frontend/src/lib/types.ts ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Color } from 'd3-color';
2
+
3
+ export interface ColorsImage {
4
+ colors: Color[];
5
+ imgURL: string;
6
+ }
7
+ export interface ColorsPrompt {
8
+ prompt: string;
9
+ images: ColorsImage[];
10
+ }
11
+
12
+ export interface LoadingState {
13
+ loadingMessage: string;
14
+ isLoading: boolean;
15
+ }
frontend/src/lib/utils.ts ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import quantize from 'quantize';
2
+ import * as d3 from 'd3-color';
3
+ import type { Color } from 'd3-color';
4
+ import { dev } from '$app/environment';
5
+
6
+ export function randomSeed() {
7
+ return BigInt(13248873089935215612 & (((1 << 63) - 1) * Math.random()));
8
+ }
9
+
10
+ function sortColors(colors: Color[]): Color[] {
11
+ const reverse = true;
12
+ return colors
13
+ .map((color) => d3.hcl(color))
14
+ .sort((a, b) => {
15
+ const aa = a.h;
16
+ const bb = b.h;
17
+
18
+ return !reverse ? aa - bb || isNaN(aa) - isNaN(bb) : bb - aa || isNaN(bb) - isNaN(aa);
19
+ });
20
+ }
21
+
22
+ function createPixelArray(imgData: Uint8ClampedArray, pixelCount: number, quality: number) {
23
+ // from https://github.com/lokesh/color-thief
24
+ const pixels = imgData;
25
+ const pixelArray = [];
26
+
27
+ for (let i = 0, offset, r, g, b, a; i < pixelCount; i = i + quality) {
28
+ offset = i * 4;
29
+ r = pixels[offset + 0];
30
+ g = pixels[offset + 1];
31
+ b = pixels[offset + 2];
32
+ a = pixels[offset + 3];
33
+
34
+ // If pixel is mostly opaque and not white
35
+ if (typeof a === 'undefined' || a >= 125) {
36
+ if (!(r > 250 && g > 250 && b > 250)) {
37
+ pixelArray.push([r, g, b]);
38
+ }
39
+ }
40
+ }
41
+ return pixelArray;
42
+ }
43
+
44
+ export function extractPalette(
45
+ base64image: string,
46
+ colorCount = 5,
47
+ quality = 1
48
+ ): Promise<{ colors: Color[]; imgBlob: Blob }> {
49
+ return new Promise((resolve) => {
50
+ const img = new Image();
51
+ img.onload = async () => {
52
+ const w = img.width;
53
+ const h = img.height;
54
+ const canvas = document.createElement('canvas');
55
+ canvas.width = w;
56
+ canvas.height = h;
57
+ const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
58
+ ctx.drawImage(img, 0, 0, w, h);
59
+ const imageData = ctx.getImageData(0, 0, w, h);
60
+ const pixelArray = createPixelArray(imageData.data, w * h, quality);
61
+ const cmap = quantize(pixelArray, colorCount);
62
+ const colors: number[][] = cmap.palette();
63
+ const tempCanvas = document.createElement('canvas');
64
+ tempCanvas.width = w / 5;
65
+ tempCanvas.height = h / 5;
66
+ const tempCtx = tempCanvas.getContext('2d') as CanvasRenderingContext2D;
67
+ tempCtx.drawImage(img, 0, 0, w, h, 0, 0, w / 5, h / 5);
68
+
69
+ const imgBlob: Blob = await new Promise((_resolve) =>
70
+ tempCanvas.toBlob(_resolve, 'image/jpeg', 0.8)
71
+ );
72
+ const colorsRGB = colors.map((color) => d3.rgb(...(color as [number, number, number])));
73
+ resolve({
74
+ colors: sortColors(colorsRGB),
75
+ imgBlob
76
+ });
77
+ };
78
+ img.src = base64image;
79
+ });
80
+ }
81
+
82
+ export async function uploadImage(imagBlob: Blob, prompt: string): string {
83
+ // simple regex slugify string for file name
84
+ const promptSlug = slugify(prompt);
85
+ const UPLOAD_URL = dev ? 'moon/uploads' : 'https://huggingface.co/uploads';
86
+
87
+ const hash = crypto.randomUUID().split('-')[0];
88
+ const fileName = `color-palette-${hash}-${promptSlug}.jpeg`;
89
+
90
+ const file = new File([imagBlob], fileName, { type: 'image/jpeg' });
91
+
92
+ console.log('uploading image', file);
93
+
94
+ const response = await fetch(UPLOAD_URL, {
95
+ method: 'POST',
96
+ headers: {
97
+ 'Content-Type': file.type,
98
+ 'X-Requested-With': 'XMLHttpRequest'
99
+ },
100
+ body: file /// <- File inherits from Blob
101
+ });
102
+ const url = await response.text();
103
+
104
+ console.log('uploaded images', url);
105
+ return url;
106
+ }
107
+
108
+ function slugify(text: string) {
109
+ if (!text) return '';
110
+ return text
111
+ .toString()
112
+ .toLowerCase()
113
+ .replace(/\s+/g, '-')
114
+ .replace(/[^\w\-]+/g, '')
115
+ .replace(/\-\-+/g, '-')
116
+ .replace(/^-+/, '')
117
+ .replace(/-+$/, '');
118
+ }
frontend/src/routes/+layout.svelte ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ <script>
2
+ import '../app.css';
3
+ </script>
4
+
5
+ <slot />
frontend/src/routes/+layout.ts ADDED
@@ -0,0 +1 @@
 
 
1
+ export const prerender = true;
frontend/src/routes/+page.svelte ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import type { ColorsPrompt, ColorsImage } from '$lib/types';
4
+ import { randomSeed, extractPalette, uploadImage } from '$lib/utils';
5
+ import { isLoading, loadingState } from '$lib/store';
6
+ import { PUBLIC_WS_ENDPOINT, PUBLIC_API} from '$env/static/public';
7
+ import Pallette from '$lib/Palette.svelte';
8
+ import ArrowRight from '$lib/ArrowRight.svelte';
9
+ import ArrowLeft from '$lib/ArrowLeft.svelte';
10
+
11
+ let promptsData: ColorsPrompt[] = [];
12
+ let prompt: string;
13
+ let promptInputEl: HTMLElement;
14
+
15
+ onMount(() => {
16
+ fetchData();
17
+ const interval = window.setInterval(fetchData, 5000);
18
+ return () => {
19
+ clearInterval(interval);
20
+ };
21
+ });
22
+
23
+ async function fetchData() {
24
+ const palettes = await fetch(PUBLIC_API + '/data').then((d) => d.json());
25
+ if (!promptsData || palettes?.length > promptsData?.length) {
26
+ promptsData = sortData(palettes);
27
+ }
28
+ }
29
+
30
+ $: promptsTotal = promptsData?.length || null;
31
+
32
+ let page: number = 0;
33
+ const maxPerPage: number = 10;
34
+ $: totalPages = Math.ceil(promptsData?.length / maxPerPage) || 0;
35
+ $: promptsDataPage = [...promptsData].slice(page * maxPerPage, (page + 1) * maxPerPage);
36
+ let pagesLinks: number[] = [];
37
+ $: if (totalPages) {
38
+ const pagesNums = Array(totalPages)
39
+ .fill([])
40
+ .map((_, i) => ({ value: i, label: i + 1 }));
41
+ pagesLinks = pagesNums
42
+ .slice(0, 3)
43
+ .concat([{ value: -1, label: '...' }])
44
+ .concat(pagesNums.length > 3 ? pagesNums.slice(-1) : []);
45
+ console.log(pagesLinks);
46
+ }
47
+
48
+ function sortData(_promptData: ColorsPrompt[]) {
49
+ return _promptData
50
+ .sort((a, b) => b.id - a.id)
51
+ .map((p) => p.data)
52
+ .filter((d) => d.images.length > 0);
53
+ }
54
+ async function savePaletteDB(colorPrompt: ColorsPrompt) {
55
+ try {
56
+ const newPalettes: ColorsPrompt[] = await fetch(PUBLIC_API + '/new_palette', {
57
+ method: 'POST',
58
+ headers: {
59
+ 'Content-Type': 'application/json'
60
+ },
61
+ body: JSON.stringify({
62
+ prompt: colorPrompt.prompt,
63
+ images: colorPrompt.images.map((i) => ({
64
+ imgURL: i.imgURL,
65
+ colors: i.colors.map((c) => c.formatHex())
66
+ }))
67
+ })
68
+ }).then((d) => d.json());
69
+
70
+ promptsData = sortData(newPalettes);
71
+ } catch (e) {
72
+ console.error(e);
73
+ }
74
+ }
75
+
76
+ async function generatePalette(_prompt: string) {
77
+ if (!_prompt || $isLoading == true) return;
78
+ $loadingState = 'Pending';
79
+ $isLoading = true;
80
+
81
+ const sessionHash = crypto.randomUUID();
82
+
83
+ const hashpayload = {
84
+ fn_index: 2,
85
+ session_hash: sessionHash
86
+ };
87
+
88
+ const datapayload = {
89
+ data: [_prompt]
90
+ };
91
+
92
+ const websocket = new WebSocket(PUBLIC_WS_ENDPOINT);
93
+ // websocket.onopen = async function (event) {
94
+ // websocket.send(JSON.stringify({ hash: sessionHash }));
95
+ // };
96
+ websocket.onclose = (evt) => {
97
+ if (!evt.wasClean) {
98
+ $loadingState = 'Error';
99
+ $isLoading = false;
100
+ }
101
+ };
102
+ websocket.onmessage = async function (event) {
103
+ try {
104
+ const data = JSON.parse(event.data);
105
+ $loadingState = '';
106
+ switch (data.msg) {
107
+ case 'send_hash':
108
+ websocket.send(JSON.stringify(hashpayload));
109
+ break;
110
+ case 'send_data':
111
+ $loadingState = 'Sending Data';
112
+ websocket.send(JSON.stringify({ ...hashpayload, ...datapayload }));
113
+ break;
114
+ case 'queue_full':
115
+ $loadingState = 'Queue full';
116
+ websocket.close();
117
+ $isLoading = false;
118
+ return;
119
+ case 'estimation':
120
+ const { msg, rank, queue_size } = data;
121
+ $loadingState = `On queue ${rank}/${queue_size}`;
122
+ break;
123
+ case 'process_generating':
124
+ $loadingState = data.success ? 'Generating' : 'Error';
125
+ break;
126
+ case 'process_completed':
127
+ try {
128
+ const images = await extractColorsImages(data.output.data[0], _prompt);
129
+ savePaletteDB({
130
+ prompt: _prompt,
131
+ images
132
+ });
133
+ $loadingState = data.success ? 'Complete' : 'Error';
134
+ } catch (e) {
135
+ $loadingState = e.message;
136
+ }
137
+ websocket.close();
138
+ $isLoading = false;
139
+ return;
140
+ case 'process_starts':
141
+ $loadingState = 'Processing';
142
+ break;
143
+ }
144
+ } catch (e) {
145
+ console.error(e);
146
+ $isLoading = false;
147
+ $loadingState = 'Error';
148
+ }
149
+ };
150
+ }
151
+ async function extractColorsImages(images: string[], _prompt: string): Promise<ColorsImage[]> {
152
+ const nsfwColors = ['#040404', '#B7B7B7', '#565656', '#747474', '#6C6C6C'];
153
+
154
+ const colorImages = [];
155
+ let isNSFW = false;
156
+ for (const base64img of images) {
157
+ const { colors, imgBlob } = await extractPalette(base64img);
158
+ if (
159
+ !colors.map((color) => color.formatHex().toUpperCase()).every((c) => nsfwColors.includes(c))
160
+ ) {
161
+ const url = await uploadImage(imgBlob, _prompt);
162
+ const colorsImage: ColorsImage = {
163
+ colors,
164
+ imgURL: url
165
+ };
166
+ colorImages.push(colorsImage);
167
+ } else {
168
+ isNSFW = true;
169
+ }
170
+ }
171
+
172
+ if (colorImages.length === 0 && isNSFW) {
173
+ console.error('Possible NSFW image');
174
+ throw new Error('Possible NSFW image');
175
+ }
176
+ return colorImages;
177
+ }
178
+ function remix(e: CustomEvent) {
179
+ prompt = e.detail.prompt;
180
+ promptInputEl.scrollIntoView({ behavior: 'smooth' });
181
+ scrollTop();
182
+ }
183
+ function scrollTop() {
184
+ window.scrollTo(0, 0);
185
+ if ('parentIFrame' in window) {
186
+ window.parentIFrame.scrollTo(0, promptInputEl.offsetTop);
187
+ }
188
+ }
189
+ </script>
190
+
191
+ <div class="max-w-screen-md mx-auto px-3 py-8 relative z-0">
192
+ <h1 class="text-3xl font-bold leading-normal">Palette generation with Stable Diffusion</h1>
193
+ <p class="text-sm">
194
+ Original ideas:
195
+
196
+ <a
197
+ class="link"
198
+ target="_blank"
199
+ rel="nofollow noopener"
200
+ href="https://twitter.com/mattdesl/status/1569457653298139136"
201
+ >
202
+ Matt DesLauriers
203
+ </a>,
204
+ <a class="link" href="https://drib.net/homage"> dribnet </a>
205
+ </p>
206
+ <div class="relative top-0 z-50 bg-white dark:bg-black py-3">
207
+ <form class="grid grid-cols-6" on:submit|preventDefault={() => generatePalette(prompt)}>
208
+ <input
209
+ bind:this={promptInputEl}
210
+ class="input"
211
+ placeholder="A photo of a beautiful sunset in San Francisco"
212
+ title="Input prompt to generate image and obtain palette"
213
+ type="text"
214
+ name="prompt"
215
+ bind:value={prompt}
216
+ disabled={$isLoading}
217
+ />
218
+ <button
219
+ class="button"
220
+ on:click|preventDefault={() => generatePalette(prompt)}
221
+ disabled={$isLoading}
222
+ title="Generate Palette"
223
+ >
224
+ Create Palette
225
+ </button>
226
+ </form>
227
+ {#if $loadingState}
228
+ <h3 class="text-xs font-bold ml-3 inline-block">{$loadingState}</h3>
229
+ {#if $isLoading}
230
+ <svg
231
+ xmlns="http://www.w3.org/2000/svg"
232
+ fill="none"
233
+ viewBox="0 0 24 24"
234
+ class="animate-spin max-w-[1rem] inline-block"
235
+ >
236
+ <path
237
+ fill="currentColor"
238
+ d="M20 12a8 8 0 0 1-8 8v4a12 12 0 0 0 12-12h-4Zm-2-5.3a8 8 0 0 1 2 5.3h4c0-3-1.1-5.8-3-8l-3 2.7Z"
239
+ />
240
+ </svg>
241
+ {/if}
242
+ {/if}
243
+ </div>
244
+
245
+ <div class="flex items-center gap-4 my-10">
246
+ <div class="font-bold text-sm">
247
+ {promptsTotal ? `${promptsTotal} submitted palettes` : 'Loading...'}
248
+ </div>
249
+ <div class="grow border-b border-gray-200" />
250
+ </div>
251
+
252
+ {#if promptsDataPage}
253
+ <div>
254
+ {#each promptsDataPage as promptData}
255
+ <Pallette {promptData} on:remix={remix} />
256
+ <div class="border-b border-gray-200 py-2" />
257
+ {/each}
258
+ </div>
259
+ <nav role="navigation">
260
+ <ul
261
+ class="items-center sm:justify-center space-x-2 select-none w-full flex justify-center mt-6 mb-4"
262
+ >
263
+ <li />
264
+ <li>
265
+ <a
266
+ on:click|preventDefault={() => {
267
+ page = page - 1 < 0 ? 0 : page - 1;
268
+ scrollTop();
269
+ }}
270
+ class="px-2.5 py-1 hover:bg-gray-50 dark:hover:bg-gray-800 flex items-center rounded-lg"
271
+ href="#"
272
+ ><ArrowLeft /> Previous
273
+ </a>
274
+ </li>
275
+ <li class="text-sm">
276
+ <span class="inline-block min-w-[3ch] text-right">{page + 1} </span>/<span
277
+ class="inline-block min-w-[3ch]"
278
+ >{totalPages}
279
+ </span>
280
+ </li>
281
+ <li>
282
+ <a
283
+ on:click|preventDefault={() => {
284
+ page = page + 1 >= totalPages - 1 ? totalPages - 1 : page + 1;
285
+ scrollTop();
286
+ }}
287
+ class="px-2.5 py-1 hover:bg-gray-50 dark:hover:bg-gray-800 flex items-center rounded-lg"
288
+ href="#"
289
+ >Next <ArrowRight />
290
+ </a>
291
+ </li>
292
+ </ul>
293
+ </nav>
294
+ {/if}
295
+ </div>
296
+
297
+ <style lang="postcss" scoped>
298
+ .link {
299
+ @apply text-xs underline font-bold hover:no-underline hover:text-gray-500 visited:text-gray-500;
300
+ }
301
+ .input {
302
+ @apply text-sm disabled:opacity-50 col-span-4 md:col-span-5 italic dark:placeholder:text-black placeholder:text-white text-white dark:text-black placeholder:text-opacity-30 dark:placeholder:text-opacity-10 dark:bg-white bg-slate-900 border-2 border-black rounded-2xl px-2 shadow-sm focus:outline-none focus:border-gray-400 focus:ring-1;
303
+ }
304
+ .button {
305
+ @apply disabled:opacity-50 col-span-2 md:col-span-1 dark:bg-white dark:text-black border-2 border-black rounded-2xl ml-2 px-2 py-2 text-xs shadow-sm font-bold focus:outline-none focus:border-gray-400;
306
+ }
307
+ </style>
frontend/static/favicon.png ADDED
frontend/static/robots.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # https://www.robotstxt.org/robotstxt.html
2
+ User-agent: *
3
+ Disallow:
frontend/static/svelte-welcome.png ADDED
frontend/static/svelte-welcome.webp ADDED
frontend/svelte.config.js ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import adapter from '@sveltejs/adapter-static';
2
+ import preprocess from 'svelte-preprocess';
3
+
4
+ const dev = process.env.NODE_ENV === 'development';
5
+ console.log(dev)
6
+ /** @type {import('@sveltejs/kit').Config} */
7
+ const config = {
8
+ preprocess: [
9
+ preprocess({
10
+ postcss: true
11
+ })
12
+ ],
13
+ kit: {
14
+ paths: {
15
+ base: '/static'
16
+ },
17
+ adapter: adapter({
18
+ pages: 'build',
19
+ assets: 'build',
20
+ fallback: null,
21
+ precompress: false
22
+ })
23
+ }
24
+ };
25
+
26
+ export default config;
frontend/tailwind.config.cjs ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ content: ['./src/**/*.{html,js,svelte,ts}'],
4
+ theme: {},
5
+ plugins: [require('@tailwindcss/forms'), require('@tailwindcss/line-clamp')]
6
+ };
frontend/tsconfig.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "extends": "./.svelte-kit/tsconfig.json",
3
+ "compilerOptions": {
4
+ "allowJs": true,
5
+ "checkJs": true,
6
+ "esModuleInterop": true,
7
+ "forceConsistentCasingInFileNames": true,
8
+ "resolveJsonModule": true,
9
+ "skipLibCheck": true,
10
+ "sourceMap": true,
11
+ "strict": true
12
+ }
13
+ // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
14
+ //
15
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
16
+ // from the referenced tsconfig.json - TypeScript does not merge them in
17
+ }
frontend/vite.config.dev.ts ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { sveltekit } from '@sveltejs/kit/vite';
2
+ import type { UserConfig } from 'vite';
3
+
4
+ const config: UserConfig = {
5
+ plugins: [sveltekit()],
6
+ server: {
7
+ proxy: {
8
+ '/moon': {
9
+ target: 'https://huggingface.co',
10
+ changeOrigin: true,
11
+ cookieDomainRewrite: 'localhost',
12
+ rewrite: (path) => path.replace(/^\/moon/, '')
13
+ }
14
+ }
15
+ }
16
+ };
17
+
18
+ export default config;
frontend/vite.config.ts ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import { sveltekit } from '@sveltejs/kit/vite';
2
+ import type { UserConfig } from 'vite';
3
+
4
+ const config: UserConfig = {
5
+ plugins: [sveltekit()]
6
+ };
7
+
8
+ export default config;
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ datasets
2
+ flask
3
+ flask_cors
4
+ flask_expects_json
5
+ requests
6
+ Pillow
7
+ gradio
8
+ Flask-APScheduler
run.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ import subprocess
2
+
3
+ subprocess.run(["make", "build-all"], shell=False)
static/_app/immutable/assets/_layout-e397cbf6.css ADDED
@@ -0,0 +1 @@
 
 
1
+ *,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[type=text],[type=email],[type=url],[type=password],[type=number],[type=date],[type=datetime-local],[type=month],[type=search],[type=tel],[type=time],[type=week],[multiple],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow: 0 0 #0000}[type=text]:focus,[type=email]:focus,[type=url]:focus,[type=password]:focus,[type=number]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=month]:focus,[type=search]:focus,[type=tel]:focus,[type=time]:focus,[type=week]:focus,[multiple]:focus,textarea:focus,select:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:initial;background-position:initial;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow: 0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 2px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}[type=radio]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")}[type=checkbox]:checked:hover,[type=checkbox]:checked:focus,[type=radio]:checked:hover,[type=radio]:checked:focus{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:indeterminate:hover,[type=checkbox]:indeterminate:focus{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::-webkit-backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.absolute{position:absolute}.relative{position:relative}.bottom-0{bottom:0px}.top-0{top:0px}.z-0{z-index:0}.z-50{z-index:50}.col-span-6{grid-column:span 6 / span 6}.col-span-4{grid-column:span 4 / span 4}.col-span-2{grid-column:span 2 / span 2}.row-start-1{grid-row-start:1}.row-start-3{grid-row-start:3}.row-start-2{grid-row-start:2}.row-start-4{grid-row-start:4}.m-1{margin:.25rem}.mx-auto{margin-left:auto;margin-right:auto}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.mr-1\.5{margin-right:.375rem}.mr-1{margin-right:.25rem}.ml-1\.5{margin-left:.375rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.mt-6{margin-top:1.5rem}.mb-4{margin-bottom:1rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.grid{display:grid}.aspect-square{aspect-ratio:1 / 1}.h-3{height:.75rem}.w-full{width:100%}.w-3{width:.75rem}.min-w-\[9ch\]{min-width:9ch}.min-w-\[3ch\]{min-width:3ch}.max-w-full{max-width:100%}.max-w-prose{max-width:65ch}.max-w-\[100px\]{max-width:100px}.max-w-screen-md{max-width:768px}.max-w-\[1rem\]{max-width:1rem}.grow{flex-grow:1}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@-webkit-keyframes spin{to{transform:rotate(360deg)}}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-around{justify-content:space-around}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(.5rem * var(--tw-space-x-reverse));margin-left:calc(.5rem * calc(1 - var(--tw-space-x-reverse)))}.rounded-full{border-radius:9999px}.rounded-2xl{border-radius:1rem}.rounded-lg{border-radius:.5rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-black{--tw-border-opacity: 1;border-color:rgb(0 0 0 / var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity))}.bg-slate-900{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity))}.px-2{padding-left:.5rem;padding-right:.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.pl-1{padding-left:.25rem}.pb-3{padding-bottom:.75rem}.text-center{text-align:center}.text-right{text-align:right}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-sm{font-size:.875rem;line-height:1.25rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-normal{line-height:1.5}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.underline{text-decoration-line:underline}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.line-clamp-3{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3}.placeholder\:text-white::-moz-placeholder{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.placeholder\:text-white::placeholder{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.placeholder\:text-opacity-30::-moz-placeholder{--tw-text-opacity: .3}.placeholder\:text-opacity-30::placeholder{--tw-text-opacity: .3}.hover\:bg-gray-50:hover{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity))}.hover\:text-gray-500:hover{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.hover\:no-underline:hover{text-decoration-line:none}.focus\:border-gray-400:focus{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.disabled\:opacity-50:disabled{opacity:.5}@media (prefers-color-scheme: dark){.dark\:border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity))}.dark\:bg-\[rgb\(11\,15\,25\)\]{--tw-bg-opacity: 1;background-color:rgb(11 15 25 / var(--tw-bg-opacity))}.dark\:bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.dark\:bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity))}.dark\:bg-slate-300{--tw-bg-opacity: 1;background-color:rgb(203 213 225 / var(--tw-bg-opacity))}.dark\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.dark\:text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.dark\:placeholder\:text-black::-moz-placeholder{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.dark\:placeholder\:text-black::placeholder{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.dark\:placeholder\:text-opacity-10::-moz-placeholder{--tw-text-opacity: .1}.dark\:placeholder\:text-opacity-10::placeholder{--tw-text-opacity: .1}.dark\:hover\:bg-gray-800:hover{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity))}}@media (min-width: 640px){.sm\:justify-center{justify-content:center}}@media (min-width: 768px){.md\:col-span-4{grid-column:span 4 / span 4}.md\:col-span-2{grid-column:span 2 / span 2}.md\:col-span-5{grid-column:span 5 / span 5}.md\:col-span-1{grid-column:span 1 / span 1}.md\:col-start-5{grid-column-start:5}.md\:row-start-2{grid-row-start:2}.md\:justify-end{justify-content:flex-end}}
static/_app/immutable/assets/_page-fd1176fc.css ADDED
@@ -0,0 +1 @@
 
 
1
+ .button.svelte-8zu88a{margin-left:.5rem;min-width:9ch;border-radius:1rem;border-width:2px;--tw-border-opacity:1;border-color:rgb(0 0 0 / var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(0 0 0 / var(--tw-bg-opacity));padding:.5rem;font-size:.75rem;line-height:1rem;font-weight:700;--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity));--tw-shadow:0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.button.svelte-8zu88a:focus{--tw-border-opacity:1;border-color:rgb(156 163 175 / var(--tw-border-opacity));outline:2px solid transparent;outline-offset:2px}@media (prefers-color-scheme: dark){.button.svelte-8zu88a{--tw-border-opacity:1;border-color:rgb(255 255 255 / var(--tw-border-opacity))}}.link.svelte-zbscw1{font-size:.75rem;line-height:1rem;font-weight:700;text-decoration-line:underline}.link.svelte-zbscw1:visited{color:#6b7280}.link.svelte-zbscw1:hover{--tw-text-opacity:1;color:rgb(107 114 128 / var(--tw-text-opacity));text-decoration-line:none}.input.svelte-zbscw1{grid-column:span 4 / span 4;border-radius:1rem;border-width:2px;--tw-border-opacity:1;border-color:rgb(0 0 0 / var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(15 23 42 / var(--tw-bg-opacity));padding-left:.5rem;padding-right:.5rem;font-size:.875rem;line-height:1.25rem;font-style:italic;--tw-text-opacity:1;color:rgb(255 255 255 / var(--tw-text-opacity));--tw-shadow:0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.input.svelte-zbscw1::-moz-placeholder{color:rgb(255 255 255 / var(--tw-text-opacity));--tw-text-opacity:.3 }.input.svelte-zbscw1::placeholder{color:rgb(255 255 255 / var(--tw-text-opacity));--tw-text-opacity:.3 }.input.svelte-zbscw1:focus{--tw-border-opacity:1;border-color:rgb(156 163 175 / var(--tw-border-opacity));outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.input.svelte-zbscw1:disabled{opacity:.5}@media (prefers-color-scheme: dark){.input.svelte-zbscw1{--tw-bg-opacity:1;background-color:rgb(255 255 255 / var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(0 0 0 / var(--tw-text-opacity))}.input.svelte-zbscw1::-moz-placeholder{color:rgb(0 0 0 / var(--tw-text-opacity));--tw-text-opacity:.1 }.input.svelte-zbscw1::placeholder{color:rgb(0 0 0 / var(--tw-text-opacity));--tw-text-opacity:.1 }}@media (min-width: 768px){.input.svelte-zbscw1{grid-column:span 5 / span 5}}.button.svelte-zbscw1{grid-column:span 2 / span 2;margin-left:.5rem;border-radius:1rem;border-width:2px;--tw-border-opacity:1;border-color:rgb(0 0 0 / var(--tw-border-opacity));padding:.5rem;font-size:.75rem;line-height:1rem;font-weight:700;--tw-shadow:0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.button.svelte-zbscw1:focus{--tw-border-opacity:1;border-color:rgb(156 163 175 / var(--tw-border-opacity));outline:2px solid transparent;outline-offset:2px}.button.svelte-zbscw1:disabled{opacity:.5}@media (prefers-color-scheme: dark){.button.svelte-zbscw1{--tw-bg-opacity:1;background-color:rgb(255 255 255 / var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(0 0 0 / var(--tw-text-opacity))}}@media (min-width: 768px){.button.svelte-zbscw1{grid-column:span 1 / span 1}}
static/_app/immutable/chunks/0-17a4fec1.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{_ as r}from"./_layout-1daba58d.js";import{default as t}from"../components/pages/_layout.svelte-55da5a4f.js";export{t as component,r as shared};
static/_app/immutable/chunks/1-26e94021.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{default as t}from"../components/error.svelte-c31c95c4.js";export{t as component};
static/_app/immutable/chunks/2-fc64cbc2.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{default as t}from"../components/pages/_page.svelte-3643b29c.js";export{t as component};
static/_app/immutable/chunks/_layout-1daba58d.js ADDED
@@ -0,0 +1 @@
 
 
1
+ const e=!0,r=Object.freeze(Object.defineProperty({__proto__:null,prerender:!0},Symbol.toStringTag,{value:"Module"}));export{r as _,e as p};
static/_app/immutable/chunks/index-3bda1050.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{A as f,s as l}from"./index-5559954d.js";const e=[];function h(n,u=f){let o;const i=new Set;function r(t){if(l(n,t)&&(n=t,o)){const c=!e.length;for(const s of i)s[1](),e.push(s,n);if(c){for(let s=0;s<e.length;s+=2)e[s][0](e[s+1]);e.length=0}}}function b(t){r(t(n))}function p(t,c=f){const s=[t,c];return i.add(s),i.size===1&&(o=u(r)||f),t(n),()=>{i.delete(s),i.size===0&&(o(),o=null)}}return{set:r,update:b,subscribe:p}}export{h as w};
static/_app/immutable/chunks/index-5559954d.js ADDED
@@ -0,0 +1 @@
 
 
1
+ function S(){}function H(t,n){for(const e in n)t[e]=n[e];return t}function B(t){return t()}function M(){return Object.create(null)}function p(t){t.forEach(B)}function I(t){return typeof t=="function"}function st(t,n){return t!=t?n==n:t!==n||t&&typeof t=="object"||typeof t=="function"}let g;function ot(t,n){return g||(g=document.createElement("a")),g.href=n,t===g.href}function G(t){return Object.keys(t).length===0}function J(t,...n){if(t==null)return S;const e=t.subscribe(...n);return e.unsubscribe?()=>e.unsubscribe():e}function at(t,n,e){t.$$.on_destroy.push(J(n,e))}function ft(t,n,e,i){if(t){const r=D(t,n,e,i);return t[0](r)}}function D(t,n,e,i){return t[1]&&i?H(e.ctx.slice(),t[1](i(n))):e.ctx}function _t(t,n,e,i){if(t[2]&&i){const r=t[2](i(e));if(n.dirty===void 0)return r;if(typeof r=="object"){const o=[],c=Math.max(n.dirty.length,r.length);for(let s=0;s<c;s+=1)o[s]=n.dirty[s]|r[s];return o}return n.dirty|r}return n.dirty}function dt(t,n,e,i,r,o){if(r){const c=D(n,e,i,o);t.p(c,r)}}function ht(t){if(t.ctx.length>32){const n=[],e=t.ctx.length/32;for(let i=0;i<e;i++)n[i]=-1;return n}return-1}function mt(t,n,e){return t.set(e),n}let $=!1;function K(){$=!0}function Q(){$=!1}function R(t,n,e,i){for(;t<n;){const r=t+(n-t>>1);e(r)<=i?t=r+1:n=r}return t}function W(t){if(t.hydrate_init)return;t.hydrate_init=!0;let n=t.childNodes;if(t.nodeName==="HEAD"){const u=[];for(let l=0;l<n.length;l++){const f=n[l];f.claim_order!==void 0&&u.push(f)}n=u}const e=new Int32Array(n.length+1),i=new Int32Array(n.length);e[0]=-1;let r=0;for(let u=0;u<n.length;u++){const l=n[u].claim_order,f=(r>0&&n[e[r]].claim_order<=l?r+1:R(1,r,y=>n[e[y]].claim_order,l))-1;i[u]=e[f]+1;const a=f+1;e[a]=u,r=Math.max(a,r)}const o=[],c=[];let s=n.length-1;for(let u=e[r]+1;u!=0;u=i[u-1]){for(o.push(n[u-1]);s>=u;s--)c.push(n[s]);s--}for(;s>=0;s--)c.push(n[s]);o.reverse(),c.sort((u,l)=>u.claim_order-l.claim_order);for(let u=0,l=0;u<c.length;u++){for(;l<o.length&&c[u].claim_order>=o[l].claim_order;)l++;const f=l<o.length?o[l]:null;t.insertBefore(c[u],f)}}function U(t,n){if($){for(W(t),(t.actual_end_child===void 0||t.actual_end_child!==null&&t.actual_end_child.parentNode!==t)&&(t.actual_end_child=t.firstChild);t.actual_end_child!==null&&t.actual_end_child.claim_order===void 0;)t.actual_end_child=t.actual_end_child.nextSibling;n!==t.actual_end_child?(n.claim_order!==void 0||n.parentNode!==t)&&t.insertBefore(n,t.actual_end_child):t.actual_end_child=n.nextSibling}else(n.parentNode!==t||n.nextSibling!==null)&&t.appendChild(n)}function pt(t,n,e){$&&!e?U(t,n):(n.parentNode!==t||n.nextSibling!=e)&&t.insertBefore(n,e||null)}function V(t){t.parentNode.removeChild(t)}function yt(t,n){for(let e=0;e<t.length;e+=1)t[e]&&t[e].d(n)}function X(t){return document.createElement(t)}function Y(t){return document.createElementNS("http://www.w3.org/2000/svg",t)}function A(t){return document.createTextNode(t)}function gt(){return A(" ")}function xt(){return A("")}function bt(t,n,e,i){return t.addEventListener(n,e,i),()=>t.removeEventListener(n,e,i)}function vt(t){return function(n){return n.preventDefault(),t.call(this,n)}}function $t(t,n,e){e==null?t.removeAttribute(n):t.getAttribute(n)!==e&&t.setAttribute(n,e)}function Z(t){return Array.from(t.childNodes)}function tt(t){t.claim_info===void 0&&(t.claim_info={last_index:0,total_claimed:0})}function L(t,n,e,i,r=!1){tt(t);const o=(()=>{for(let c=t.claim_info.last_index;c<t.length;c++){const s=t[c];if(n(s)){const u=e(s);return u===void 0?t.splice(c,1):t[c]=u,r||(t.claim_info.last_index=c),s}}for(let c=t.claim_info.last_index-1;c>=0;c--){const s=t[c];if(n(s)){const u=e(s);return u===void 0?t.splice(c,1):t[c]=u,r?u===void 0&&t.claim_info.last_index--:t.claim_info.last_index=c,s}}return i()})();return o.claim_order=t.claim_info.total_claimed,t.claim_info.total_claimed+=1,o}function O(t,n,e,i){return L(t,r=>r.nodeName===n,r=>{const o=[];for(let c=0;c<r.attributes.length;c++){const s=r.attributes[c];e[s.name]||o.push(s.name)}o.forEach(c=>r.removeAttribute(c))},()=>i(n))}function Et(t,n,e){return O(t,n,e,X)}function wt(t,n,e){return O(t,n,e,Y)}function nt(t,n){return L(t,e=>e.nodeType===3,e=>{const i=""+n;if(e.data.startsWith(i)){if(e.data.length!==i.length)return e.splitText(i.length)}else e.data=i},()=>A(n),!0)}function Nt(t){return nt(t," ")}function St(t,n){n=""+n,t.wholeText!==n&&(t.data=n)}function At(t,n){t.value=n==null?"":n}function jt(t,n,e,i){e===null?t.style.removeProperty(n):t.style.setProperty(n,e,i?"important":"")}function et(t,n,{bubbles:e=!1,cancelable:i=!1}={}){const r=document.createEvent("CustomEvent");return r.initCustomEvent(t,e,i,n),r}let m;function h(t){m=t}function j(){if(!m)throw new Error("Function called outside component initialization");return m}function Ct(t){j().$$.on_mount.push(t)}function kt(t){j().$$.after_update.push(t)}function Mt(){const t=j();return(n,e,{cancelable:i=!1}={})=>{const r=t.$$.callbacks[n];if(r){const o=et(n,e,{cancelable:i});return r.slice().forEach(c=>{c.call(t,o)}),!o.defaultPrevented}return!0}}const d=[],P=[],b=[],q=[],T=Promise.resolve();let w=!1;function z(){w||(w=!0,T.then(F))}function Pt(){return z(),T}function N(t){b.push(t)}const E=new Set;let x=0;function F(){const t=m;do{for(;x<d.length;){const n=d[x];x++,h(n),it(n.$$)}for(h(null),d.length=0,x=0;P.length;)P.pop()();for(let n=0;n<b.length;n+=1){const e=b[n];E.has(e)||(E.add(e),e())}b.length=0}while(d.length);for(;q.length;)q.pop()();w=!1,E.clear(),h(t)}function it(t){if(t.fragment!==null){t.update(),p(t.before_update);const n=t.dirty;t.dirty=[-1],t.fragment&&t.fragment.p(t.ctx,n),t.after_update.forEach(N)}}const v=new Set;let _;function qt(){_={r:0,c:[],p:_}}function Bt(){_.r||p(_.c),_=_.p}function rt(t,n){t&&t.i&&(v.delete(t),t.i(n))}function Dt(t,n,e,i){if(t&&t.o){if(v.has(t))return;v.add(t),_.c.push(()=>{v.delete(t),i&&(e&&t.d(1),i())}),t.o(n)}else i&&i()}function Lt(t){t&&t.c()}function Ot(t,n){t&&t.l(n)}function ct(t,n,e,i){const{fragment:r,on_mount:o,on_destroy:c,after_update:s}=t.$$;r&&r.m(n,e),i||N(()=>{const u=o.map(B).filter(I);c?c.push(...u):p(u),t.$$.on_mount=[]}),s.forEach(N)}function ut(t,n){const e=t.$$;e.fragment!==null&&(p(e.on_destroy),e.fragment&&e.fragment.d(n),e.on_destroy=e.fragment=null,e.ctx=[])}function lt(t,n){t.$$.dirty[0]===-1&&(d.push(t),z(),t.$$.dirty.fill(0)),t.$$.dirty[n/31|0]|=1<<n%31}function Tt(t,n,e,i,r,o,c,s=[-1]){const u=m;h(t);const l=t.$$={fragment:null,ctx:null,props:o,update:S,not_equal:r,bound:M(),on_mount:[],on_destroy:[],on_disconnect:[],before_update:[],after_update:[],context:new Map(n.context||(u?u.$$.context:[])),callbacks:M(),dirty:s,skip_bound:!1,root:n.target||u.$$.root};c&&c(l.root);let f=!1;if(l.ctx=e?e(t,n.props||{},(a,y,...C)=>{const k=C.length?C[0]:y;return l.ctx&&r(l.ctx[a],l.ctx[a]=k)&&(!l.skip_bound&&l.bound[a]&&l.bound[a](k),f&&lt(t,a)),y}):[],l.update(),f=!0,p(l.before_update),l.fragment=i?i(l.ctx):!1,n.target){if(n.hydrate){K();const a=Z(n.target);l.fragment&&l.fragment.l(a),a.forEach(V)}else l.fragment&&l.fragment.c();n.intro&&rt(t.$$.fragment),ct(t,n.target,n.anchor,n.customElement),Q(),F()}h(u)}class zt{$destroy(){ut(this,1),this.$destroy=S}$on(n,e){const i=this.$$.callbacks[n]||(this.$$.callbacks[n]=[]);return i.push(e),()=>{const r=i.indexOf(e);r!==-1&&i.splice(r,1)}}$set(n){this.$$set&&!G(n)&&(this.$$.skip_bound=!0,this.$$set(n),this.$$.skip_bound=!1)}}export{S as A,ft as B,dt as C,ht as D,_t as E,U as F,at as G,yt as H,Y as I,wt as J,bt as K,ot as L,p as M,Mt as N,At as O,vt as P,mt as Q,P as R,zt as S,gt as a,pt as b,Nt as c,Bt as d,xt as e,rt as f,qt as g,V as h,Tt as i,kt as j,X as k,Et as l,Z as m,$t as n,Ct as o,jt as p,A as q,nt as r,st as s,Dt as t,St as u,Lt as v,Ot as w,ct as x,ut as y,Pt as z};
static/_app/immutable/chunks/singletons-e4c31a41.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{w as u}from"./index-3bda1050.js";let f="",b="";function g(n){f=n.base,b=n.assets||f}function m(n){let e=n.baseURI;if(!e){const t=n.getElementsByTagName("base");e=t.length?t[0].href:n.URL}return e}function _(){return{x:pageXOffset,y:pageYOffset}}function k(n){let e,t=null,r=null,a=null;for(const s of n.composedPath())s instanceof Element&&(!e&&s.nodeName.toUpperCase()==="A"&&(e=s),t===null&&(t=l(s,"data-sveltekit-noscroll")),r===null&&(r=l(s,"data-sveltekit-prefetch")),a===null&&(a=l(s,"data-sveltekit-reload")));const o=e&&new URL(e instanceof SVGAElement?e.href.baseVal:e.href,document.baseURI);return{a:e,url:o,options:{noscroll:t,prefetch:r,reload:a}}}function l(n,e){const t=n.getAttribute(e);return t===null?t:t===""?!0:(t==="off",!1)}function d(n){const e=u(n);let t=!0;function r(){t=!0,e.update(s=>s)}function a(s){t=!1,e.set(s)}function o(s){let i;return e.subscribe(c=>{(i===void 0||t&&c!==i)&&s(i=c)})}return{notify:r,set:a,subscribe:o}}function p(){const{set:n,subscribe:e}=u(!1);let t;async function r(){clearTimeout(t);const a=await fetch(`${b}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(a.ok){const{version:o}=await a.json(),s=o!=="1666722090902";return s&&(n(!0),clearTimeout(t)),s}else throw new Error(`Version check failed: ${a.status}`)}return{subscribe:e,check:r}}function v(n){n.client}const w={url:d({}),page:d({}),navigating:u(null),updated:p()};export{_ as a,g as b,k as f,m as g,v as i,w as s};
static/_app/immutable/components/error.svelte-c31c95c4.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{S as A,i as C,s as F,k as v,q as k,a as h,e as q,l as g,m as E,r as $,h as p,c as R,b as u,F as P,u as S,A as w,G}from"../chunks/index-5559954d.js";import{s as H}from"../chunks/singletons-e4c31a41.js";const O=()=>{const t=H,s={page:{subscribe:t.page.subscribe},navigating:{subscribe:t.navigating.subscribe},updated:t.updated};return Object.defineProperties(s,{preloading:{get(){return console.error("stores.preloading is deprecated; use stores.navigating instead"),{subscribe:t.navigating.subscribe}},enumerable:!1},session:{get(){return B(),{}},enumerable:!1}}),s},z={subscribe(t){return O().page.subscribe(t)}};function B(){throw new Error("stores.session is no longer available. See https://github.com/sveltejs/kit/discussions/5883")}function N(t){let s,i=t[0].error.frame+"",o;return{c(){s=v("pre"),o=k(i)},l(r){s=g(r,"PRE",{});var a=E(s);o=$(a,i),a.forEach(p)},m(r,a){u(r,s,a),P(s,o)},p(r,a){a&1&&i!==(i=r[0].error.frame+"")&&S(o,i)},d(r){r&&p(s)}}}function y(t){let s,i=t[0].error.stack+"",o;return{c(){s=v("pre"),o=k(i)},l(r){s=g(r,"PRE",{});var a=E(s);o=$(a,i),a.forEach(p)},m(r,a){u(r,s,a),P(s,o)},p(r,a){a&1&&i!==(i=r[0].error.stack+"")&&S(o,i)},d(r){r&&p(s)}}}function D(t){let s,i=t[0].status+"",o,r,a,b=t[0].error.message+"",_,d,c,m,l=t[0].error.frame&&N(t),n=t[0].error.stack&&y(t);return{c(){s=v("h1"),o=k(i),r=h(),a=v("pre"),_=k(b),d=h(),l&&l.c(),c=h(),n&&n.c(),m=q()},l(e){s=g(e,"H1",{});var f=E(s);o=$(f,i),f.forEach(p),r=R(e),a=g(e,"PRE",{});var j=E(a);_=$(j,b),j.forEach(p),d=R(e),l&&l.l(e),c=R(e),n&&n.l(e),m=q()},m(e,f){u(e,s,f),P(s,o),u(e,r,f),u(e,a,f),P(a,_),u(e,d,f),l&&l.m(e,f),u(e,c,f),n&&n.m(e,f),u(e,m,f)},p(e,[f]){f&1&&i!==(i=e[0].status+"")&&S(o,i),f&1&&b!==(b=e[0].error.message+"")&&S(_,b),e[0].error.frame?l?l.p(e,f):(l=N(e),l.c(),l.m(c.parentNode,c)):l&&(l.d(1),l=null),e[0].error.stack?n?n.p(e,f):(n=y(e),n.c(),n.m(m.parentNode,m)):n&&(n.d(1),n=null)},i:w,o:w,d(e){e&&p(s),e&&p(r),e&&p(a),e&&p(d),l&&l.d(e),e&&p(c),n&&n.d(e),e&&p(m)}}}function I(t,s,i){let o;return G(t,z,r=>i(0,o=r)),[o]}class L extends A{constructor(s){super(),C(this,s,I,D,F,{})}}export{L as default};