mirror of
				https://github.com/gpxstudio/gpx.studio.git
				synced 2025-11-04 05:21:09 +00:00 
			
		
		
		
	update shadcn components
This commit is contained in:
		@@ -1,5 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
	"$schema": "https://next.shadcn-svelte.com/schema.json",
 | 
			
		||||
	"$schema": "https://shadcn-svelte.com/schema.json",
 | 
			
		||||
	"style": "default",
 | 
			
		||||
	"tailwind": {
 | 
			
		||||
		"css": "src/app.css",
 | 
			
		||||
		"baseColor": "slate"
 | 
			
		||||
@@ -12,5 +13,5 @@
 | 
			
		||||
		"lib": "$lib"
 | 
			
		||||
	},
 | 
			
		||||
	"typescript": true,
 | 
			
		||||
	"registry": "https://next.shadcn-svelte.com/registry"
 | 
			
		||||
	"registry": "https://shadcn-svelte.com/registry"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										134
									
								
								website/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										134
									
								
								website/package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -27,11 +27,10 @@
 | 
			
		||||
                "png.js": "^0.2.1",
 | 
			
		||||
                "sanitize-html": "^2.17.0",
 | 
			
		||||
                "sortablejs": "^1.15.6",
 | 
			
		||||
                "tailwind-merge": "^3.3.0",
 | 
			
		||||
                "tailwind-variants": "^1.0.0"
 | 
			
		||||
                "tailwind-merge": "^3.3.0"
 | 
			
		||||
            },
 | 
			
		||||
            "devDependencies": {
 | 
			
		||||
                "@lucide/svelte": "^0.513.0",
 | 
			
		||||
                "@lucide/svelte": "^0.544.0",
 | 
			
		||||
                "@sveltejs/adapter-static": "^3.0.8",
 | 
			
		||||
                "@sveltejs/enhanced-img": "^0.6.0",
 | 
			
		||||
                "@sveltejs/kit": "^2.21.2",
 | 
			
		||||
@@ -48,7 +47,7 @@
 | 
			
		||||
                "@types/sortablejs": "^1.15.8",
 | 
			
		||||
                "@typescript-eslint/eslint-plugin": "^8.33.1",
 | 
			
		||||
                "@typescript-eslint/parser": "^8.33.1",
 | 
			
		||||
                "bits-ui": "^2.5.0",
 | 
			
		||||
                "bits-ui": "^2.12.0",
 | 
			
		||||
                "eslint": "^9.28.0",
 | 
			
		||||
                "eslint-config-prettier": "^10.1.5",
 | 
			
		||||
                "eslint-plugin-svelte": "^3.9.1",
 | 
			
		||||
@@ -56,14 +55,15 @@
 | 
			
		||||
                "glob": "^11.0.2",
 | 
			
		||||
                "lucide-static": "^0.513.0",
 | 
			
		||||
                "mdsvex": "^0.12.6",
 | 
			
		||||
                "mode-watcher": "^1.0.7",
 | 
			
		||||
                "mode-watcher": "^1.1.0",
 | 
			
		||||
                "paneforge": "^1.0.0-next.5",
 | 
			
		||||
                "postcss": "^8.4.47",
 | 
			
		||||
                "prettier": "^3.5.3",
 | 
			
		||||
                "prettier-plugin-svelte": "^3.4.0",
 | 
			
		||||
                "svelte": "^5.33.18",
 | 
			
		||||
                "svelte-check": "^4.0.0",
 | 
			
		||||
                "svelte-sonner": "^1.0.4",
 | 
			
		||||
                "svelte-sonner": "^1.0.5",
 | 
			
		||||
                "tailwind-variants": "^3.1.1",
 | 
			
		||||
                "tailwindcss": "^4.1.8",
 | 
			
		||||
                "tslib": "^2.8.1",
 | 
			
		||||
                "tsx": "^4.19.1",
 | 
			
		||||
@@ -1625,9 +1625,9 @@
 | 
			
		||||
            "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/@lucide/svelte": {
 | 
			
		||||
            "version": "0.513.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-0.513.0.tgz",
 | 
			
		||||
            "integrity": "sha512-XwBQMQkMlr9qp9yVg+epx5MzhBBrqul8atO00y/ZfhlKRJuQZVmq3ELibApqyBtj9ys0Ai4FH/SZcODTUFYXig==",
 | 
			
		||||
            "version": "0.544.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-0.544.0.tgz",
 | 
			
		||||
            "integrity": "sha512-9f9O6uxng2pLB01sxNySHduJN3HTl5p0HDu4H26VR51vhZfiMzyOMe9Mhof3XAk4l813eTtl+/DYRvGyoRR+yw==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "ISC",
 | 
			
		||||
            "peerDependencies": {
 | 
			
		||||
@@ -3233,23 +3233,21 @@
 | 
			
		||||
            ]
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/bits-ui": {
 | 
			
		||||
            "version": "2.5.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-2.5.0.tgz",
 | 
			
		||||
            "integrity": "sha512-PbjylA1UWd4A/c5AYqie/EVxQ1/8uugmJKLg9whLoBBHbfPEBGhK09dCPrahK9kA6DRHhMmij0XXIUGIfrmNow==",
 | 
			
		||||
            "version": "2.12.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-2.12.0.tgz",
 | 
			
		||||
            "integrity": "sha512-8NF4ILNyAJlIxDXpl/akGXGBV5QmZAe+8gTfPttM5P6/+LrijumcSfFXY5cr4QkXwTmLA7H5stYpbgJf2XFJvg==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "MIT",
 | 
			
		||||
            "dependencies": {
 | 
			
		||||
                "@floating-ui/core": "^1.7.0",
 | 
			
		||||
                "@floating-ui/dom": "^1.7.0",
 | 
			
		||||
                "css.escape": "^1.5.1",
 | 
			
		||||
                "@floating-ui/core": "^1.7.1",
 | 
			
		||||
                "@floating-ui/dom": "^1.7.1",
 | 
			
		||||
                "esm-env": "^1.1.2",
 | 
			
		||||
                "runed": "^0.28.0",
 | 
			
		||||
                "svelte-toolbelt": "^0.9.1",
 | 
			
		||||
                "runed": "^0.35.1",
 | 
			
		||||
                "svelte-toolbelt": "^0.10.6",
 | 
			
		||||
                "tabbable": "^6.2.0"
 | 
			
		||||
            },
 | 
			
		||||
            "engines": {
 | 
			
		||||
                "node": ">=20",
 | 
			
		||||
                "pnpm": ">=8.7.0"
 | 
			
		||||
                "node": ">=20"
 | 
			
		||||
            },
 | 
			
		||||
            "funding": {
 | 
			
		||||
                "url": "https://github.com/sponsors/huntabyte"
 | 
			
		||||
@@ -3260,9 +3258,9 @@
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/bits-ui/node_modules/runed": {
 | 
			
		||||
            "version": "0.28.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/runed/-/runed-0.28.0.tgz",
 | 
			
		||||
            "integrity": "sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ==",
 | 
			
		||||
            "version": "0.35.1",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/runed/-/runed-0.35.1.tgz",
 | 
			
		||||
            "integrity": "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "funding": [
 | 
			
		||||
                "https://github.com/sponsors/huntabyte",
 | 
			
		||||
@@ -3270,23 +3268,31 @@
 | 
			
		||||
            ],
 | 
			
		||||
            "license": "MIT",
 | 
			
		||||
            "dependencies": {
 | 
			
		||||
                "esm-env": "^1.0.0"
 | 
			
		||||
                "dequal": "^2.0.3",
 | 
			
		||||
                "esm-env": "^1.0.0",
 | 
			
		||||
                "lz-string": "^1.5.0"
 | 
			
		||||
            },
 | 
			
		||||
            "peerDependencies": {
 | 
			
		||||
                "@sveltejs/kit": "^2.21.0",
 | 
			
		||||
                "svelte": "^5.7.0"
 | 
			
		||||
            },
 | 
			
		||||
            "peerDependenciesMeta": {
 | 
			
		||||
                "@sveltejs/kit": {
 | 
			
		||||
                    "optional": true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/bits-ui/node_modules/svelte-toolbelt": {
 | 
			
		||||
            "version": "0.9.1",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.9.1.tgz",
 | 
			
		||||
            "integrity": "sha512-wBX6MtYw/kpht80j5zLpxJyR9soLizXPIAIWEVd9llAi17SR44ZdG291bldjB7r/K5duC0opDFcuhk2cA1hb8g==",
 | 
			
		||||
            "version": "0.10.6",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.10.6.tgz",
 | 
			
		||||
            "integrity": "sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "funding": [
 | 
			
		||||
                "https://github.com/sponsors/huntabyte"
 | 
			
		||||
            ],
 | 
			
		||||
            "dependencies": {
 | 
			
		||||
                "clsx": "^2.1.1",
 | 
			
		||||
                "runed": "^0.28.0",
 | 
			
		||||
                "runed": "^0.35.1",
 | 
			
		||||
                "style-to-object": "^1.0.8"
 | 
			
		||||
            },
 | 
			
		||||
            "engines": {
 | 
			
		||||
@@ -3891,13 +3897,6 @@
 | 
			
		||||
                "node": "*"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/css.escape": {
 | 
			
		||||
            "version": "1.5.1",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
 | 
			
		||||
            "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "MIT"
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/csscolorparser": {
 | 
			
		||||
            "version": "1.0.3",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
 | 
			
		||||
@@ -4053,6 +4052,16 @@
 | 
			
		||||
                "node": ">=0.4.0"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/dequal": {
 | 
			
		||||
            "version": "2.0.3",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
 | 
			
		||||
            "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "MIT",
 | 
			
		||||
            "engines": {
 | 
			
		||||
                "node": ">=6"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/des.js": {
 | 
			
		||||
            "version": "1.1.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz",
 | 
			
		||||
@@ -6019,6 +6028,16 @@
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "ISC"
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/lz-string": {
 | 
			
		||||
            "version": "1.5.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
 | 
			
		||||
            "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "MIT",
 | 
			
		||||
            "bin": {
 | 
			
		||||
                "lz-string": "bin/bin.js"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/magic-string": {
 | 
			
		||||
            "version": "0.30.17",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
 | 
			
		||||
@@ -6369,9 +6388,9 @@
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/mode-watcher": {
 | 
			
		||||
            "version": "1.0.7",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-1.0.7.tgz",
 | 
			
		||||
            "integrity": "sha512-ZGA7ZGdOvBJeTQkzdBOnXSgTkO6U6iIFWJoyGCTt6oHNg9XP9NBvS26De+V4W2aqI+B0yYXUskFG2VnEo3zyMQ==",
 | 
			
		||||
            "version": "1.1.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-1.1.0.tgz",
 | 
			
		||||
            "integrity": "sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "MIT",
 | 
			
		||||
            "dependencies": {
 | 
			
		||||
@@ -8292,22 +8311,22 @@
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/svelte-sonner": {
 | 
			
		||||
            "version": "1.0.4",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/svelte-sonner/-/svelte-sonner-1.0.4.tgz",
 | 
			
		||||
            "integrity": "sha512-ctm9jeV0Rf3im2J6RU1emccrJFjRSdNSPsLlxaF62TLZw9bB1D40U/U7+wqEgohJY/X7FBdghdj0BFQF/IqKPQ==",
 | 
			
		||||
            "version": "1.0.5",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/svelte-sonner/-/svelte-sonner-1.0.5.tgz",
 | 
			
		||||
            "integrity": "sha512-9dpGPFqKb/QWudYqGnEz93vuY+NgCEvyNvxoCLMVGw6sDN/3oVeKV1xiEirW2E1N3vJEyj5imSBNOGltQHA7mg==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "MIT",
 | 
			
		||||
            "dependencies": {
 | 
			
		||||
                "runed": "^0.26.0"
 | 
			
		||||
                "runed": "^0.28.0"
 | 
			
		||||
            },
 | 
			
		||||
            "peerDependencies": {
 | 
			
		||||
                "svelte": "^5.0.0"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/svelte-sonner/node_modules/runed": {
 | 
			
		||||
            "version": "0.26.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/runed/-/runed-0.26.0.tgz",
 | 
			
		||||
            "integrity": "sha512-qWFv0cvLVRd8pdl/AslqzvtQyEn5KaIugEernwg9G98uJVSZcs/ygvPBvF80LA46V8pwRvSKnaVLDI3+i2wubw==",
 | 
			
		||||
            "version": "0.28.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/runed/-/runed-0.28.0.tgz",
 | 
			
		||||
            "integrity": "sha512-k2xx7RuO9hWcdd9f+8JoBeqWtYrm5CALfgpkg2YDB80ds/QE4w0qqu34A7fqiAwiBBSBQOid7TLxwxVC27ymWQ==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "funding": [
 | 
			
		||||
                "https://github.com/sponsors/huntabyte",
 | 
			
		||||
@@ -8376,35 +8395,30 @@
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/tailwind-variants": {
 | 
			
		||||
            "version": "1.0.0",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-1.0.0.tgz",
 | 
			
		||||
            "integrity": "sha512-2WSbv4ulEEyuBKomOunut65D8UZwxrHoRfYnxGcQNnHqlSCp2+B7Yz2W+yrNDrxRodOXtGD/1oCcKGNBnUqMqA==",
 | 
			
		||||
            "version": "3.1.1",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-3.1.1.tgz",
 | 
			
		||||
            "integrity": "sha512-ftLXe3krnqkMHsuBTEmaVUXYovXtPyTK7ckEfDRXS8PBZx0bAUas+A0jYxuKA5b8qg++wvQ3d2MQ7l/xeZxbZQ==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "MIT",
 | 
			
		||||
            "dependencies": {
 | 
			
		||||
                "tailwind-merge": "3.0.2"
 | 
			
		||||
            },
 | 
			
		||||
            "engines": {
 | 
			
		||||
                "node": ">=16.x",
 | 
			
		||||
                "pnpm": ">=7.x"
 | 
			
		||||
            },
 | 
			
		||||
            "peerDependencies": {
 | 
			
		||||
                "tailwind-merge": ">=3.0.0",
 | 
			
		||||
                "tailwindcss": "*"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/tailwind-variants/node_modules/tailwind-merge": {
 | 
			
		||||
            "version": "3.0.2",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.0.2.tgz",
 | 
			
		||||
            "integrity": "sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==",
 | 
			
		||||
            "license": "MIT",
 | 
			
		||||
            "funding": {
 | 
			
		||||
                "type": "github",
 | 
			
		||||
                "url": "https://github.com/sponsors/dcastil"
 | 
			
		||||
            },
 | 
			
		||||
            "peerDependenciesMeta": {
 | 
			
		||||
                "tailwind-merge": {
 | 
			
		||||
                    "optional": true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/tailwindcss": {
 | 
			
		||||
            "version": "4.1.8",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz",
 | 
			
		||||
            "integrity": "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==",
 | 
			
		||||
            "dev": true,
 | 
			
		||||
            "license": "MIT"
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/tapable": {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
        "format": "prettier --write ."
 | 
			
		||||
    },
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@lucide/svelte": "^0.513.0",
 | 
			
		||||
        "@lucide/svelte": "^0.544.0",
 | 
			
		||||
        "@sveltejs/adapter-static": "^3.0.8",
 | 
			
		||||
        "@sveltejs/enhanced-img": "^0.6.0",
 | 
			
		||||
        "@sveltejs/kit": "^2.21.2",
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
        "@types/sortablejs": "^1.15.8",
 | 
			
		||||
        "@typescript-eslint/eslint-plugin": "^8.33.1",
 | 
			
		||||
        "@typescript-eslint/parser": "^8.33.1",
 | 
			
		||||
        "bits-ui": "^2.5.0",
 | 
			
		||||
        "bits-ui": "^2.12.0",
 | 
			
		||||
        "eslint": "^9.28.0",
 | 
			
		||||
        "eslint-config-prettier": "^10.1.5",
 | 
			
		||||
        "eslint-plugin-svelte": "^3.9.1",
 | 
			
		||||
@@ -39,14 +39,15 @@
 | 
			
		||||
        "glob": "^11.0.2",
 | 
			
		||||
        "lucide-static": "^0.513.0",
 | 
			
		||||
        "mdsvex": "^0.12.6",
 | 
			
		||||
        "mode-watcher": "^1.0.7",
 | 
			
		||||
        "mode-watcher": "^1.1.0",
 | 
			
		||||
        "paneforge": "^1.0.0-next.5",
 | 
			
		||||
        "postcss": "^8.4.47",
 | 
			
		||||
        "prettier": "^3.5.3",
 | 
			
		||||
        "prettier-plugin-svelte": "^3.4.0",
 | 
			
		||||
        "svelte": "^5.33.18",
 | 
			
		||||
        "svelte-check": "^4.0.0",
 | 
			
		||||
        "svelte-sonner": "^1.0.4",
 | 
			
		||||
        "svelte-sonner": "^1.0.5",
 | 
			
		||||
        "tailwind-variants": "^3.1.1",
 | 
			
		||||
        "tailwindcss": "^4.1.8",
 | 
			
		||||
        "tslib": "^2.8.1",
 | 
			
		||||
        "tsx": "^4.19.1",
 | 
			
		||||
@@ -77,7 +78,6 @@
 | 
			
		||||
        "png.js": "^0.2.1",
 | 
			
		||||
        "sanitize-html": "^2.17.0",
 | 
			
		||||
        "sortablejs": "^1.15.6",
 | 
			
		||||
        "tailwind-merge": "^3.3.0",
 | 
			
		||||
        "tailwind-variants": "^1.0.0"
 | 
			
		||||
        "tailwind-merge": "^3.3.0"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    import { CircleHelp } from '@lucide/svelte';
 | 
			
		||||
    import { CircleQuestionMark } from '@lucide/svelte';
 | 
			
		||||
    import { i18n } from '$lib/i18n.svelte';
 | 
			
		||||
 | 
			
		||||
    export let link: string | undefined = undefined;
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
<div
 | 
			
		||||
    class="text-sm bg-secondary rounded border flex flex-row items-center p-2 {$$props.class || ''}"
 | 
			
		||||
>
 | 
			
		||||
    <CircleHelp size="16" class="w-4 mr-2 shrink-0 grow-0" />
 | 
			
		||||
    <CircleQuestionMark size="16" class="w-4 mr-2 shrink-0 grow-0" />
 | 
			
		||||
    <div>
 | 
			
		||||
        <slot />
 | 
			
		||||
        {#if link}
 | 
			
		||||
 
 | 
			
		||||
@@ -120,13 +120,13 @@
 | 
			
		||||
                </Menubar.Trigger>
 | 
			
		||||
                <Menubar.Content class="border-none">
 | 
			
		||||
                    <Menubar.Item onclick={createFile}>
 | 
			
		||||
                        <Plus size="16" class="mr-1" />
 | 
			
		||||
                        <Plus size="16" />
 | 
			
		||||
                        {i18n._('menu.new')}
 | 
			
		||||
                        <Shortcut key="+" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
                    <Menubar.Separator />
 | 
			
		||||
                    <Menubar.Item onclick={triggerFileInput}>
 | 
			
		||||
                        <FolderOpen size="16" class="mr-1" />
 | 
			
		||||
                        <FolderOpen size="16" />
 | 
			
		||||
                        {i18n._('menu.open')}
 | 
			
		||||
                        <Shortcut key="O" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -135,7 +135,7 @@
 | 
			
		||||
                        onclick={fileActions.duplicateSelection}
 | 
			
		||||
                        disabled={$selection.size == 0}
 | 
			
		||||
                    >
 | 
			
		||||
                        <Copy size="16" class="mr-1" />
 | 
			
		||||
                        <Copy size="16" />
 | 
			
		||||
                        {i18n._('menu.duplicate')}
 | 
			
		||||
                        <Shortcut key="D" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -144,7 +144,7 @@
 | 
			
		||||
                        onclick={fileActions.deleteSelectedFiles}
 | 
			
		||||
                        disabled={$selection.size == 0}
 | 
			
		||||
                    >
 | 
			
		||||
                        <FileX size="16" class="mr-1" />
 | 
			
		||||
                        <FileX size="16" />
 | 
			
		||||
                        {i18n._('menu.close')}
 | 
			
		||||
                        <Shortcut key="⌫" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -152,7 +152,7 @@
 | 
			
		||||
                        onclick={fileActions.deleteAllFiles}
 | 
			
		||||
                        disabled={fileStateCollection.size == 0}
 | 
			
		||||
                    >
 | 
			
		||||
                        <FileX size="16" class="mr-1" />
 | 
			
		||||
                        <FileX size="16" />
 | 
			
		||||
                        {i18n._('menu.close_all')}
 | 
			
		||||
                        <Shortcut key="⌫" ctrl={true} shift={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -161,7 +161,7 @@
 | 
			
		||||
                        onclick={() => (exportState.current = ExportState.SELECTION)}
 | 
			
		||||
                        disabled={$selection.size == 0}
 | 
			
		||||
                    >
 | 
			
		||||
                        <Download size="16" class="mr-1" />
 | 
			
		||||
                        <Download size="16" />
 | 
			
		||||
                        {i18n._('menu.export')}
 | 
			
		||||
                        <Shortcut key="S" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -169,7 +169,7 @@
 | 
			
		||||
                        onclick={() => (exportState.current = ExportState.ALL)}
 | 
			
		||||
                        disabled={fileStateCollection.size == 0}
 | 
			
		||||
                    >
 | 
			
		||||
                        <Download size="16" class="mr-1" />
 | 
			
		||||
                        <Download size="16" />
 | 
			
		||||
                        {i18n._('menu.export_all')}
 | 
			
		||||
                        <Shortcut key="S" ctrl={true} shift={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -185,7 +185,7 @@
 | 
			
		||||
                        onclick={() => fileActionManager.undo()}
 | 
			
		||||
                        disabled={!fileActionManager.canUndo}
 | 
			
		||||
                    >
 | 
			
		||||
                        <Undo2 size="16" class="mr-1" />
 | 
			
		||||
                        <Undo2 size="16" />
 | 
			
		||||
                        {i18n._('menu.undo')}
 | 
			
		||||
                        <Shortcut key="Z" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -193,7 +193,7 @@
 | 
			
		||||
                        onclick={() => fileActionManager.redo()}
 | 
			
		||||
                        disabled={!fileActionManager.canRedo}
 | 
			
		||||
                    >
 | 
			
		||||
                        <Redo2 size="16" class="mr-1" />
 | 
			
		||||
                        <Redo2 size="16" />
 | 
			
		||||
                        {i18n._('menu.redo')}
 | 
			
		||||
                        <Shortcut key="Z" ctrl={true} shift={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -209,7 +209,7 @@
 | 
			
		||||
                                )}
 | 
			
		||||
                        onclick={() => (editMetadata.current = true)}
 | 
			
		||||
                    >
 | 
			
		||||
                        <Info size="16" class="mr-1" />
 | 
			
		||||
                        <Info size="16" />
 | 
			
		||||
                        {i18n._('menu.metadata.button')}
 | 
			
		||||
                        <Shortcut key="I" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -224,7 +224,7 @@
 | 
			
		||||
                                )}
 | 
			
		||||
                        onclick={() => (editStyle.current = true)}
 | 
			
		||||
                    >
 | 
			
		||||
                        <PaintBucket size="16" class="mr-1" />
 | 
			
		||||
                        <PaintBucket size="16" />
 | 
			
		||||
                        {i18n._('menu.style.button')}
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
                    <Menubar.Item
 | 
			
		||||
@@ -238,10 +238,10 @@
 | 
			
		||||
                        disabled={$selection.size == 0}
 | 
			
		||||
                    >
 | 
			
		||||
                        <!-- {#if $allHidden}
 | 
			
		||||
                            <Eye size="16" class="mr-1" />
 | 
			
		||||
                            <Eye size="16" />
 | 
			
		||||
                            {i18n._('menu.unhide')}
 | 
			
		||||
                        {:else}
 | 
			
		||||
                            <EyeOff size="16" class="mr-1" />
 | 
			
		||||
                            <EyeOff size="16" />
 | 
			
		||||
                            {i18n._('menu.hide')}
 | 
			
		||||
                        {/if} -->
 | 
			
		||||
                        <Shortcut key="H" ctrl={true} />
 | 
			
		||||
@@ -256,7 +256,7 @@
 | 
			
		||||
                                    )}
 | 
			
		||||
                                disabled={$selection.size !== 1}
 | 
			
		||||
                            >
 | 
			
		||||
                                <Plus size="16" class="mr-1" />
 | 
			
		||||
                                <Plus size="16" />
 | 
			
		||||
                                {i18n._('menu.new_track')}
 | 
			
		||||
                            </Menubar.Item>
 | 
			
		||||
                        {:else if $selection
 | 
			
		||||
@@ -273,7 +273,7 @@
 | 
			
		||||
                                }}
 | 
			
		||||
                                disabled={$selection.size !== 1}
 | 
			
		||||
                            >
 | 
			
		||||
                                <Plus size="16" class="mr-1" />
 | 
			
		||||
                                <Plus size="16" />
 | 
			
		||||
                                {i18n._('menu.new_segment')}
 | 
			
		||||
                            </Menubar.Item>
 | 
			
		||||
                        {/if}
 | 
			
		||||
@@ -283,7 +283,7 @@
 | 
			
		||||
                        onclick={selection.selectAll}
 | 
			
		||||
                        disabled={fileStateCollection.size == 0}
 | 
			
		||||
                    >
 | 
			
		||||
                        <FileStack size="16" class="mr-1" />
 | 
			
		||||
                        <FileStack size="16" />
 | 
			
		||||
                        {i18n._('menu.select_all')}
 | 
			
		||||
                        <Shortcut key="A" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -294,7 +294,7 @@
 | 
			
		||||
                            }
 | 
			
		||||
                        }}
 | 
			
		||||
                    >
 | 
			
		||||
                        <Maximize size="16" class="mr-1" />
 | 
			
		||||
                        <Maximize size="16" />
 | 
			
		||||
                        {i18n._('menu.center')}
 | 
			
		||||
                        <Shortcut key="⏎" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -304,7 +304,7 @@
 | 
			
		||||
                            onclick={selection.copySelection}
 | 
			
		||||
                            disabled={$selection.size === 0}
 | 
			
		||||
                        >
 | 
			
		||||
                            <ClipboardCopy size="16" class="mr-1" />
 | 
			
		||||
                            <ClipboardCopy size="16" />
 | 
			
		||||
                            {i18n._('menu.copy')}
 | 
			
		||||
                            <Shortcut key="C" ctrl={true} />
 | 
			
		||||
                        </Menubar.Item>
 | 
			
		||||
@@ -312,7 +312,7 @@
 | 
			
		||||
                            onclick={selection.cutSelection}
 | 
			
		||||
                            disabled={$selection.size === 0}
 | 
			
		||||
                        >
 | 
			
		||||
                            <Scissors size="16" class="mr-1" />
 | 
			
		||||
                            <Scissors size="16" />
 | 
			
		||||
                            {i18n._('menu.cut')}
 | 
			
		||||
                            <Shortcut key="X" ctrl={true} />
 | 
			
		||||
                        </Menubar.Item>
 | 
			
		||||
@@ -325,7 +325,7 @@
 | 
			
		||||
                                    ))}
 | 
			
		||||
                            onclick={pasteSelection}
 | 
			
		||||
                        >
 | 
			
		||||
                            <ClipboardPaste size="16" class="mr-1" />
 | 
			
		||||
                            <ClipboardPaste size="16" />
 | 
			
		||||
                            {i18n._('menu.paste')}
 | 
			
		||||
                            <Shortcut key="V" ctrl={true} />
 | 
			
		||||
                        </Menubar.Item>
 | 
			
		||||
@@ -335,7 +335,7 @@
 | 
			
		||||
                        onclick={fileActions.deleteSelection}
 | 
			
		||||
                        disabled={$selection.size == 0}
 | 
			
		||||
                    >
 | 
			
		||||
                        <Trash2 size="16" class="mr-1" />
 | 
			
		||||
                        <Trash2 size="16" />
 | 
			
		||||
                        {i18n._('menu.delete')}
 | 
			
		||||
                        <Shortcut key="⌫" ctrl={true} />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
@@ -348,42 +348,36 @@
 | 
			
		||||
                </Menubar.Trigger>
 | 
			
		||||
                <Menubar.Content class="border-none">
 | 
			
		||||
                    <Menubar.CheckboxItem bind:checked={$elevationProfile}>
 | 
			
		||||
                        <ChartArea size="16" class="mr-1" />
 | 
			
		||||
                        <ChartArea size="16" />
 | 
			
		||||
                        {i18n._('menu.elevation_profile')}
 | 
			
		||||
                        <Shortcut key="P" ctrl={true} />
 | 
			
		||||
                    </Menubar.CheckboxItem>
 | 
			
		||||
                    <Menubar.CheckboxItem bind:checked={$treeFileView}>
 | 
			
		||||
                        <ListTree size="16" class="mr-1" />
 | 
			
		||||
                        <ListTree size="16" />
 | 
			
		||||
                        {i18n._('menu.tree_file_view')}
 | 
			
		||||
                        <Shortcut key="L" ctrl={true} />
 | 
			
		||||
                    </Menubar.CheckboxItem>
 | 
			
		||||
                    <Menubar.Separator />
 | 
			
		||||
                    <Menubar.Item inset onclick={switchBasemaps}>
 | 
			
		||||
                        <Map size="16" class="mr-1" />{i18n._('menu.switch_basemap')}<Shortcut
 | 
			
		||||
                            key="F1"
 | 
			
		||||
                        />
 | 
			
		||||
                        <Map size="16" />{i18n._('menu.switch_basemap')}<Shortcut key="F1" />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
                    <Menubar.Item inset onclick={toggleOverlays}>
 | 
			
		||||
                        <Layers2 size="16" class="mr-1" />{i18n._('menu.toggle_overlays')}<Shortcut
 | 
			
		||||
                            key="F2"
 | 
			
		||||
                        />
 | 
			
		||||
                        <Layers2 size="16" />{i18n._('menu.toggle_overlays')}<Shortcut key="F2" />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
                    <Menubar.Separator />
 | 
			
		||||
                    <Menubar.CheckboxItem bind:checked={$distanceMarkers}>
 | 
			
		||||
                        <Coins size="16" class="mr-1" />{i18n._('menu.distance_markers')}<Shortcut
 | 
			
		||||
                            key="F3"
 | 
			
		||||
                        />
 | 
			
		||||
                        <Coins size="16" />{i18n._('menu.distance_markers')}<Shortcut key="F3" />
 | 
			
		||||
                    </Menubar.CheckboxItem>
 | 
			
		||||
                    <Menubar.CheckboxItem bind:checked={$directionMarkers}>
 | 
			
		||||
                        <Milestone size="16" class="mr-1" />{i18n._(
 | 
			
		||||
                            'menu.direction_markers'
 | 
			
		||||
                        )}<Shortcut key="F4" />
 | 
			
		||||
                        <Milestone size="16" />{i18n._('menu.direction_markers')}<Shortcut
 | 
			
		||||
                            key="F4"
 | 
			
		||||
                        />
 | 
			
		||||
                    </Menubar.CheckboxItem>
 | 
			
		||||
                    <Menubar.Separator />
 | 
			
		||||
                    <Menubar.Item inset onclick={map.toggle3D}>
 | 
			
		||||
                        <Box size="16" class="mr-1" />
 | 
			
		||||
                        <Box size="16" />
 | 
			
		||||
                        {i18n._('menu.toggle_3d')}
 | 
			
		||||
                        <Shortcut key="{i18n._('menu.ctrl')}+{i18n._('menu.drag')}" />
 | 
			
		||||
                        <Shortcut key="{i18n._('menu.ctrl')} {i18n._('menu.drag')}" />
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
                </Menubar.Content>
 | 
			
		||||
            </Menubar.Menu>
 | 
			
		||||
@@ -397,7 +391,7 @@
 | 
			
		||||
                <Menubar.Content class="border-none">
 | 
			
		||||
                    <Menubar.Sub>
 | 
			
		||||
                        <Menubar.SubTrigger>
 | 
			
		||||
                            <Ruler size="16" class="mr-1" />{i18n._('menu.distance_units')}
 | 
			
		||||
                            <Ruler size="16" class="mr-2" />{i18n._('menu.distance_units')}
 | 
			
		||||
                        </Menubar.SubTrigger>
 | 
			
		||||
                        <Menubar.SubContent>
 | 
			
		||||
                            <Menubar.RadioGroup bind:value={$distanceUnits}>
 | 
			
		||||
@@ -415,7 +409,7 @@
 | 
			
		||||
                    </Menubar.Sub>
 | 
			
		||||
                    <Menubar.Sub>
 | 
			
		||||
                        <Menubar.SubTrigger>
 | 
			
		||||
                            <Zap size="16" class="mr-1" />{i18n._('menu.velocity_units')}
 | 
			
		||||
                            <Zap size="16" class="mr-2" />{i18n._('menu.velocity_units')}
 | 
			
		||||
                        </Menubar.SubTrigger>
 | 
			
		||||
                        <Menubar.SubContent>
 | 
			
		||||
                            <Menubar.RadioGroup bind:value={$velocityUnits}>
 | 
			
		||||
@@ -430,7 +424,7 @@
 | 
			
		||||
                    </Menubar.Sub>
 | 
			
		||||
                    <Menubar.Sub>
 | 
			
		||||
                        <Menubar.SubTrigger>
 | 
			
		||||
                            <Thermometer size="16" class="mr-1" />{i18n._('menu.temperature_units')}
 | 
			
		||||
                            <Thermometer size="16" class="mr-2" />{i18n._('menu.temperature_units')}
 | 
			
		||||
                        </Menubar.SubTrigger>
 | 
			
		||||
                        <Menubar.SubContent>
 | 
			
		||||
                            <Menubar.RadioGroup bind:value={$temperatureUnits}>
 | 
			
		||||
@@ -446,7 +440,7 @@
 | 
			
		||||
                    <Menubar.Separator />
 | 
			
		||||
                    <Menubar.Sub>
 | 
			
		||||
                        <Menubar.SubTrigger>
 | 
			
		||||
                            <Languages size="16" class="mr-1" />
 | 
			
		||||
                            <Languages size="16" class="mr-2" />
 | 
			
		||||
                            {i18n._('menu.language')}
 | 
			
		||||
                        </Menubar.SubTrigger>
 | 
			
		||||
                        <Menubar.SubContent>
 | 
			
		||||
@@ -462,9 +456,9 @@
 | 
			
		||||
                    <Menubar.Sub>
 | 
			
		||||
                        <Menubar.SubTrigger>
 | 
			
		||||
                            {#if mode.current === 'light' || !mode.current}
 | 
			
		||||
                                <Sun size="16" class="mr-1" />
 | 
			
		||||
                                <Sun size="16" class="mr-2" />
 | 
			
		||||
                            {:else}
 | 
			
		||||
                                <Moon size="16" class="mr-1" />
 | 
			
		||||
                                <Moon size="16" class="mr-2" />
 | 
			
		||||
                            {/if}
 | 
			
		||||
                            {i18n._('menu.mode')}
 | 
			
		||||
                        </Menubar.SubTrigger>
 | 
			
		||||
@@ -487,7 +481,7 @@
 | 
			
		||||
                    <Menubar.Separator />
 | 
			
		||||
                    <Menubar.Sub>
 | 
			
		||||
                        <Menubar.SubTrigger>
 | 
			
		||||
                            <PersonStanding size="16" class="mr-1" />
 | 
			
		||||
                            <PersonStanding size="16" class="mr-2" />
 | 
			
		||||
                            {i18n._('menu.street_view_source')}
 | 
			
		||||
                        </Menubar.SubTrigger>
 | 
			
		||||
                        <Menubar.SubContent>
 | 
			
		||||
@@ -502,7 +496,7 @@
 | 
			
		||||
                        </Menubar.SubContent>
 | 
			
		||||
                    </Menubar.Sub>
 | 
			
		||||
                    <Menubar.Item onclick={() => (layerSettingsOpen = true)}>
 | 
			
		||||
                        <Layers size="16" class="mr-1" />
 | 
			
		||||
                        <Layers size="16" />
 | 
			
		||||
                        {i18n._('menu.layers')}
 | 
			
		||||
                    </Menubar.Item>
 | 
			
		||||
                </Menubar.Content>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,14 +2,24 @@
 | 
			
		||||
    import { isMac, isSafari } from '$lib/utils';
 | 
			
		||||
    import { onMount } from 'svelte';
 | 
			
		||||
    import { i18n } from '$lib/i18n.svelte';
 | 
			
		||||
    import * as Kbd from '$lib/components/ui/kbd/index.js';
 | 
			
		||||
 | 
			
		||||
    export let key: string | undefined = undefined;
 | 
			
		||||
    export let shift: boolean = false;
 | 
			
		||||
    export let ctrl: boolean = false;
 | 
			
		||||
    export let click: boolean = false;
 | 
			
		||||
    let {
 | 
			
		||||
        key = undefined,
 | 
			
		||||
        shift = false,
 | 
			
		||||
        ctrl = false,
 | 
			
		||||
        click = false,
 | 
			
		||||
        class: className = '',
 | 
			
		||||
    }: {
 | 
			
		||||
        key?: string;
 | 
			
		||||
        shift?: boolean;
 | 
			
		||||
        ctrl?: boolean;
 | 
			
		||||
        click?: boolean;
 | 
			
		||||
        class?: string;
 | 
			
		||||
    } = $props();
 | 
			
		||||
 | 
			
		||||
    let mac = false;
 | 
			
		||||
    let safari = false;
 | 
			
		||||
    let mac = $state(false);
 | 
			
		||||
    let safari = $state(false);
 | 
			
		||||
 | 
			
		||||
    onMount(() => {
 | 
			
		||||
        mac = isMac();
 | 
			
		||||
@@ -17,20 +27,17 @@
 | 
			
		||||
    });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
    class="ml-auto pl-2 text-xs tracking-widest text-muted-foreground flex flex-row gap-0 items-baseline"
 | 
			
		||||
    {...$$props}
 | 
			
		||||
>
 | 
			
		||||
<Kbd.Root class="ml-auto {className}">
 | 
			
		||||
    {#if shift}
 | 
			
		||||
        <span>⇧</span>
 | 
			
		||||
        ⇧
 | 
			
		||||
    {/if}
 | 
			
		||||
    {#if ctrl}
 | 
			
		||||
        <span>{mac && !safari ? '⌘' : i18n._('menu.ctrl') + '+'}</span>
 | 
			
		||||
        {mac && !safari ? '⌘' : i18n._('menu.ctrl')}
 | 
			
		||||
    {/if}
 | 
			
		||||
    {#if key}
 | 
			
		||||
        <span class={key === '+' ? 'font-medium text-sm/4' : ''}>{key}</span>
 | 
			
		||||
        {key}
 | 
			
		||||
    {/if}
 | 
			
		||||
    {#if click}
 | 
			
		||||
        <span>{i18n._('menu.click')}</span>
 | 
			
		||||
        {i18n._('menu.click')}
 | 
			
		||||
    {/if}
 | 
			
		||||
</div>
 | 
			
		||||
</Kbd.Root>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,31 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    import * as Tooltip from '$lib/components/ui/tooltip/index.js';
 | 
			
		||||
    import type { Snippet } from 'svelte';
 | 
			
		||||
 | 
			
		||||
    export let label: string;
 | 
			
		||||
    export let side: 'top' | 'right' | 'bottom' | 'left' = 'top';
 | 
			
		||||
    let {
 | 
			
		||||
        label,
 | 
			
		||||
        side = 'top',
 | 
			
		||||
        children,
 | 
			
		||||
        extra,
 | 
			
		||||
        class: className = '',
 | 
			
		||||
    }: {
 | 
			
		||||
        label: string;
 | 
			
		||||
        side?: 'top' | 'right' | 'bottom' | 'left';
 | 
			
		||||
        children: Snippet;
 | 
			
		||||
        extra?: Snippet;
 | 
			
		||||
        class?: string;
 | 
			
		||||
    } = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<Tooltip.Provider>
 | 
			
		||||
    <Tooltip.Root>
 | 
			
		||||
        <Tooltip.Trigger {...$$restProps} aria-label={label}>
 | 
			
		||||
            <slot />
 | 
			
		||||
        <Tooltip.Trigger class={className} aria-label={label}>
 | 
			
		||||
            {@render children()}
 | 
			
		||||
        </Tooltip.Trigger>
 | 
			
		||||
        <Tooltip.Content {side}>
 | 
			
		||||
            <div class="flex flex-row items-center">
 | 
			
		||||
            <div class="flex flex-row items-center gap-2">
 | 
			
		||||
                <span>{label}</span>
 | 
			
		||||
                <slot name="extra" />
 | 
			
		||||
                {@render extra?.()}
 | 
			
		||||
            </div>
 | 
			
		||||
        </Tooltip.Content>
 | 
			
		||||
    </Tooltip.Root>
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@
 | 
			
		||||
                variant="ghost"
 | 
			
		||||
                class="w-full flex flex-row {side === 'right'
 | 
			
		||||
                    ? 'justify-between'
 | 
			
		||||
                    : 'justify-start'} py-0 px-1 h-fit {nohover
 | 
			
		||||
                    : 'justify-start'} p-0 has-[>svg]:px-0 h-fit {nohover
 | 
			
		||||
                    ? 'hover:bg-background'
 | 
			
		||||
                    : ''} pointer-events-none"
 | 
			
		||||
            >
 | 
			
		||||
@@ -62,7 +62,7 @@
 | 
			
		||||
            variant="ghost"
 | 
			
		||||
            class="w-full flex flex-row {side === 'right'
 | 
			
		||||
                ? 'justify-between'
 | 
			
		||||
                : 'justify-start'} py-0 px-1 h-fit {nohover ? 'hover:bg-background' : ''}"
 | 
			
		||||
                : 'justify-start'} p-0 has-[>svg]:px-0 h-fit {nohover ? 'hover:bg-background' : ''}"
 | 
			
		||||
        >
 | 
			
		||||
            {#if side === 'left'}
 | 
			
		||||
                <Collapsible.Trigger>
 | 
			
		||||
@@ -86,7 +86,7 @@
 | 
			
		||||
        </Button>
 | 
			
		||||
    {/if}
 | 
			
		||||
 | 
			
		||||
    <Collapsible.Content class="ml-2">
 | 
			
		||||
    <Collapsible.Content>
 | 
			
		||||
        {@render props.content()}
 | 
			
		||||
    </Collapsible.Content>
 | 
			
		||||
</Collapsible.Root>
 | 
			
		||||
 
 | 
			
		||||
@@ -312,10 +312,20 @@
 | 
			
		||||
            <div class="flex flex-row items-center gap-2" data-id={id}>
 | 
			
		||||
                <Move size="12" />
 | 
			
		||||
                <span class="grow">{$customLayers[id].name}</span>
 | 
			
		||||
                <Button variant="outline" onclick={() => (selectedLayerId = id)} class="p-1 h-7">
 | 
			
		||||
                <Button
 | 
			
		||||
                    variant="outline"
 | 
			
		||||
                    size="icon-sm"
 | 
			
		||||
                    onclick={() => (selectedLayerId = id)}
 | 
			
		||||
                    class="p-1 h-7"
 | 
			
		||||
                >
 | 
			
		||||
                    <Pencil size="16" />
 | 
			
		||||
                </Button>
 | 
			
		||||
                <Button variant="outline" onclick={() => deleteLayer(id)} class="p-1 h-7">
 | 
			
		||||
                <Button
 | 
			
		||||
                    variant="outline"
 | 
			
		||||
                    size="icon-sm"
 | 
			
		||||
                    onclick={() => deleteLayer(id)}
 | 
			
		||||
                    class="p-1 h-7"
 | 
			
		||||
                >
 | 
			
		||||
                    <Trash2 size="16" />
 | 
			
		||||
                </Button>
 | 
			
		||||
            </div>
 | 
			
		||||
@@ -338,17 +348,26 @@
 | 
			
		||||
            <div class="flex flex-row items-center gap-2" data-id={id}>
 | 
			
		||||
                <Move size="12" />
 | 
			
		||||
                <span class="grow">{$customLayers[id].name}</span>
 | 
			
		||||
                <Button variant="outline" onclick={() => (selectedLayerId = id)} class="p-1 h-7">
 | 
			
		||||
                <Button
 | 
			
		||||
                    variant="outline"
 | 
			
		||||
                    size="icon-sm"
 | 
			
		||||
                    onclick={() => (selectedLayerId = id)}
 | 
			
		||||
                    class="p-1 h-7"
 | 
			
		||||
                >
 | 
			
		||||
                    <Pencil size="16" />
 | 
			
		||||
                </Button>
 | 
			
		||||
                <Button variant="outline" onclick={() => deleteLayer(id)} class="p-1 h-7">
 | 
			
		||||
                <Button
 | 
			
		||||
                    variant="outline"
 | 
			
		||||
                    size="icon-sm"
 | 
			
		||||
                    onclick={() => deleteLayer(id)}
 | 
			
		||||
                    class="p-1 h-7"
 | 
			
		||||
                >
 | 
			
		||||
                    <Trash2 size="16" />
 | 
			
		||||
                </Button>
 | 
			
		||||
            </div>
 | 
			
		||||
        {/each}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <Card.Root>
 | 
			
		||||
    <Card.Root class="py-0 gap-0 shadow-none">
 | 
			
		||||
        <Card.Header class="p-3">
 | 
			
		||||
            <Card.Title class="text-base">
 | 
			
		||||
                {#if selectedLayerId}
 | 
			
		||||
 
 | 
			
		||||
@@ -179,9 +179,9 @@
 | 
			
		||||
                ? 'grid-rows-[1fr] grid-cols-[1fr]'
 | 
			
		||||
                : ''} {cancelEvents ? 'pointer-events-none' : ''}"
 | 
			
		||||
        >
 | 
			
		||||
            <ScrollArea>
 | 
			
		||||
            <ScrollArea class="overflow-hidden">
 | 
			
		||||
                <div class="h-fit">
 | 
			
		||||
                    <div class="p-2">
 | 
			
		||||
                    <div class="p-2 ml-1">
 | 
			
		||||
                        <LayerTree
 | 
			
		||||
                            layerTree={$selectedBasemapTree}
 | 
			
		||||
                            name="basemaps"
 | 
			
		||||
@@ -193,7 +193,7 @@
 | 
			
		||||
                        />
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <Separator class="w-full" />
 | 
			
		||||
                    <div class="p-2">
 | 
			
		||||
                    <div class="p-2 ml-1">
 | 
			
		||||
                        {#if $currentOverlays}
 | 
			
		||||
                            <LayerTree
 | 
			
		||||
                                layerTree={$selectedOverlayTree}
 | 
			
		||||
@@ -204,7 +204,7 @@
 | 
			
		||||
                        {/if}
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <Separator class="w-full" />
 | 
			
		||||
                    <div class="p-2">
 | 
			
		||||
                    <div class="p-2 ml-1">
 | 
			
		||||
                        {#if $currentOverpassQueries}
 | 
			
		||||
                            <LayerTree
 | 
			
		||||
                                layerTree={$selectedOverpassTree}
 | 
			
		||||
 
 | 
			
		||||
@@ -90,7 +90,7 @@
 | 
			
		||||
                    <Accordion.Item value="layer-selection" class="flex flex-col">
 | 
			
		||||
                        <Accordion.Trigger>{i18n._('layers.selection')}</Accordion.Trigger>
 | 
			
		||||
                        <Accordion.Content class="grow flex flex-col border rounded">
 | 
			
		||||
                            <div class="py-2 pl-1 pr-2">
 | 
			
		||||
                            <div class="py-2 pl-3 pr-2">
 | 
			
		||||
                                <LayerTree
 | 
			
		||||
                                    layerTree={basemapTree}
 | 
			
		||||
                                    name="basemapSettings"
 | 
			
		||||
@@ -99,7 +99,7 @@
 | 
			
		||||
                                />
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <Separator />
 | 
			
		||||
                            <div class="py-2 pl-1 pr-2">
 | 
			
		||||
                            <div class="py-2 pl-3 pr-2">
 | 
			
		||||
                                <LayerTree
 | 
			
		||||
                                    layerTree={overlayTree}
 | 
			
		||||
                                    name="overlaySettings"
 | 
			
		||||
@@ -108,7 +108,7 @@
 | 
			
		||||
                                />
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <Separator />
 | 
			
		||||
                            <div class="py-2 pl-1 pr-2">
 | 
			
		||||
                            <div class="py-2 pl-3 pr-2">
 | 
			
		||||
                                <LayerTree
 | 
			
		||||
                                    layerTree={overpassTree}
 | 
			
		||||
                                    name="overpassSettings"
 | 
			
		||||
@@ -130,7 +130,7 @@
 | 
			
		||||
                                    type="single"
 | 
			
		||||
                                    onValueChange={setOpacityFromSelection}
 | 
			
		||||
                                >
 | 
			
		||||
                                    <Select.Trigger class="h-8 mr-1">
 | 
			
		||||
                                    <Select.Trigger class="h-8 mr-1 w-full">
 | 
			
		||||
                                        {#if selectedOverlay}
 | 
			
		||||
                                            {#if isSelected($selectedOverlayTree, selectedOverlay)}
 | 
			
		||||
                                                {i18n._(`layers.label.${selectedOverlay}`)}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
    import { settings } from '$lib/logic/settings';
 | 
			
		||||
    import { i18n } from '$lib/i18n.svelte';
 | 
			
		||||
    import { onMount } from 'svelte';
 | 
			
		||||
    import ButtonWithTooltip from '$lib/components/ButtonWithTooltip.svelte';
 | 
			
		||||
 | 
			
		||||
    const { streetViewSource } = settings;
 | 
			
		||||
 | 
			
		||||
@@ -47,15 +48,21 @@
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<CustomControl class="w-[29px] h-[29px] shrink-0">
 | 
			
		||||
    <Tooltip class="w-full h-full" side="left" label={i18n._('menu.toggle_street_view')}>
 | 
			
		||||
        <Toggle
 | 
			
		||||
            bind:pressed={$streetViewEnabled}
 | 
			
		||||
            class="w-full h-full rounded p-0"
 | 
			
		||||
            aria-label={i18n._('menu.toggle_street_view')}
 | 
			
		||||
        >
 | 
			
		||||
            <PersonStanding size="22" />
 | 
			
		||||
        </Toggle>
 | 
			
		||||
    </Tooltip>
 | 
			
		||||
    <ButtonWithTooltip
 | 
			
		||||
        variant="ghost"
 | 
			
		||||
        class="w-full h-full"
 | 
			
		||||
        side="left"
 | 
			
		||||
        label={i18n._('menu.toggle_street_view')}
 | 
			
		||||
        onclick={() => {
 | 
			
		||||
            $streetViewEnabled = !$streetViewEnabled;
 | 
			
		||||
        }}
 | 
			
		||||
    >
 | 
			
		||||
        <PersonStanding
 | 
			
		||||
            size="22"
 | 
			
		||||
            class="size-5.5"
 | 
			
		||||
            color={$streetViewEnabled ? '#33b5e5' : 'currentColor'}
 | 
			
		||||
        />
 | 
			
		||||
    </ButtonWithTooltip>
 | 
			
		||||
</CustomControl>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
 
 | 
			
		||||
@@ -26,31 +26,31 @@
 | 
			
		||||
            ''}"
 | 
			
		||||
    >
 | 
			
		||||
        <ToolbarItem itemTool={Tool.ROUTING} label={i18n._('toolbar.routing.tooltip')}>
 | 
			
		||||
            <Pencil size="18" />
 | 
			
		||||
            <Pencil size="18" class="size-4.5" />
 | 
			
		||||
        </ToolbarItem>
 | 
			
		||||
        <ToolbarItem itemTool={Tool.WAYPOINT} label={i18n._('toolbar.waypoint.tooltip')}>
 | 
			
		||||
            <MapPin size="18" />
 | 
			
		||||
            <MapPin size="18" class="size-4.5" />
 | 
			
		||||
        </ToolbarItem>
 | 
			
		||||
        <ToolbarItem itemTool={Tool.SCISSORS} label={i18n._('toolbar.scissors.tooltip')}>
 | 
			
		||||
            <Scissors size="18" />
 | 
			
		||||
            <Scissors size="18" class="size-4.5" />
 | 
			
		||||
        </ToolbarItem>
 | 
			
		||||
        <ToolbarItem itemTool={Tool.TIME} label={i18n._('toolbar.time.tooltip')}>
 | 
			
		||||
            <CalendarClock size="18" />
 | 
			
		||||
            <CalendarClock size="18" class="size-4.5" />
 | 
			
		||||
        </ToolbarItem>
 | 
			
		||||
        <ToolbarItem itemTool={Tool.MERGE} label={i18n._('toolbar.merge.tooltip')}>
 | 
			
		||||
            <Group size="18" />
 | 
			
		||||
            <Group size="18" class="size-4.5" />
 | 
			
		||||
        </ToolbarItem>
 | 
			
		||||
        <ToolbarItem itemTool={Tool.EXTRACT} label={i18n._('toolbar.extract.tooltip')}>
 | 
			
		||||
            <Ungroup size="18" />
 | 
			
		||||
            <Ungroup size="18" class="size-4.5" />
 | 
			
		||||
        </ToolbarItem>
 | 
			
		||||
        <ToolbarItem itemTool={Tool.ELEVATION} label={i18n._('toolbar.elevation.button')}>
 | 
			
		||||
            <MountainSnow size="18" />
 | 
			
		||||
            <MountainSnow size="18" class="size-4.5" />
 | 
			
		||||
        </ToolbarItem>
 | 
			
		||||
        <ToolbarItem itemTool={Tool.REDUCE} label={i18n._('toolbar.reduce.tooltip')}>
 | 
			
		||||
            <Funnel size="18" />
 | 
			
		||||
            <Funnel size="18" class="size-4.5" />
 | 
			
		||||
        </ToolbarItem>
 | 
			
		||||
        <ToolbarItem itemTool={Tool.CLEAN} label={i18n._('toolbar.clean.tooltip')}>
 | 
			
		||||
            <SquareDashedMousePointer size="18" />
 | 
			
		||||
            <SquareDashedMousePointer size="18" class="size-4.5" />
 | 
			
		||||
        </ToolbarItem>
 | 
			
		||||
    </div>
 | 
			
		||||
    <ToolbarItemMenu class={props.class ?? ''} />
 | 
			
		||||
 
 | 
			
		||||
@@ -24,13 +24,13 @@
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<Tooltip.Provider>
 | 
			
		||||
    <Tooltip.Root delayDuration={300}>
 | 
			
		||||
    <Tooltip.Root>
 | 
			
		||||
        <Tooltip.Trigger>
 | 
			
		||||
            {#snippet child({ props })}
 | 
			
		||||
                <Button
 | 
			
		||||
                    {...props}
 | 
			
		||||
                    variant="ghost"
 | 
			
		||||
                    class="h-[26px] px-1 py-1.5 {$currentTool === itemTool ? 'bg-accent' : ''}"
 | 
			
		||||
                    class="size-[24px] {$currentTool === itemTool ? 'bg-accent' : ''}"
 | 
			
		||||
                    onclick={toggleTool}
 | 
			
		||||
                    aria-label={label}
 | 
			
		||||
                >
 | 
			
		||||
 
 | 
			
		||||
@@ -40,8 +40,8 @@
 | 
			
		||||
{#if $currentTool !== null}
 | 
			
		||||
    <div class="translate-x-1 h-full animate-in animate-out {className}">
 | 
			
		||||
        <div class="rounded-md shadow-md pointer-events-auto">
 | 
			
		||||
            <Card.Root class="rounded-md border-none">
 | 
			
		||||
                <Card.Content class="p-2.5">
 | 
			
		||||
            <Card.Root class="rounded-md border-none py-2.5">
 | 
			
		||||
                <Card.Content class="px-2.5">
 | 
			
		||||
                    {#if $currentTool === Tool.ROUTING}
 | 
			
		||||
                        <Routing {popup} {popupElement} bind:minimized={$minimizeRoutingMenu} />
 | 
			
		||||
                    {:else if $currentTool === Tool.SCISSORS}
 | 
			
		||||
 
 | 
			
		||||
@@ -95,22 +95,14 @@
 | 
			
		||||
        {:else if mergeType === MergeType.TRACES && !canMergeTraces}
 | 
			
		||||
            {i18n._('toolbar.merge.help_cannot_merge_traces')}
 | 
			
		||||
            {i18n._('toolbar.merge.selection_tip').split('{KEYBOARD_SHORTCUT}')[0]}
 | 
			
		||||
            <Shortcut
 | 
			
		||||
                ctrl={true}
 | 
			
		||||
                click={true}
 | 
			
		||||
                class="inline-flex text-muted-foreground text-xs border rounded p-0.5 gap-0"
 | 
			
		||||
            />
 | 
			
		||||
            <Shortcut ctrl={true} click={true} class="border" />
 | 
			
		||||
            {i18n._('toolbar.merge.selection_tip').split('{KEYBOARD_SHORTCUT}')[1]}
 | 
			
		||||
        {:else if mergeType === MergeType.CONTENTS && canMergeContents}
 | 
			
		||||
            {i18n._('toolbar.merge.help_merge_contents')}
 | 
			
		||||
        {:else if mergeType === MergeType.CONTENTS && !canMergeContents}
 | 
			
		||||
            {i18n._('toolbar.merge.help_cannot_merge_contents')}
 | 
			
		||||
            {i18n._('toolbar.merge.selection_tip').split('{KEYBOARD_SHORTCUT}')[0]}
 | 
			
		||||
            <Shortcut
 | 
			
		||||
                ctrl={true}
 | 
			
		||||
                click={true}
 | 
			
		||||
                class="inline-flex text-muted-foreground text-xs border rounded p-0.5 gap-0"
 | 
			
		||||
            />
 | 
			
		||||
            <Shortcut ctrl={true} click={true} class="border" />
 | 
			
		||||
            {i18n._('toolbar.merge.selection_tip').split('{KEYBOARD_SHORTCUT}')[1]}
 | 
			
		||||
        {/if}
 | 
			
		||||
    </Help>
 | 
			
		||||
 
 | 
			
		||||
@@ -110,7 +110,9 @@
 | 
			
		||||
 | 
			
		||||
    onDestroy(() => {
 | 
			
		||||
        if ($map) {
 | 
			
		||||
            fileStateCollectionObserver.destroy();
 | 
			
		||||
            if (fileStateCollectionObserver) {
 | 
			
		||||
                fileStateCollectionObserver.destroy();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mapCursor.notify(MapCursorState.TOOL_WITH_CROSSHAIR, false);
 | 
			
		||||
            $map.off('click', createFileWithPoint);
 | 
			
		||||
@@ -120,14 +122,14 @@
 | 
			
		||||
 | 
			
		||||
{#if minimizable && minimized}
 | 
			
		||||
    <div class="-m-1.5 -mb-2">
 | 
			
		||||
        <Button variant="ghost" class="px-1 h-[26px]" onclick={() => (minimized = false)}>
 | 
			
		||||
            <SquareArrowOutDownRight size="18" />
 | 
			
		||||
        <Button variant="ghost" size="icon-sm" class="size-6" onclick={() => (minimized = false)}>
 | 
			
		||||
            <SquareArrowOutDownRight size="18" class="size-4.5" />
 | 
			
		||||
        </Button>
 | 
			
		||||
    </div>
 | 
			
		||||
{:else}
 | 
			
		||||
    <div class="flex flex-col gap-3 w-full max-w-80 animate-in animate-out {className ?? ''}">
 | 
			
		||||
        <div class="flex flex-col gap-3">
 | 
			
		||||
            <Label class="flex flex-row justify-between items-center gap-2">
 | 
			
		||||
            <Label class="justify-between">
 | 
			
		||||
                <span class="flex flex-row items-center gap-1">
 | 
			
		||||
                    {#if $routing}
 | 
			
		||||
                        <Route size="16" />
 | 
			
		||||
@@ -137,13 +139,15 @@
 | 
			
		||||
                    {i18n._('toolbar.routing.use_routing')}
 | 
			
		||||
                </span>
 | 
			
		||||
                <Tooltip label={i18n._('toolbar.routing.use_routing_tooltip')}>
 | 
			
		||||
                    <Switch class="scale-90" bind:checked={$routing} />
 | 
			
		||||
                    <Shortcut slot="extra" key="F5" />
 | 
			
		||||
                    <Switch bind:checked={$routing} />
 | 
			
		||||
                    {#snippet extra()}
 | 
			
		||||
                        <Shortcut key="F5" />
 | 
			
		||||
                    {/snippet}
 | 
			
		||||
                </Tooltip>
 | 
			
		||||
            </Label>
 | 
			
		||||
            {#if $routing}
 | 
			
		||||
                <div class="flex flex-col gap-3" in:slide>
 | 
			
		||||
                    <Label class="flex flex-row justify-between items-center gap-2">
 | 
			
		||||
                    <Label class="justify-between">
 | 
			
		||||
                        <span class="shrink-0 flex flex-row items-center gap-1">
 | 
			
		||||
                            {#if $routingProfile.includes('bike') || $routingProfile.includes('motorcycle')}
 | 
			
		||||
                                <Bike size="16" />
 | 
			
		||||
@@ -171,12 +175,12 @@
 | 
			
		||||
                            </Select.Content>
 | 
			
		||||
                        </Select.Root>
 | 
			
		||||
                    </Label>
 | 
			
		||||
                    <Label class="flex flex-row justify-between items-center gap-2">
 | 
			
		||||
                    <Label class="justify-between">
 | 
			
		||||
                        <span class="flex flex-row gap-1">
 | 
			
		||||
                            <TriangleAlert size="16" />
 | 
			
		||||
                            {i18n._('toolbar.routing.allow_private')}
 | 
			
		||||
                        </span>
 | 
			
		||||
                        <Switch class="scale-90" bind:checked={$privateRoads} />
 | 
			
		||||
                        <Switch bind:checked={$privateRoads} />
 | 
			
		||||
                    </Label>
 | 
			
		||||
                </div>
 | 
			
		||||
            {/if}
 | 
			
		||||
@@ -185,7 +189,7 @@
 | 
			
		||||
            <ButtonWithTooltip
 | 
			
		||||
                label={i18n._('toolbar.routing.reverse.tooltip')}
 | 
			
		||||
                variant="outline"
 | 
			
		||||
                class="flex flex-row gap-1 text-xs px-2"
 | 
			
		||||
                class="gap-1 text-xs"
 | 
			
		||||
                disabled={!validSelection}
 | 
			
		||||
                onclick={fileActions.reverseSelection}
 | 
			
		||||
            >
 | 
			
		||||
@@ -194,7 +198,7 @@
 | 
			
		||||
            <ButtonWithTooltip
 | 
			
		||||
                label={i18n._('toolbar.routing.route_back_to_start.tooltip')}
 | 
			
		||||
                variant="outline"
 | 
			
		||||
                class="flex flex-row gap-1 text-xs px-2"
 | 
			
		||||
                class="gap-1 text-xs"
 | 
			
		||||
                disabled={!validSelection}
 | 
			
		||||
                onclick={() => {
 | 
			
		||||
                    const selected = selection.getOrderedSelection();
 | 
			
		||||
@@ -230,7 +234,7 @@
 | 
			
		||||
            <ButtonWithTooltip
 | 
			
		||||
                label={i18n._('toolbar.routing.round_trip.tooltip')}
 | 
			
		||||
                variant="outline"
 | 
			
		||||
                class="flex flex-row gap-1 text-xs px-2"
 | 
			
		||||
                class="gap-1 text-xs"
 | 
			
		||||
                disabled={!validSelection}
 | 
			
		||||
                onclick={fileActions.createRoundTripForSelection}
 | 
			
		||||
            >
 | 
			
		||||
@@ -247,7 +251,8 @@
 | 
			
		||||
            </Help>
 | 
			
		||||
            <Button
 | 
			
		||||
                variant="ghost"
 | 
			
		||||
                class="px-1 h-6"
 | 
			
		||||
                size="icon-sm"
 | 
			
		||||
                class="size-6"
 | 
			
		||||
                onclick={() => {
 | 
			
		||||
                    if (minimizable) {
 | 
			
		||||
                        minimized = true;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,80 +1,82 @@
 | 
			
		||||
<script lang="ts" module>
 | 
			
		||||
    import { cn, type WithElementRef } from '$lib/utils.js';
 | 
			
		||||
    import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
 | 
			
		||||
    import { type VariantProps, tv } from 'tailwind-variants';
 | 
			
		||||
	import { cn, type WithElementRef } from "$lib/utils.js";
 | 
			
		||||
	import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
 | 
			
		||||
	import { type VariantProps, tv } from "tailwind-variants";
 | 
			
		||||
 | 
			
		||||
    export const buttonVariants = tv({
 | 
			
		||||
        base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-all focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
 | 
			
		||||
        variants: {
 | 
			
		||||
            variant: {
 | 
			
		||||
                default: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
 | 
			
		||||
                destructive:
 | 
			
		||||
                    'bg-destructive shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white',
 | 
			
		||||
                outline:
 | 
			
		||||
                    'bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border',
 | 
			
		||||
                secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
 | 
			
		||||
                ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
 | 
			
		||||
                link: 'text-primary underline-offset-4 hover:underline',
 | 
			
		||||
            },
 | 
			
		||||
            size: {
 | 
			
		||||
                default: 'h-9 px-4 py-2 has-[>svg]:px-3',
 | 
			
		||||
                sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5',
 | 
			
		||||
                lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
 | 
			
		||||
                icon: 'size-9',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        defaultVariants: {
 | 
			
		||||
            variant: 'default',
 | 
			
		||||
            size: 'default',
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
	export const buttonVariants = tv({
 | 
			
		||||
		base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-all focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
 | 
			
		||||
		variants: {
 | 
			
		||||
			variant: {
 | 
			
		||||
				default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
 | 
			
		||||
				destructive:
 | 
			
		||||
					"bg-destructive shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white",
 | 
			
		||||
				outline:
 | 
			
		||||
					"bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border",
 | 
			
		||||
				secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
 | 
			
		||||
				ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
 | 
			
		||||
				link: "text-primary underline-offset-4 hover:underline",
 | 
			
		||||
			},
 | 
			
		||||
			size: {
 | 
			
		||||
				default: "h-9 px-4 py-2 has-[>svg]:px-3",
 | 
			
		||||
				sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
 | 
			
		||||
				lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
 | 
			
		||||
				icon: "size-9",
 | 
			
		||||
				"icon-sm": "size-8",
 | 
			
		||||
				"icon-lg": "size-10",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		defaultVariants: {
 | 
			
		||||
			variant: "default",
 | 
			
		||||
			size: "default",
 | 
			
		||||
		},
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
    export type ButtonVariant = VariantProps<typeof buttonVariants>['variant'];
 | 
			
		||||
    export type ButtonSize = VariantProps<typeof buttonVariants>['size'];
 | 
			
		||||
	export type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
 | 
			
		||||
	export type ButtonSize = VariantProps<typeof buttonVariants>["size"];
 | 
			
		||||
 | 
			
		||||
    export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
 | 
			
		||||
        WithElementRef<HTMLAnchorAttributes> & {
 | 
			
		||||
            variant?: ButtonVariant;
 | 
			
		||||
            size?: ButtonSize;
 | 
			
		||||
        };
 | 
			
		||||
	export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
 | 
			
		||||
		WithElementRef<HTMLAnchorAttributes> & {
 | 
			
		||||
			variant?: ButtonVariant;
 | 
			
		||||
			size?: ButtonSize;
 | 
			
		||||
		};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    let {
 | 
			
		||||
        class: className,
 | 
			
		||||
        variant = 'default',
 | 
			
		||||
        size = 'default',
 | 
			
		||||
        ref = $bindable(null),
 | 
			
		||||
        href = undefined,
 | 
			
		||||
        type = 'button',
 | 
			
		||||
        disabled,
 | 
			
		||||
        children,
 | 
			
		||||
        ...restProps
 | 
			
		||||
    }: ButtonProps = $props();
 | 
			
		||||
	let {
 | 
			
		||||
		class: className,
 | 
			
		||||
		variant = "default",
 | 
			
		||||
		size = "default",
 | 
			
		||||
		ref = $bindable(null),
 | 
			
		||||
		href = undefined,
 | 
			
		||||
		type = "button",
 | 
			
		||||
		disabled,
 | 
			
		||||
		children,
 | 
			
		||||
		...restProps
 | 
			
		||||
	}: ButtonProps = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
{#if href}
 | 
			
		||||
    <a
 | 
			
		||||
        bind:this={ref}
 | 
			
		||||
        data-slot="button"
 | 
			
		||||
        class={cn(buttonVariants({ variant, size }), className)}
 | 
			
		||||
        href={disabled ? undefined : href}
 | 
			
		||||
        aria-disabled={disabled}
 | 
			
		||||
        role={disabled ? 'link' : undefined}
 | 
			
		||||
        tabindex={disabled ? -1 : undefined}
 | 
			
		||||
        {...restProps}
 | 
			
		||||
    >
 | 
			
		||||
        {@render children?.()}
 | 
			
		||||
    </a>
 | 
			
		||||
	<a
 | 
			
		||||
		bind:this={ref}
 | 
			
		||||
		data-slot="button"
 | 
			
		||||
		class={cn(buttonVariants({ variant, size }), className)}
 | 
			
		||||
		href={disabled ? undefined : href}
 | 
			
		||||
		aria-disabled={disabled}
 | 
			
		||||
		role={disabled ? "link" : undefined}
 | 
			
		||||
		tabindex={disabled ? -1 : undefined}
 | 
			
		||||
		{...restProps}
 | 
			
		||||
	>
 | 
			
		||||
		{@render children?.()}
 | 
			
		||||
	</a>
 | 
			
		||||
{:else}
 | 
			
		||||
    <button
 | 
			
		||||
        bind:this={ref}
 | 
			
		||||
        data-slot="button"
 | 
			
		||||
        class={cn(buttonVariants({ variant, size }), className)}
 | 
			
		||||
        {type}
 | 
			
		||||
        {disabled}
 | 
			
		||||
        {...restProps}
 | 
			
		||||
    >
 | 
			
		||||
        {@render children?.()}
 | 
			
		||||
    </button>
 | 
			
		||||
	<button
 | 
			
		||||
		bind:this={ref}
 | 
			
		||||
		data-slot="button"
 | 
			
		||||
		class={cn(buttonVariants({ variant, size }), className)}
 | 
			
		||||
		{type}
 | 
			
		||||
		{disabled}
 | 
			
		||||
		{...restProps}
 | 
			
		||||
	>
 | 
			
		||||
		{@render children?.()}
 | 
			
		||||
	</button>
 | 
			
		||||
{/if}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@
 | 
			
		||||
		{@render children?.()}
 | 
			
		||||
		{#if showCloseButton}
 | 
			
		||||
			<DialogPrimitive.Close
 | 
			
		||||
				class="ring-offset-background focus:ring-ring rounded-xs focus:outline-hidden absolute right-4 top-4 opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
 | 
			
		||||
				class="ring-offset-background focus:ring-ring rounded-xs focus:outline-hidden absolute end-4 top-4 opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
 | 
			
		||||
			>
 | 
			
		||||
				<XIcon />
 | 
			
		||||
				<span class="sr-only">Close</span>
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
		data-slot="dropdown-menu-content"
 | 
			
		||||
		{sideOffset}
 | 
			
		||||
		class={cn(
 | 
			
		||||
			"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 max-h-(--radix-dropdown-menu-content-available-height) origin-(--radix-dropdown-menu-content-transform-origin) z-50 min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border p-1 shadow-md",
 | 
			
		||||
			"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 max-h-(--bits-dropdown-menu-content-available-height) origin-(--bits-dropdown-menu-content-transform-origin) z-50 min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border p-1 shadow-md outline-none",
 | 
			
		||||
			className
 | 
			
		||||
		)}
 | 
			
		||||
		{...restProps}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
	bind:ref
 | 
			
		||||
	data-slot="dropdown-menu-sub-content"
 | 
			
		||||
	class={cn(
 | 
			
		||||
		"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--radix-dropdown-menu-content-transform-origin) z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg",
 | 
			
		||||
		"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--bits-dropdown-menu-content-transform-origin) z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg",
 | 
			
		||||
		className
 | 
			
		||||
	)}
 | 
			
		||||
	{...restProps}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
		type,
 | 
			
		||||
		files = $bindable(),
 | 
			
		||||
		class: className,
 | 
			
		||||
		"data-slot": dataSlot = "input",
 | 
			
		||||
		...restProps
 | 
			
		||||
	}: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
@@ -22,9 +23,9 @@
 | 
			
		||||
{#if type === "file"}
 | 
			
		||||
	<input
 | 
			
		||||
		bind:this={ref}
 | 
			
		||||
		data-slot="input"
 | 
			
		||||
		data-slot={dataSlot}
 | 
			
		||||
		class={cn(
 | 
			
		||||
			"selection:bg-primary dark:bg-input/30 selection:text-primary-foreground border-input ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 pt-1.5 text-sm font-medium outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
 | 
			
		||||
			"selection:bg-primary dark:bg-input/30 selection:text-primary-foreground border-input ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 pt-1.5 text-sm font-medium outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50",
 | 
			
		||||
			"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
 | 
			
		||||
			"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
 | 
			
		||||
			className
 | 
			
		||||
@@ -37,7 +38,7 @@
 | 
			
		||||
{:else}
 | 
			
		||||
	<input
 | 
			
		||||
		bind:this={ref}
 | 
			
		||||
		data-slot="input"
 | 
			
		||||
		data-slot={dataSlot}
 | 
			
		||||
		class={cn(
 | 
			
		||||
			"border-input bg-background selection:bg-primary dark:bg-input/30 selection:text-primary-foreground ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
 | 
			
		||||
			"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								website/src/lib/components/ui/kbd/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								website/src/lib/components/ui/kbd/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
import Root from "./kbd.svelte";
 | 
			
		||||
import Group from "./kbd-group.svelte";
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
	Root,
 | 
			
		||||
	Group,
 | 
			
		||||
	//
 | 
			
		||||
	Root as Kbd,
 | 
			
		||||
	Group as KbdGroup,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										10
									
								
								website/src/lib/components/ui/kbd/kbd-group.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								website/src/lib/components/ui/kbd/kbd-group.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
	import { cn } from "$lib/utils.js";
 | 
			
		||||
	import type { HTMLAttributes } from "svelte/elements";
 | 
			
		||||
 | 
			
		||||
	let { class: className, children, ...restProps }: HTMLAttributes<HTMLElement> = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<kbd data-slot="kbd-group" class={cn("inline-flex items-center gap-1", className)} {...restProps}>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</kbd>
 | 
			
		||||
							
								
								
									
										19
									
								
								website/src/lib/components/ui/kbd/kbd.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								website/src/lib/components/ui/kbd/kbd.svelte
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
	import { cn } from "$lib/utils.js";
 | 
			
		||||
	import type { HTMLAttributes } from "svelte/elements";
 | 
			
		||||
 | 
			
		||||
	let { class: className, children, ...restProps }: HTMLAttributes<HTMLElement> = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<kbd
 | 
			
		||||
	data-slot="kbd"
 | 
			
		||||
	class={cn(
 | 
			
		||||
		"bg-muted text-muted-foreground pointer-events-none inline-flex h-5 w-fit min-w-5 select-none items-center justify-center gap-1 rounded-sm px-1 font-sans text-xs font-medium",
 | 
			
		||||
		"[&_svg:not([class*='size-'])]:size-3",
 | 
			
		||||
		"[[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10",
 | 
			
		||||
		className
 | 
			
		||||
	)}
 | 
			
		||||
	{...restProps}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</kbd>
 | 
			
		||||
@@ -1,40 +1,40 @@
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
    import { ScrollArea as ScrollAreaPrimitive } from 'bits-ui';
 | 
			
		||||
    import { Scrollbar } from './index.js';
 | 
			
		||||
    import { cn, type WithoutChild } from '$lib/utils.js';
 | 
			
		||||
	import { ScrollArea as ScrollAreaPrimitive } from "bits-ui";
 | 
			
		||||
	import { Scrollbar } from "./index.js";
 | 
			
		||||
	import { cn, type WithoutChild } from "$lib/utils.js";
 | 
			
		||||
 | 
			
		||||
    let {
 | 
			
		||||
        ref = $bindable(null),
 | 
			
		||||
        class: className,
 | 
			
		||||
        orientation = 'vertical',
 | 
			
		||||
        scrollbarXClasses = '',
 | 
			
		||||
        scrollbarYClasses = '',
 | 
			
		||||
        children,
 | 
			
		||||
        ...restProps
 | 
			
		||||
    }: WithoutChild<ScrollAreaPrimitive.RootProps> & {
 | 
			
		||||
        orientation?: 'vertical' | 'horizontal' | 'both' | undefined;
 | 
			
		||||
        scrollbarXClasses?: string | undefined;
 | 
			
		||||
        scrollbarYClasses?: string | undefined;
 | 
			
		||||
    } = $props();
 | 
			
		||||
	let {
 | 
			
		||||
		ref = $bindable(null),
 | 
			
		||||
		class: className,
 | 
			
		||||
		orientation = "vertical",
 | 
			
		||||
		scrollbarXClasses = "",
 | 
			
		||||
		scrollbarYClasses = "",
 | 
			
		||||
		children,
 | 
			
		||||
		...restProps
 | 
			
		||||
	}: WithoutChild<ScrollAreaPrimitive.RootProps> & {
 | 
			
		||||
		orientation?: "vertical" | "horizontal" | "both" | undefined;
 | 
			
		||||
		scrollbarXClasses?: string | undefined;
 | 
			
		||||
		scrollbarYClasses?: string | undefined;
 | 
			
		||||
	} = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<ScrollAreaPrimitive.Root
 | 
			
		||||
    bind:ref
 | 
			
		||||
    data-slot="scroll-area"
 | 
			
		||||
    class={cn('relative overflow-hidden', className)}
 | 
			
		||||
    {...restProps}
 | 
			
		||||
	bind:ref
 | 
			
		||||
	data-slot="scroll-area"
 | 
			
		||||
	class={cn("relative", className)}
 | 
			
		||||
	{...restProps}
 | 
			
		||||
>
 | 
			
		||||
    <ScrollAreaPrimitive.Viewport
 | 
			
		||||
        data-slot="scroll-area-viewport"
 | 
			
		||||
        class="ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-4"
 | 
			
		||||
    >
 | 
			
		||||
        {@render children?.()}
 | 
			
		||||
    </ScrollAreaPrimitive.Viewport>
 | 
			
		||||
    {#if orientation === 'vertical' || orientation === 'both'}
 | 
			
		||||
        <Scrollbar orientation="vertical" class={scrollbarYClasses} />
 | 
			
		||||
    {/if}
 | 
			
		||||
    {#if orientation === 'horizontal' || orientation === 'both'}
 | 
			
		||||
        <Scrollbar orientation="horizontal" class={scrollbarXClasses} />
 | 
			
		||||
    {/if}
 | 
			
		||||
    <ScrollAreaPrimitive.Corner />
 | 
			
		||||
	<ScrollAreaPrimitive.Viewport
 | 
			
		||||
		data-slot="scroll-area-viewport"
 | 
			
		||||
		class="ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] focus-visible:outline-1 focus-visible:ring-4"
 | 
			
		||||
	>
 | 
			
		||||
		{@render children?.()}
 | 
			
		||||
	</ScrollAreaPrimitive.Viewport>
 | 
			
		||||
	{#if orientation === "vertical" || orientation === "both"}
 | 
			
		||||
		<Scrollbar orientation="vertical" class={scrollbarYClasses} />
 | 
			
		||||
	{/if}
 | 
			
		||||
	{#if orientation === "horizontal" || orientation === "both"}
 | 
			
		||||
		<Scrollbar orientation="horizontal" class={scrollbarXClasses} />
 | 
			
		||||
	{/if}
 | 
			
		||||
	<ScrollAreaPrimitive.Corner />
 | 
			
		||||
</ScrollAreaPrimitive.Root>
 | 
			
		||||
 
 | 
			
		||||
@@ -5,13 +5,14 @@
 | 
			
		||||
	let {
 | 
			
		||||
		ref = $bindable(null),
 | 
			
		||||
		class: className,
 | 
			
		||||
		"data-slot": dataSlot = "separator",
 | 
			
		||||
		...restProps
 | 
			
		||||
	}: SeparatorPrimitive.RootProps = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<SeparatorPrimitive.Root
 | 
			
		||||
	bind:ref
 | 
			
		||||
	data-slot="separator"
 | 
			
		||||
	data-slot={dataSlot}
 | 
			
		||||
	class={cn(
 | 
			
		||||
		"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px",
 | 
			
		||||
		className
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,6 @@
 | 
			
		||||
<Sonner
 | 
			
		||||
	theme={mode.current}
 | 
			
		||||
	class="toaster group"
 | 
			
		||||
	style="--normal-bg: var(--popover); --normal-text: var(--popover-foreground); --normal-border: var(--border);"
 | 
			
		||||
	style="--normal-bg: var(--color-popover); --normal-text: var(--color-popover-foreground); --normal-border: var(--color-border);"
 | 
			
		||||
	{...restProps}
 | 
			
		||||
/>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,13 +6,14 @@
 | 
			
		||||
		ref = $bindable(null),
 | 
			
		||||
		value = $bindable(),
 | 
			
		||||
		class: className,
 | 
			
		||||
		"data-slot": dataSlot = "textarea",
 | 
			
		||||
		...restProps
 | 
			
		||||
	}: WithoutChildren<WithElementRef<HTMLTextareaAttributes>> = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<textarea
 | 
			
		||||
	bind:this={ref}
 | 
			
		||||
	data-slot="textarea"
 | 
			
		||||
	data-slot={dataSlot}
 | 
			
		||||
	class={cn(
 | 
			
		||||
		"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 field-sizing-content shadow-xs flex min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
 | 
			
		||||
		className
 | 
			
		||||
 
 | 
			
		||||
@@ -34,9 +34,9 @@
 | 
			
		||||
					class={cn(
 | 
			
		||||
						"bg-primary z-50 size-2.5 rotate-45 rounded-[2px]",
 | 
			
		||||
						"data-[side=top]:translate-x-1/2 data-[side=top]:translate-y-[calc(-50%_+_2px)]",
 | 
			
		||||
						"data-[side=bottom]:-translate-y-[calc(-50%_+_1px)] data-[side=bottom]:translate-x-1/2",
 | 
			
		||||
						"data-[side=bottom]:-translate-x-1/2 data-[side=bottom]:-translate-y-[calc(-50%_+_1px)]",
 | 
			
		||||
						"data-[side=right]:translate-x-[calc(50%_+_2px)] data-[side=right]:translate-y-1/2",
 | 
			
		||||
						"data-[side=left]:translate-y-[calc(50%_-_3px)]",
 | 
			
		||||
						"data-[side=left]:-translate-y-[calc(50%_-_3px)]",
 | 
			
		||||
						arrowClasses
 | 
			
		||||
					)}
 | 
			
		||||
					{...props}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user