generated from tpl/obsidian-sample-plugin
			Add bookshelf view
This commit is contained in:
		
							parent
							
								
									31cfa881c7
								
							
						
					
					
						commit
						5c73b8871c
					
				| 
						 | 
				
			
			@ -2,6 +2,7 @@ import esbuild from "esbuild";
 | 
			
		|||
import process from "process";
 | 
			
		||||
import builtins from "builtin-modules";
 | 
			
		||||
import esbuildSvelte from "esbuild-svelte";
 | 
			
		||||
import { sassPlugin } from "esbuild-sass-plugin";
 | 
			
		||||
import { sveltePreprocess } from "svelte-preprocess";
 | 
			
		||||
import dotenv from "dotenv";
 | 
			
		||||
import dotenvExpand from "dotenv-expand";
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +61,7 @@ const context = await esbuild.context({
 | 
			
		|||
					!warning.filename?.includes("node_modules"),
 | 
			
		||||
			},
 | 
			
		||||
		}),
 | 
			
		||||
		sassPlugin(),
 | 
			
		||||
		{
 | 
			
		||||
			name: "copy-plugin",
 | 
			
		||||
			setup(build) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,6 +45,7 @@
 | 
			
		|||
	"dependencies": {
 | 
			
		||||
		"chart.js": "^4.5.0",
 | 
			
		||||
		"chroma-js": "^3.1.2",
 | 
			
		||||
		"esbuild-sass-plugin": "^3.3.1",
 | 
			
		||||
		"uuid": "^11.1.0",
 | 
			
		||||
		"yaml": "^2.8.0",
 | 
			
		||||
		"zod": "^3.25.67"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										248
									
								
								pnpm-lock.yaml
								
								
								
								
							
							
						
						
									
										248
									
								
								pnpm-lock.yaml
								
								
								
								
							| 
						 | 
				
			
			@ -14,6 +14,9 @@ importers:
 | 
			
		|||
      chroma-js:
 | 
			
		||||
        specifier: ^3.1.2
 | 
			
		||||
        version: 3.1.2
 | 
			
		||||
      esbuild-sass-plugin:
 | 
			
		||||
        specifier: ^3.3.1
 | 
			
		||||
        version: 3.3.1(esbuild@0.17.3)(sass-embedded@1.89.2)
 | 
			
		||||
      uuid:
 | 
			
		||||
        specifier: ^11.1.0
 | 
			
		||||
        version: 11.1.0
 | 
			
		||||
| 
						 | 
				
			
			@ -112,6 +115,9 @@ packages:
 | 
			
		|||
    resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
 | 
			
		||||
    engines: {node: '>=6.0.0'}
 | 
			
		||||
 | 
			
		||||
  '@bufbuild/protobuf@2.6.0':
 | 
			
		||||
    resolution: {integrity: sha512-6cuonJVNOIL7lTj5zgo/Rc2bKAo4/GvN+rKCrUj7GdEHRzCk8zKOfFwUsL9nAVk5rSIsRmlgcpLzTRysopEeeg==}
 | 
			
		||||
 | 
			
		||||
  '@codemirror/state@6.5.2':
 | 
			
		||||
    resolution: {integrity: sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -576,6 +582,9 @@ packages:
 | 
			
		|||
    resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
 | 
			
		||||
    engines: {node: '>=8'}
 | 
			
		||||
 | 
			
		||||
  buffer-builder@0.2.0:
 | 
			
		||||
    resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==}
 | 
			
		||||
 | 
			
		||||
  builtin-modules@3.3.0:
 | 
			
		||||
    resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
 | 
			
		||||
    engines: {node: '>=6'}
 | 
			
		||||
| 
						 | 
				
			
			@ -632,6 +641,9 @@ packages:
 | 
			
		|||
  color-name@1.1.4:
 | 
			
		||||
    resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
 | 
			
		||||
 | 
			
		||||
  colorjs.io@0.5.2:
 | 
			
		||||
    resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
 | 
			
		||||
 | 
			
		||||
  concat-map@0.0.1:
 | 
			
		||||
    resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -730,6 +742,12 @@ packages:
 | 
			
		|||
    resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
 | 
			
		||||
    engines: {node: '>= 0.4'}
 | 
			
		||||
 | 
			
		||||
  esbuild-sass-plugin@3.3.1:
 | 
			
		||||
    resolution: {integrity: sha512-SnO1ls+d52n6j8gRRpjexXI8MsHEaumS0IdDHaYM29Y6gakzZYMls6i9ql9+AWMSQk/eryndmUpXEgT34QrX1A==}
 | 
			
		||||
    peerDependencies:
 | 
			
		||||
      esbuild: '>=0.20.1'
 | 
			
		||||
      sass-embedded: ^1.71.1
 | 
			
		||||
 | 
			
		||||
  esbuild-svelte@0.9.3:
 | 
			
		||||
    resolution: {integrity: sha512-CgEcGY1r/d16+aggec3czoFBEBaYIrFOnMxpsO6fWNaNEqHregPN5DLAPZDqrL7rXDNplW+WMu8s3GMq9FqgJA==}
 | 
			
		||||
    engines: {node: '>=18'}
 | 
			
		||||
| 
						 | 
				
			
			@ -1339,6 +1357,9 @@ packages:
 | 
			
		|||
    peerDependencies:
 | 
			
		||||
      svelte: ^5.7.0
 | 
			
		||||
 | 
			
		||||
  rxjs@7.8.2:
 | 
			
		||||
    resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==}
 | 
			
		||||
 | 
			
		||||
  sade@1.8.1:
 | 
			
		||||
    resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
 | 
			
		||||
    engines: {node: '>=6'}
 | 
			
		||||
| 
						 | 
				
			
			@ -1347,6 +1368,9 @@ packages:
 | 
			
		|||
    resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
 | 
			
		||||
    engines: {node: '>=0.4'}
 | 
			
		||||
 | 
			
		||||
  safe-identifier@0.4.2:
 | 
			
		||||
    resolution: {integrity: sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==}
 | 
			
		||||
 | 
			
		||||
  safe-push-apply@1.0.0:
 | 
			
		||||
    resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
 | 
			
		||||
    engines: {node: '>= 0.4'}
 | 
			
		||||
| 
						 | 
				
			
			@ -1355,6 +1379,107 @@ packages:
 | 
			
		|||
    resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
 | 
			
		||||
    engines: {node: '>= 0.4'}
 | 
			
		||||
 | 
			
		||||
  sass-embedded-android-arm64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-+pq7a7AUpItNyPu61sRlP6G2A8pSPpyazASb+8AK2pVlFayCSPAEgpwpCE9A2/Xj86xJZeMizzKUHxM2CBCUxA==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [arm64]
 | 
			
		||||
    os: [android]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-android-arm@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-oHAPTboBHRZlDBhyRB6dvDKh4KvFs+DZibDHXbkSI6dBZxMTT+Yb2ivocHnctVGucKTLQeT7+OM5DjWHyynL/A==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [arm]
 | 
			
		||||
    os: [android]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-android-riscv64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-HfJJWp/S6XSYvlGAqNdakeEMPOdhBkj2s2lN6SHnON54rahKem+z9pUbCriUJfM65Z90lakdGuOfidY61R9TYg==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [riscv64]
 | 
			
		||||
    os: [android]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-android-x64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-BGPzq53VH5z5HN8de6jfMqJjnRe1E6sfnCWFd4pK+CAiuM7iw5Fx6BQZu3ikfI1l2GY0y6pRXzsVLdp/j4EKEA==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [x64]
 | 
			
		||||
    os: [android]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-darwin-arm64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-UCm3RL/tzMpG7DsubARsvGUNXC5pgfQvP+RRFJo9XPIi6elopY5B6H4m9dRYDpHA+scjVthdiDwkPYr9+S/KGw==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [arm64]
 | 
			
		||||
    os: [darwin]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-darwin-x64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-D9WxtDY5VYtMApXRuhQK9VkPHB8R79NIIR6xxVlN2MIdEid/TZWi1MHNweieETXhWGrKhRKglwnHxxyKdJYMnA==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [x64]
 | 
			
		||||
    os: [darwin]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-arm64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-2N4WW5LLsbtrWUJ7iTpjvhajGIbmDR18ZzYRywHdMLpfdPApuHPMDF5CYzHbS+LLx2UAx7CFKBnj5LLjY6eFgQ==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [arm64]
 | 
			
		||||
    os: [linux]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-arm@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-leP0t5U4r95dc90o8TCWfxNXwMAsQhpWxTkdtySDpngoqtTy3miMd7EYNYd1znI0FN1CBaUvbdCMbnbPwygDlA==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [arm]
 | 
			
		||||
    os: [linux]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-musl-arm64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-nTyuaBX6U1A/cG7WJh0pKD1gY8hbg1m2SnzsyoFG+exQ0lBX/lwTLHq3nyhF+0atv7YYhYKbmfz+sjPP8CZ9lw==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [arm64]
 | 
			
		||||
    os: [linux]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-musl-arm@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-Z6gG2FiVEEdxYHRi2sS5VIYBmp17351bWtOCUZ/thBM66+e70yiN6Eyqjz80DjL8haRUegNQgy9ZJqsLAAmr9g==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [arm]
 | 
			
		||||
    os: [linux]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-musl-riscv64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-N6oul+qALO0SwGY8JW7H/Vs0oZIMrRMBM4GqX3AjM/6y8JsJRxkAwnfd0fDyK+aICMFarDqQonQNIx99gdTZqw==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [riscv64]
 | 
			
		||||
    os: [linux]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-musl-x64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-K+FmWcdj/uyP8GiG9foxOCPfb5OAZG0uSVq80DKgVSC0U44AdGjvAvVZkrgFEcZ6cCqlNC2JfYmslB5iqdL7tg==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [x64]
 | 
			
		||||
    os: [linux]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-riscv64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-g9nTbnD/3yhOaskeqeBQETbtfDQWRgsjHok6bn7DdAuwBsyrR3JlSFyqKc46pn9Xxd9SQQZU8AzM4IR+sY0A0w==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [riscv64]
 | 
			
		||||
    os: [linux]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-x64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-Ax7dKvzncyQzIl4r7012KCMBvJzOz4uwSNoyoM5IV6y5I1f5hEwI25+U4WfuTqdkv42taCMgpjZbh9ERr6JVMQ==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [x64]
 | 
			
		||||
    os: [linux]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-win32-arm64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-j96iJni50ZUsfD6tRxDQE2QSYQ2WrfHxeiyAXf41Kw0V4w5KYR/Sf6rCZQLMTUOHnD16qTMVpQi20LQSqf4WGg==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [arm64]
 | 
			
		||||
    os: [win32]
 | 
			
		||||
 | 
			
		||||
  sass-embedded-win32-x64@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-cS2j5ljdkQsb4PaORiClaVYynE9OAPZG/XjbOMxpQmjRIf7UroY4PEIH+Waf+y47PfXFX9SyxhYuw2NIKGbEng==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
    cpu: [x64]
 | 
			
		||||
    os: [win32]
 | 
			
		||||
 | 
			
		||||
  sass-embedded@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-Ack2K8rc57kCFcYlf3HXpZEJFNUX8xd8DILldksREmYXQkRHI879yy8q4mRDJgrojkySMZqmmmW1NxrFxMsYaA==}
 | 
			
		||||
    engines: {node: '>=16.0.0'}
 | 
			
		||||
    hasBin: true
 | 
			
		||||
 | 
			
		||||
  sass@1.89.2:
 | 
			
		||||
    resolution: {integrity: sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==}
 | 
			
		||||
    engines: {node: '>=14.0.0'}
 | 
			
		||||
| 
						 | 
				
			
			@ -1480,6 +1605,10 @@ packages:
 | 
			
		|||
    resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
 | 
			
		||||
    engines: {node: '>=8'}
 | 
			
		||||
 | 
			
		||||
  supports-color@8.1.1:
 | 
			
		||||
    resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
 | 
			
		||||
    engines: {node: '>=10'}
 | 
			
		||||
 | 
			
		||||
  supports-preserve-symlinks-flag@1.0.0:
 | 
			
		||||
    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
 | 
			
		||||
    engines: {node: '>= 0.4'}
 | 
			
		||||
| 
						 | 
				
			
			@ -1539,6 +1668,14 @@ packages:
 | 
			
		|||
    resolution: {integrity: sha512-TF+8irl7rpj3+fpaLuPRX5BqReTAqckp0Fumxa/mCeK3fo0/MnBb9W/Z2bLwtqj3C3r5Lm6NKIAw7YrgIv1Fwg==}
 | 
			
		||||
    engines: {node: '>=18'}
 | 
			
		||||
 | 
			
		||||
  sync-child-process@1.0.2:
 | 
			
		||||
    resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==}
 | 
			
		||||
    engines: {node: '>=16.0.0'}
 | 
			
		||||
 | 
			
		||||
  sync-message-port@1.1.3:
 | 
			
		||||
    resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==}
 | 
			
		||||
    engines: {node: '>=16.0.0'}
 | 
			
		||||
 | 
			
		||||
  to-regex-range@5.0.1:
 | 
			
		||||
    resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
 | 
			
		||||
    engines: {node: '>=8.0'}
 | 
			
		||||
| 
						 | 
				
			
			@ -1602,6 +1739,9 @@ packages:
 | 
			
		|||
  validate-npm-package-license@3.0.4:
 | 
			
		||||
    resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
 | 
			
		||||
 | 
			
		||||
  varint@6.0.0:
 | 
			
		||||
    resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
 | 
			
		||||
 | 
			
		||||
  w3c-keyname@2.2.8:
 | 
			
		||||
    resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1659,6 +1799,8 @@ snapshots:
 | 
			
		|||
      '@jridgewell/gen-mapping': 0.3.8
 | 
			
		||||
      '@jridgewell/trace-mapping': 0.3.25
 | 
			
		||||
 | 
			
		||||
  '@bufbuild/protobuf@2.6.0': {}
 | 
			
		||||
 | 
			
		||||
  '@codemirror/state@6.5.2':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@marijn/find-cluster-break': 1.0.2
 | 
			
		||||
| 
						 | 
				
			
			@ -2056,6 +2198,8 @@ snapshots:
 | 
			
		|||
    dependencies:
 | 
			
		||||
      fill-range: 7.1.1
 | 
			
		||||
 | 
			
		||||
  buffer-builder@0.2.0: {}
 | 
			
		||||
 | 
			
		||||
  builtin-modules@3.3.0: {}
 | 
			
		||||
 | 
			
		||||
  call-bind-apply-helpers@1.0.2:
 | 
			
		||||
| 
						 | 
				
			
			@ -2112,6 +2256,8 @@ snapshots:
 | 
			
		|||
 | 
			
		||||
  color-name@1.1.4: {}
 | 
			
		||||
 | 
			
		||||
  colorjs.io@0.5.2: {}
 | 
			
		||||
 | 
			
		||||
  concat-map@0.0.1: {}
 | 
			
		||||
 | 
			
		||||
  crelt@1.0.6: {}
 | 
			
		||||
| 
						 | 
				
			
			@ -2269,6 +2415,14 @@ snapshots:
 | 
			
		|||
      is-date-object: 1.1.0
 | 
			
		||||
      is-symbol: 1.1.1
 | 
			
		||||
 | 
			
		||||
  esbuild-sass-plugin@3.3.1(esbuild@0.17.3)(sass-embedded@1.89.2):
 | 
			
		||||
    dependencies:
 | 
			
		||||
      esbuild: 0.17.3
 | 
			
		||||
      resolve: 1.22.10
 | 
			
		||||
      safe-identifier: 0.4.2
 | 
			
		||||
      sass: 1.89.2
 | 
			
		||||
      sass-embedded: 1.89.2
 | 
			
		||||
 | 
			
		||||
  esbuild-svelte@0.9.3(esbuild@0.17.3)(svelte@5.34.8):
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@jridgewell/trace-mapping': 0.3.25
 | 
			
		||||
| 
						 | 
				
			
			@ -2916,6 +3070,10 @@ snapshots:
 | 
			
		|||
      esm-env: 1.2.2
 | 
			
		||||
      svelte: 5.34.8
 | 
			
		||||
 | 
			
		||||
  rxjs@7.8.2:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      tslib: 2.4.0
 | 
			
		||||
 | 
			
		||||
  sade@1.8.1:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      mri: 1.2.0
 | 
			
		||||
| 
						 | 
				
			
			@ -2928,6 +3086,8 @@ snapshots:
 | 
			
		|||
      has-symbols: 1.1.0
 | 
			
		||||
      isarray: 2.0.5
 | 
			
		||||
 | 
			
		||||
  safe-identifier@0.4.2: {}
 | 
			
		||||
 | 
			
		||||
  safe-push-apply@1.0.0:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      es-errors: 1.3.0
 | 
			
		||||
| 
						 | 
				
			
			@ -2939,6 +3099,82 @@ snapshots:
 | 
			
		|||
      es-errors: 1.3.0
 | 
			
		||||
      is-regex: 1.2.1
 | 
			
		||||
 | 
			
		||||
  sass-embedded-android-arm64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-android-arm@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-android-riscv64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-android-x64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-darwin-arm64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-darwin-x64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-arm64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-arm@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-musl-arm64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-musl-arm@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-musl-riscv64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-musl-x64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-riscv64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-linux-x64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-win32-arm64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded-win32-x64@1.89.2:
 | 
			
		||||
    optional: true
 | 
			
		||||
 | 
			
		||||
  sass-embedded@1.89.2:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@bufbuild/protobuf': 2.6.0
 | 
			
		||||
      buffer-builder: 0.2.0
 | 
			
		||||
      colorjs.io: 0.5.2
 | 
			
		||||
      immutable: 5.1.3
 | 
			
		||||
      rxjs: 7.8.2
 | 
			
		||||
      supports-color: 8.1.1
 | 
			
		||||
      sync-child-process: 1.0.2
 | 
			
		||||
      varint: 6.0.0
 | 
			
		||||
    optionalDependencies:
 | 
			
		||||
      sass-embedded-android-arm: 1.89.2
 | 
			
		||||
      sass-embedded-android-arm64: 1.89.2
 | 
			
		||||
      sass-embedded-android-riscv64: 1.89.2
 | 
			
		||||
      sass-embedded-android-x64: 1.89.2
 | 
			
		||||
      sass-embedded-darwin-arm64: 1.89.2
 | 
			
		||||
      sass-embedded-darwin-x64: 1.89.2
 | 
			
		||||
      sass-embedded-linux-arm: 1.89.2
 | 
			
		||||
      sass-embedded-linux-arm64: 1.89.2
 | 
			
		||||
      sass-embedded-linux-musl-arm: 1.89.2
 | 
			
		||||
      sass-embedded-linux-musl-arm64: 1.89.2
 | 
			
		||||
      sass-embedded-linux-musl-riscv64: 1.89.2
 | 
			
		||||
      sass-embedded-linux-musl-x64: 1.89.2
 | 
			
		||||
      sass-embedded-linux-riscv64: 1.89.2
 | 
			
		||||
      sass-embedded-linux-x64: 1.89.2
 | 
			
		||||
      sass-embedded-win32-arm64: 1.89.2
 | 
			
		||||
      sass-embedded-win32-x64: 1.89.2
 | 
			
		||||
 | 
			
		||||
  sass@1.89.2:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      chokidar: 4.0.3
 | 
			
		||||
| 
						 | 
				
			
			@ -3084,6 +3320,10 @@ snapshots:
 | 
			
		|||
    dependencies:
 | 
			
		||||
      has-flag: 4.0.0
 | 
			
		||||
 | 
			
		||||
  supports-color@8.1.1:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      has-flag: 4.0.0
 | 
			
		||||
 | 
			
		||||
  supports-preserve-symlinks-flag@1.0.0: {}
 | 
			
		||||
 | 
			
		||||
  svelte-check@4.2.2(picomatch@4.0.2)(svelte@5.34.8)(typescript@5.0.4):
 | 
			
		||||
| 
						 | 
				
			
			@ -3128,6 +3368,12 @@ snapshots:
 | 
			
		|||
      magic-string: 0.30.17
 | 
			
		||||
      zimmerframe: 1.1.2
 | 
			
		||||
 | 
			
		||||
  sync-child-process@1.0.2:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      sync-message-port: 1.1.3
 | 
			
		||||
 | 
			
		||||
  sync-message-port@1.1.3: {}
 | 
			
		||||
 | 
			
		||||
  to-regex-range@5.0.1:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      is-number: 7.0.0
 | 
			
		||||
| 
						 | 
				
			
			@ -3203,6 +3449,8 @@ snapshots:
 | 
			
		|||
      spdx-correct: 3.2.0
 | 
			
		||||
      spdx-expression-parse: 3.0.1
 | 
			
		||||
 | 
			
		||||
  varint@6.0.0: {}
 | 
			
		||||
 | 
			
		||||
  w3c-keyname@2.2.8: {}
 | 
			
		||||
 | 
			
		||||
  which-boxed-primitive@1.1.1:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ import { BackupReadingLogCommand } from "@commands/CreateReadingLogBackupCommand
 | 
			
		|||
import { RestoreReadingLogBackupCommand } from "@commands/RestoreReadingLogBackupCommand";
 | 
			
		||||
import { Goodreads } from "@data-sources/Goodreads";
 | 
			
		||||
import { CreateBookFromGoodreadsUrlCommand } from "@commands/CreateBookFromGoodreadsUrlCommand";
 | 
			
		||||
import { registerBookshelfCodeBlockProcessor } from "@ui/code-blocks/BookshelfCodeBlock";
 | 
			
		||||
 | 
			
		||||
export default class BookTrackerPlugin extends Plugin {
 | 
			
		||||
	public settings: BookTrackerPluginSettings;
 | 
			
		||||
| 
						 | 
				
			
			@ -85,6 +86,7 @@ export default class BookTrackerPlugin extends Plugin {
 | 
			
		|||
 | 
			
		||||
		registerReadingLogCodeBlockProcessor(this);
 | 
			
		||||
		registerReadingStatsCodeBlockProcessor(this);
 | 
			
		||||
		registerBookshelfCodeBlockProcessor(this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onunload() {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
import { registerCodeBlockRenderer } from ".";
 | 
			
		||||
import { SvelteCodeBlockRenderer } from "./SvelteCodeBlockRenderer";
 | 
			
		||||
import BookshelfCodeBlockView from "./BookshelfCodeBlockView.svelte";
 | 
			
		||||
import type BookTrackerPlugin from "@src/main";
 | 
			
		||||
 | 
			
		||||
export function registerBookshelfCodeBlockProcessor(
 | 
			
		||||
	plugin: BookTrackerPlugin
 | 
			
		||||
): void {
 | 
			
		||||
	registerCodeBlockRenderer(
 | 
			
		||||
		plugin,
 | 
			
		||||
		"bookshelf",
 | 
			
		||||
		(source, el) => new BookshelfCodeBlockRenderer(plugin, source, el)
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class BookshelfCodeBlockRenderer extends SvelteCodeBlockRenderer<
 | 
			
		||||
	typeof BookshelfCodeBlockView
 | 
			
		||||
> {
 | 
			
		||||
	constructor(
 | 
			
		||||
		plugin: BookTrackerPlugin,
 | 
			
		||||
		source: string,
 | 
			
		||||
		contentEl: HTMLElement
 | 
			
		||||
	) {
 | 
			
		||||
		super(contentEl, BookshelfCodeBlockView, { props: { plugin, source } });
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	onunload() {}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,131 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import Book from "@ui/components/bookshelf/Book.svelte";
 | 
			
		||||
	import Bookshelf from "@ui/components/bookshelf/Bookshelf.svelte";
 | 
			
		||||
	import BookStack from "@ui/components/bookshelf/BookStack.svelte";
 | 
			
		||||
	import BookStackElement from "@ui/components/bookshelf/BookStackElement.svelte";
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<Bookshelf>
 | 
			
		||||
	<Book
 | 
			
		||||
		title="Hello World"
 | 
			
		||||
		color="purple"
 | 
			
		||||
		width={1120}
 | 
			
		||||
		design="colored-spine"
 | 
			
		||||
	/>
 | 
			
		||||
	<Book title="White Space" width={700} design="split-bands" color="pink" />
 | 
			
		||||
	<Book
 | 
			
		||||
		title="The Art of Computer Programming Vol 1"
 | 
			
		||||
		width={1156}
 | 
			
		||||
		design="dual-top-bands"
 | 
			
		||||
		color="cyan"
 | 
			
		||||
	/>
 | 
			
		||||
	<Book
 | 
			
		||||
		title="Cascading Style Sheets"
 | 
			
		||||
		subtitle="Guide to Design"
 | 
			
		||||
		width={560}
 | 
			
		||||
		orientation="tilted"
 | 
			
		||||
	/>
 | 
			
		||||
	<Book
 | 
			
		||||
		title="HTML5"
 | 
			
		||||
		subtitle="Welcome to the Web"
 | 
			
		||||
		width={1350}
 | 
			
		||||
		design="colored-spine"
 | 
			
		||||
	/>
 | 
			
		||||
	<BookStack totalChildren={2}>
 | 
			
		||||
		<BookStackElement
 | 
			
		||||
			title="Coding for Dummies"
 | 
			
		||||
			subtitle="JS tutorial"
 | 
			
		||||
			color="blue"
 | 
			
		||||
			design="colored-spine"
 | 
			
		||||
		/>
 | 
			
		||||
		<BookStackElement
 | 
			
		||||
			title="Coding for Dummies"
 | 
			
		||||
			subtitle="C# tutorial"
 | 
			
		||||
			color="pink"
 | 
			
		||||
			design="dual-top-bands"
 | 
			
		||||
		/>
 | 
			
		||||
	</BookStack>
 | 
			
		||||
	<Book
 | 
			
		||||
		title="CoffeeScript"
 | 
			
		||||
		subtitle="The JS Alternative"
 | 
			
		||||
		author="The Dev Guy"
 | 
			
		||||
		design="split-bands"
 | 
			
		||||
		color="green"
 | 
			
		||||
		orientation="on-display"
 | 
			
		||||
	/>
 | 
			
		||||
	<Book
 | 
			
		||||
		title="Cheat Sheet"
 | 
			
		||||
		subtitle="Guide to Design"
 | 
			
		||||
		color="blue"
 | 
			
		||||
		design="split-bands"
 | 
			
		||||
		width={870}
 | 
			
		||||
	/>
 | 
			
		||||
	<Book
 | 
			
		||||
		title="Psychology of Colors"
 | 
			
		||||
		color="pink"
 | 
			
		||||
		design="dual-top-bands"
 | 
			
		||||
		width={540}
 | 
			
		||||
	/>
 | 
			
		||||
	<Book
 | 
			
		||||
		title="TypeScript"
 | 
			
		||||
		subtitle="Intro JS to type checking"
 | 
			
		||||
		color="cyan"
 | 
			
		||||
		design="colored-spine"
 | 
			
		||||
		width={1130}
 | 
			
		||||
	/>
 | 
			
		||||
	<Book title="Testing" width={10} />
 | 
			
		||||
	<Book
 | 
			
		||||
		title="JavaScript"
 | 
			
		||||
		subtitle="The Definitive Guide"
 | 
			
		||||
		author="David Flanagan"
 | 
			
		||||
		design="split-bands"
 | 
			
		||||
		color="purple"
 | 
			
		||||
		orientation="on-display"
 | 
			
		||||
	/>
 | 
			
		||||
	<Book title="Pragmatic Programmer" color="red" />
 | 
			
		||||
	<Book title="White Space" color="yellow" design="split-bands" />
 | 
			
		||||
	<Book
 | 
			
		||||
		title="W3 Schools"
 | 
			
		||||
		subtitle="The best around"
 | 
			
		||||
		color="blue"
 | 
			
		||||
		design="split-bands"
 | 
			
		||||
		orientation="tilted"
 | 
			
		||||
	/>
 | 
			
		||||
	<Book
 | 
			
		||||
		title="UI/UX"
 | 
			
		||||
		subtitle="Guide to Mobile Development"
 | 
			
		||||
		author="John Doe"
 | 
			
		||||
		color="purple"
 | 
			
		||||
		orientation="on-display"
 | 
			
		||||
		design="dual-top-bands"
 | 
			
		||||
	/>
 | 
			
		||||
	<Book
 | 
			
		||||
		title="Clean Code"
 | 
			
		||||
		color="orange"
 | 
			
		||||
		orientation="tilted"
 | 
			
		||||
		design="dual-top-bands"
 | 
			
		||||
	/>
 | 
			
		||||
	<Book title="Docs for Devs" />
 | 
			
		||||
	<BookStack totalChildren={4}>
 | 
			
		||||
		<BookStackElement
 | 
			
		||||
			title="The Art of Computer Programming Vol 1"
 | 
			
		||||
			color="green"
 | 
			
		||||
			design="dual-top-bands"
 | 
			
		||||
		/>
 | 
			
		||||
		<BookStackElement
 | 
			
		||||
			title="The Art of Computer Programming Vol 2"
 | 
			
		||||
			color="red"
 | 
			
		||||
			design="dual-top-bands"
 | 
			
		||||
		/>
 | 
			
		||||
		<BookStackElement
 | 
			
		||||
			title="The Art of Computer Programming Vol 3"
 | 
			
		||||
			color="blue"
 | 
			
		||||
			design="dual-top-bands"
 | 
			
		||||
		/>
 | 
			
		||||
		<BookStackElement
 | 
			
		||||
			title="The Art of Computer Programming Vol 4a"
 | 
			
		||||
			color="pink"
 | 
			
		||||
			design="dual-top-bands"
 | 
			
		||||
		/>
 | 
			
		||||
	</BookStack>
 | 
			
		||||
</Bookshelf>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import Self from "./Book.svelte";
 | 
			
		||||
	import { Color, COLOR_NAMES, type ColorName } from "@utils/color";
 | 
			
		||||
	import BookTiltedDefault from "./designs/tilted/BookTiltedDefault.svelte";
 | 
			
		||||
	import BookOnDisplay from "./designs/book/BookOnDisplay.svelte";
 | 
			
		||||
	import BookText from "./BookText.svelte";
 | 
			
		||||
	import BookSplitBands from "./designs/book/BookSplitBands.svelte";
 | 
			
		||||
	import BookDualTopBands from "./designs/book/BookDualTopBands.svelte";
 | 
			
		||||
	import BookColoredSpine from "./designs/book/BookColoredSpine.svelte";
 | 
			
		||||
	import BookDefault from "./designs/book/BookDefault.svelte";
 | 
			
		||||
 | 
			
		||||
	const BOOK_SIZE_DEFAULT: number = 40;
 | 
			
		||||
	const BOOK_SIZE_MIN: number = 15;
 | 
			
		||||
 | 
			
		||||
	interface BookProps {
 | 
			
		||||
		title?: string;
 | 
			
		||||
		subtitle?: string;
 | 
			
		||||
		author?: string;
 | 
			
		||||
		color?: ColorName | string;
 | 
			
		||||
		design?: "default" | "colored-spine" | "dual-top-bands" | "split-bands";
 | 
			
		||||
		orientation?: "tilted" | "on-display";
 | 
			
		||||
		height?: number;
 | 
			
		||||
		width?: number;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let {
 | 
			
		||||
		title,
 | 
			
		||||
		subtitle,
 | 
			
		||||
		author,
 | 
			
		||||
		color: colorRaw = "green",
 | 
			
		||||
		design = "default",
 | 
			
		||||
		orientation,
 | 
			
		||||
		height,
 | 
			
		||||
		width,
 | 
			
		||||
	}: BookProps = $props();
 | 
			
		||||
 | 
			
		||||
	function widthCheck(input: number | undefined) {
 | 
			
		||||
		if (input) {
 | 
			
		||||
			if (input <= 150) {
 | 
			
		||||
				return BOOK_SIZE_MIN;
 | 
			
		||||
			}
 | 
			
		||||
			return input / 10;
 | 
			
		||||
		}
 | 
			
		||||
		return BOOK_SIZE_DEFAULT;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const color = $derived(
 | 
			
		||||
		colorRaw in COLOR_NAMES
 | 
			
		||||
			? Color.fromName(colorRaw as ColorName)
 | 
			
		||||
			: Color.fromCSSColor(colorRaw),
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	const verifiedWidth = $derived(widthCheck(width));
 | 
			
		||||
	const textColor = $derived(color.contrastColor.hex);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
{#if orientation}
 | 
			
		||||
	{#if orientation === "tilted"}
 | 
			
		||||
		<BookTiltedDefault {design} width={verifiedWidth}>
 | 
			
		||||
			<Self
 | 
			
		||||
				{title}
 | 
			
		||||
				{subtitle}
 | 
			
		||||
				{author}
 | 
			
		||||
				color={colorRaw}
 | 
			
		||||
				{design}
 | 
			
		||||
				{height}
 | 
			
		||||
				{width}
 | 
			
		||||
			/>
 | 
			
		||||
		</BookTiltedDefault>
 | 
			
		||||
	{:else if orientation === "on-display"}
 | 
			
		||||
		<BookOnDisplay color={color.hex}>
 | 
			
		||||
			<div
 | 
			
		||||
				class="book-display-crease"
 | 
			
		||||
				style:--book-color={color.hex}
 | 
			
		||||
			></div>
 | 
			
		||||
			{#if title}
 | 
			
		||||
				<BookText {title} {subtitle} />
 | 
			
		||||
				<p class="bookshelf__book-author">By: {author}</p>
 | 
			
		||||
			{/if}
 | 
			
		||||
		</BookOnDisplay>
 | 
			
		||||
	{/if}
 | 
			
		||||
{:else if design === "split-bands"}
 | 
			
		||||
	<BookSplitBands color={color.hex} width={verifiedWidth} {textColor}>
 | 
			
		||||
		<BookText {title} {subtitle} />
 | 
			
		||||
	</BookSplitBands>
 | 
			
		||||
{:else if design === "dual-top-bands"}
 | 
			
		||||
	<BookDualTopBands color={color.hex} width={verifiedWidth} {textColor}>
 | 
			
		||||
		<BookText {title} {subtitle} />
 | 
			
		||||
	</BookDualTopBands>
 | 
			
		||||
{:else if design === "colored-spine"}
 | 
			
		||||
	<BookColoredSpine color={color.hex} width={verifiedWidth} {textColor}>
 | 
			
		||||
		<BookText {title} {subtitle} />
 | 
			
		||||
	</BookColoredSpine>
 | 
			
		||||
{:else}
 | 
			
		||||
	<BookDefault color={color.hex} width={verifiedWidth} {textColor}>
 | 
			
		||||
		<BookText {title} {subtitle} />
 | 
			
		||||
	</BookDefault>
 | 
			
		||||
{/if}
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
	.book-display-crease {
 | 
			
		||||
		background-color: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
		width: 5px;
 | 
			
		||||
		height: 100%;
 | 
			
		||||
		position: absolute;
 | 
			
		||||
		top: 0;
 | 
			
		||||
		left: 8px;
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	const MAX_CHILDREN = 5;
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		totalChildren?: number;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, totalChildren = 0 }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<ul
 | 
			
		||||
	class="bookshelf__bookStack-wrapper"
 | 
			
		||||
	style:margin={`calc(20px + ${(MAX_CHILDREN - totalChildren) * 40}px) 1px 10px`}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</ul>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import { Color, COLOR_NAMES, type ColorName } from "@utils/color";
 | 
			
		||||
	import BookText from "./BookText.svelte";
 | 
			
		||||
	import BookStackColoredSpine from "./designs/stack/BookStackColoredSpine.svelte";
 | 
			
		||||
	import BookStackDefault from "./designs/stack/BookStackDefault.svelte";
 | 
			
		||||
	import BookStackDualTopBands from "./designs/stack/BookStackDualTopBands.svelte";
 | 
			
		||||
	import BookStackSplitBands from "./designs/stack/BookStackSplitBands.svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		title?: string;
 | 
			
		||||
		subtitle?: string;
 | 
			
		||||
		color?: ColorName | string;
 | 
			
		||||
		design?: "default" | "split-bands" | "dual-top-bands" | "colored-spine";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let {
 | 
			
		||||
		title,
 | 
			
		||||
		subtitle,
 | 
			
		||||
		color: colorRaw = "green",
 | 
			
		||||
		design,
 | 
			
		||||
	}: Props = $props();
 | 
			
		||||
 | 
			
		||||
	const color = $derived(
 | 
			
		||||
		colorRaw in COLOR_NAMES
 | 
			
		||||
			? Color.fromName(colorRaw as ColorName)
 | 
			
		||||
			: Color.fromCSSColor(colorRaw),
 | 
			
		||||
	);
 | 
			
		||||
	const textColor = $derived(color.contrastColor.hex);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<li class="bookshelf__bookstack-elem">
 | 
			
		||||
	{#if design === "split-bands"}
 | 
			
		||||
		<BookStackSplitBands color={color.hex} {textColor}>
 | 
			
		||||
			<BookText {title} {subtitle} />
 | 
			
		||||
		</BookStackSplitBands>
 | 
			
		||||
	{:else if design === "dual-top-bands"}
 | 
			
		||||
		<BookStackDualTopBands color={color.hex} {textColor}>
 | 
			
		||||
			<BookText {title} {subtitle} />
 | 
			
		||||
		</BookStackDualTopBands>
 | 
			
		||||
	{:else if design === "colored-spine"}
 | 
			
		||||
		<BookStackColoredSpine color={color.hex} {textColor}>
 | 
			
		||||
			<BookText {title} {subtitle} />
 | 
			
		||||
		</BookStackColoredSpine>
 | 
			
		||||
	{:else}
 | 
			
		||||
		<BookStackDefault color={color.hex} {textColor}>
 | 
			
		||||
			<BookText {title} {subtitle} />
 | 
			
		||||
		</BookStackDefault>
 | 
			
		||||
	{/if}
 | 
			
		||||
</li>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	interface Props {
 | 
			
		||||
		title?: string;
 | 
			
		||||
		subtitle?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { title, subtitle }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-content"
 | 
			
		||||
	class:center-content={subtitle === undefined}
 | 
			
		||||
>
 | 
			
		||||
	{#if title}
 | 
			
		||||
		<h2 class="bookshelf__book-title">{title}</h2>
 | 
			
		||||
	{/if}
 | 
			
		||||
	{#if subtitle}
 | 
			
		||||
		<h4 class="bookshelf__book-subtitle">{subtitle}</h4>
 | 
			
		||||
	{/if}
 | 
			
		||||
</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import "./bookshelf.scss";
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	type Props = {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	let { children }: Props = $props();
 | 
			
		||||
 | 
			
		||||
	const color = "#a47148";
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div class="bookshelf__wrapper" style:--book-shelf-color={color}>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background-image: linear-gradient(
 | 
			
		||||
			color-mix(in srgb, var(--book-shelf-color), black 32%),
 | 
			
		||||
			color-mix(in srgb, var(--book-shelf-color), black 30%) 220px,
 | 
			
		||||
			color-mix(in srgb, var(--book-shelf-color), white 4%) 220px,
 | 
			
		||||
			color-mix(in srgb, var(--book-shelf-color), white 4%) 222px,
 | 
			
		||||
			var(--book-shelf-color) 222px,
 | 
			
		||||
			var(--book-shelf-color) 228px,
 | 
			
		||||
			color-mix(in srgb, var(--book-shelf-color), black 4%) 228px,
 | 
			
		||||
			color-mix(in srgb, var(--book-shelf-color), black 4%) 230px
 | 
			
		||||
		);
 | 
			
		||||
		border: 10px var(--book-shelf-color) solid;
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,216 @@
 | 
			
		|||
$white: white;
 | 
			
		||||
$black: black;
 | 
			
		||||
$background: #dedede;
 | 
			
		||||
 | 
			
		||||
$bookWidth: 40px;
 | 
			
		||||
$bookHeight: 200px;
 | 
			
		||||
$bookEdge: 2px;
 | 
			
		||||
 | 
			
		||||
.bookshelf__wrapper {
 | 
			
		||||
	width: 80%;
 | 
			
		||||
	height: 100%;
 | 
			
		||||
	margin: 0 auto;
 | 
			
		||||
	overflow: hidden;
 | 
			
		||||
	background-size: 10px 230px;
 | 
			
		||||
 | 
			
		||||
	.bookshelf__bookStack-wrapper {
 | 
			
		||||
		width: 200px;
 | 
			
		||||
		height: 100%;
 | 
			
		||||
		display: inline-flex;
 | 
			
		||||
		flex-flow: column nowrap;
 | 
			
		||||
		list-style: none;
 | 
			
		||||
		padding: 0;
 | 
			
		||||
 | 
			
		||||
		.bookshelf__bookStack-outOfStock {
 | 
			
		||||
			background: #232323;
 | 
			
		||||
			color: #fff;
 | 
			
		||||
			height: 150px;
 | 
			
		||||
			padding: 0;
 | 
			
		||||
			margin: 50px 1px auto 1px;
 | 
			
		||||
			display: flex;
 | 
			
		||||
			flex-flow: column nowrap;
 | 
			
		||||
			justify-content: space-around;
 | 
			
		||||
			align-items: center;
 | 
			
		||||
			font-size: 1.1em;
 | 
			
		||||
			font-weight: 600;
 | 
			
		||||
			line-height: 1.2;
 | 
			
		||||
			letter-spacing: 1.25px;
 | 
			
		||||
			border-radius: 6px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.bookshelf__bookstack-elem {
 | 
			
		||||
			margin-inline-start: 0;
 | 
			
		||||
 | 
			
		||||
			.bookshelf__book-wrapper {
 | 
			
		||||
				width: 100%;
 | 
			
		||||
				height: 40px;
 | 
			
		||||
				margin: 0;
 | 
			
		||||
				padding: 0;
 | 
			
		||||
 | 
			
		||||
				.bookshelf__book-content {
 | 
			
		||||
					height: $bookWidth;
 | 
			
		||||
					width: $bookHeight;
 | 
			
		||||
 | 
			
		||||
					transform-origin: 0% 0%;
 | 
			
		||||
					transform: rotate(0deg);
 | 
			
		||||
					overflow: hidden;
 | 
			
		||||
 | 
			
		||||
					// * Centering content
 | 
			
		||||
					display: flex;
 | 
			
		||||
					flex-flow: column nowrap;
 | 
			
		||||
					justify-content: center;
 | 
			
		||||
					align-items: center;
 | 
			
		||||
 | 
			
		||||
					.bookshelf__book-title,
 | 
			
		||||
					.bookshelf__book-subtitle {
 | 
			
		||||
						font-size: 0.8em;
 | 
			
		||||
						font-weight: 600;
 | 
			
		||||
 | 
			
		||||
						height: calc($bookWidth / 2);
 | 
			
		||||
						width: $bookHeight;
 | 
			
		||||
 | 
			
		||||
						padding: 0;
 | 
			
		||||
						margin: 0;
 | 
			
		||||
 | 
			
		||||
						// * Centering content
 | 
			
		||||
						display: flex;
 | 
			
		||||
						justify-content: center;
 | 
			
		||||
						align-items: center;
 | 
			
		||||
						text-align: center;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					.bookshelf__book-subtitle {
 | 
			
		||||
						font-size: 0.6em;
 | 
			
		||||
						letter-spacing: 1px;
 | 
			
		||||
						font-weight: 400;
 | 
			
		||||
						font-style: italic;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				.center-content {
 | 
			
		||||
					display: flex;
 | 
			
		||||
					justify-content: center;
 | 
			
		||||
					align-items: center;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// .bookshelf__book-title{
 | 
			
		||||
				//     width: 140px;
 | 
			
		||||
				//     height: 40px;
 | 
			
		||||
				//     transform: rotate(0deg);
 | 
			
		||||
				//     margin-left: 29px;
 | 
			
		||||
				//     margin-top: 0;
 | 
			
		||||
				//     text-align: center;
 | 
			
		||||
				// }
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.bookshelf__book-wrapper {
 | 
			
		||||
		height: $bookHeight;
 | 
			
		||||
		width: $bookWidth;
 | 
			
		||||
		float: left;
 | 
			
		||||
		margin: 20px 1px 10px 1px;
 | 
			
		||||
		border-radius: 6px;
 | 
			
		||||
		transition: transform 0.4s ease;
 | 
			
		||||
		position: relative;
 | 
			
		||||
 | 
			
		||||
		.bookshelf__book-content {
 | 
			
		||||
			width: $bookHeight;
 | 
			
		||||
 | 
			
		||||
			transform-origin: 0% 0%;
 | 
			
		||||
			transform: rotate(90deg);
 | 
			
		||||
			overflow: hidden;
 | 
			
		||||
 | 
			
		||||
			// * Centering content
 | 
			
		||||
			display: flex;
 | 
			
		||||
			flex-flow: column nowrap;
 | 
			
		||||
			justify-content: center;
 | 
			
		||||
			align-items: center;
 | 
			
		||||
 | 
			
		||||
			.bookshelf__book-title,
 | 
			
		||||
			.bookshelf__book-subtitle {
 | 
			
		||||
				font-size: 0.8em;
 | 
			
		||||
				font-weight: 600;
 | 
			
		||||
 | 
			
		||||
				height: calc($bookWidth / 2);
 | 
			
		||||
				width: $bookHeight;
 | 
			
		||||
 | 
			
		||||
				padding: 0;
 | 
			
		||||
				margin: 0;
 | 
			
		||||
 | 
			
		||||
				// * Centering content
 | 
			
		||||
				display: flex;
 | 
			
		||||
				justify-content: center;
 | 
			
		||||
				align-items: center;
 | 
			
		||||
				text-align: center;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.bookshelf__book-subtitle {
 | 
			
		||||
				font-size: 0.6em;
 | 
			
		||||
				letter-spacing: 1px;
 | 
			
		||||
				font-weight: 400;
 | 
			
		||||
				font-style: italic;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&:hover {
 | 
			
		||||
			transform: scale(1.05);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.center-content {
 | 
			
		||||
			display: flex;
 | 
			
		||||
			justify-content: center;
 | 
			
		||||
			align-items: center;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.bookshelf__book-tilted {
 | 
			
		||||
		float: left;
 | 
			
		||||
		width: 72px;
 | 
			
		||||
 | 
			
		||||
		.bookshelf__book-wrapper {
 | 
			
		||||
			--book-width: 40px !important;
 | 
			
		||||
			width: 40px !important;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&:hover .bookshelf__book-wrapper {
 | 
			
		||||
			transform: translateY(-20px);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		& > .bookshelf__book-wrapper {
 | 
			
		||||
			transform: translateY(-22px) translateX(13px) rotate(9deg);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.bookshelf__book-onDisplay {
 | 
			
		||||
		width: 150px;
 | 
			
		||||
		height: 200px;
 | 
			
		||||
		display: flex;
 | 
			
		||||
		flex-flow: column wrap;
 | 
			
		||||
		justify-content: space-between;
 | 
			
		||||
		align-items: center;
 | 
			
		||||
		text-align: center;
 | 
			
		||||
		margin: 20px 2px 10px 2px;
 | 
			
		||||
		position: relative;
 | 
			
		||||
 | 
			
		||||
		.bookshelf__book-content {
 | 
			
		||||
			width: calc(100% - 11px);
 | 
			
		||||
			margin-left: 11px;
 | 
			
		||||
			transform: rotate(0deg);
 | 
			
		||||
			overflow: visible;
 | 
			
		||||
 | 
			
		||||
			.bookshelf__book-title,
 | 
			
		||||
			.bookshelf__book-subtitle {
 | 
			
		||||
				line-height: 2;
 | 
			
		||||
				margin-top: 16px;
 | 
			
		||||
				width: 100%;
 | 
			
		||||
				word-wrap: break-word;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.bookshelf__book-author {
 | 
			
		||||
			font-size: 0.8em;
 | 
			
		||||
			margin-left: 13px;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		width?: number;
 | 
			
		||||
		textColor?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", width = 40, textColor }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
	style:--book-width={width + "px"}
 | 
			
		||||
	style:width={width + "px"}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid color-mix(in srgb, var(--book-color), white 4%);
 | 
			
		||||
		border-right: 2px solid color-mix(in srgb, var(--book-color), black 4%);
 | 
			
		||||
 | 
			
		||||
		&:before {
 | 
			
		||||
			content: " ";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 100%;
 | 
			
		||||
			width: calc(var(--book-width));
 | 
			
		||||
			border-radius: 4px;
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 0px;
 | 
			
		||||
			left: -2px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		:global(.bookshelf__book-content) {
 | 
			
		||||
			height: calc(var(--book-width));
 | 
			
		||||
			width: calc(200px - 60px);
 | 
			
		||||
			margin: 0 var(--book-width);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: ColorName | string;
 | 
			
		||||
		width?: number;
 | 
			
		||||
		textColor?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", width = 40, textColor }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
	style:--book-width={width + "px"}
 | 
			
		||||
	style:width={width + "px"}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid color-mix(in srgb, var(--book-color), white 4%);
 | 
			
		||||
		border-right: 2px solid color-mix(in srgb, var(--book-color), black 4%);
 | 
			
		||||
 | 
			
		||||
		:global(.bookshelf__book-content) {
 | 
			
		||||
			height: calc(var(--book-width));
 | 
			
		||||
			width: calc(200px - 60px);
 | 
			
		||||
			margin: 0 var(--book-width);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		width?: number;
 | 
			
		||||
		textColor?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", width = 40, textColor }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
	style:--book-width={width + "px"}
 | 
			
		||||
	style:width={width + "px"}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid color-mix(in srgb, var(--book-color), white 4%);
 | 
			
		||||
		border-right: 2px solid color-mix(in srgb, var(--book-color), black 4%);
 | 
			
		||||
 | 
			
		||||
		&:after {
 | 
			
		||||
			content: "";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 20px;
 | 
			
		||||
			width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 10px;
 | 
			
		||||
			left: -2px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&:before {
 | 
			
		||||
			content: "";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 20px;
 | 
			
		||||
			width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			bottom: 10px;
 | 
			
		||||
			left: -2px;
 | 
			
		||||
			z-index: 2;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		:global(.bookshelf__book-content) {
 | 
			
		||||
			height: calc(var(--book-width));
 | 
			
		||||
			width: calc(200px - 60px) !important;
 | 
			
		||||
			margin: 30px var(--book-width);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green" }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper bookshelf__book-onDisplay"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		width?: number;
 | 
			
		||||
		textColor?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", width = 40, textColor }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
	style:--book-width={width + "px"}
 | 
			
		||||
	style:width={width + "px"}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid color-mix(in srgb, var(--book-color), white 4%);
 | 
			
		||||
		border-right: 2px solid color-mix(in srgb, var(--book-color), black 4%);
 | 
			
		||||
 | 
			
		||||
		&:after {
 | 
			
		||||
			content: "";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 20px;
 | 
			
		||||
			width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 10px;
 | 
			
		||||
			left: -2px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&:before {
 | 
			
		||||
			content: "";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 20px;
 | 
			
		||||
			width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			bottom: 10px;
 | 
			
		||||
			left: -2px;
 | 
			
		||||
			z-index: 2;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		:global(.bookshelf__book-content) {
 | 
			
		||||
			height: calc(var(--book-width));
 | 
			
		||||
			width: calc(200px - 60px) !important;
 | 
			
		||||
			margin: 30px var(--book-width);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		textColor?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", textColor }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid color-mix(in srgb, var(--book-color), white 4%);
 | 
			
		||||
		border-right: 2px solid color-mix(in srgb, var(--book-color), black 4%);
 | 
			
		||||
 | 
			
		||||
		&:before {
 | 
			
		||||
			content: " ";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 40px;
 | 
			
		||||
			width: calc(100% + 4px);
 | 
			
		||||
			border-radius: 4px;
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 0px;
 | 
			
		||||
			left: -2px;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		textColor?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", textColor }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid color-mix(in srgb, var(--book-color), white 4%);
 | 
			
		||||
		border-right: 2px solid color-mix(in srgb, var(--book-color), black 4%);
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		textColor?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", textColor }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid color-mix(in srgb, var(--book-color), white 4%);
 | 
			
		||||
		border-right: 2px solid color-mix(in srgb, var(--book-color), black 4%);
 | 
			
		||||
 | 
			
		||||
		&:after {
 | 
			
		||||
			content: " ";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 40px;
 | 
			
		||||
			width: 10px;
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 0px;
 | 
			
		||||
			left: 6px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&:before {
 | 
			
		||||
			content: " ";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 40px;
 | 
			
		||||
			width: 15px;
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 0px;
 | 
			
		||||
			left: 24px;
 | 
			
		||||
			z-index: 2;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		:global(.bookshelf__book-content) {
 | 
			
		||||
			width: calc(200px - 31px) !important;
 | 
			
		||||
			margin: 0 31px;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		textColor?: string;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", textColor }: Props = $props();
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid color-mix(in srgb, var(--book-color), white 4%);
 | 
			
		||||
		border-right: 2px solid color-mix(in srgb, var(--book-color), black 4%);
 | 
			
		||||
 | 
			
		||||
		&:after {
 | 
			
		||||
			content: " ";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 40px;
 | 
			
		||||
			width: 20px;
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 0px;
 | 
			
		||||
			left: 10px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&:before {
 | 
			
		||||
			content: " ";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
			height: 40px;
 | 
			
		||||
			width: 20px;
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 0px;
 | 
			
		||||
			right: 10px;
 | 
			
		||||
			z-index: 2;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		:global(.bookshelf__book-content) {
 | 
			
		||||
			width: calc(200px - 60px) !important;
 | 
			
		||||
			margin: 0 30px;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		width?: number;
 | 
			
		||||
		design?: "default" | "colored-spine" | "dual-top-bands" | "split-bands";
 | 
			
		||||
		topMargin?: number;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let {
 | 
			
		||||
		children,
 | 
			
		||||
		width = 40,
 | 
			
		||||
		design = "default",
 | 
			
		||||
		topMargin,
 | 
			
		||||
	}: Props = $props();
 | 
			
		||||
 | 
			
		||||
	function getTopMargin(
 | 
			
		||||
		design: "default" | "colored-spine" | "dual-top-bands" | "split-bands",
 | 
			
		||||
	): number {
 | 
			
		||||
		switch (design) {
 | 
			
		||||
			case "split-bands":
 | 
			
		||||
				return 30;
 | 
			
		||||
			case "dual-top-bands":
 | 
			
		||||
				return 41;
 | 
			
		||||
		}
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper bookshelf__book-tilted"
 | 
			
		||||
	style:--book-tilted-width={width + "px"}
 | 
			
		||||
	style:--book-tilted-top-margin={(topMargin ?? getTopMargin(design)) + "px"}
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		:global(.bookshelf__book-content) {
 | 
			
		||||
			height: calc(var(--book-tilted-width));
 | 
			
		||||
			width: calc(200px - 60px);
 | 
			
		||||
			margin: var(--book-tilted-top-margin) var(--book-tilted-width);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +40,16 @@ export class Color {
 | 
			
		|||
		return `rgba(${this.r}, ${this.g}, ${this.b}, ${this.a})`;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get contrastColor(): Color {
 | 
			
		||||
		return this.r * 0.299 +
 | 
			
		||||
			this.g * 0.587 +
 | 
			
		||||
			this.b * 0.114 +
 | 
			
		||||
			(1 - this.a) * 255 >
 | 
			
		||||
			186
 | 
			
		||||
			? new Color(0, 0, 0)
 | 
			
		||||
			: new Color(255, 255, 255);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	alpha(alpha: number): Color {
 | 
			
		||||
		return new Color(this.r, this.g, this.b, alpha);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -56,6 +66,18 @@ export class Color {
 | 
			
		|||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static fromCSSColor(color: string): Color {
 | 
			
		||||
		const ctx = document.createElement("canvas").getContext("2d")!;
 | 
			
		||||
		ctx.fillStyle = color;
 | 
			
		||||
		const hexColor = ctx.fillStyle;
 | 
			
		||||
 | 
			
		||||
		return new Color(
 | 
			
		||||
			parseInt(hexColor.slice(1, 3), 16),
 | 
			
		||||
			parseInt(hexColor.slice(3, 5), 16),
 | 
			
		||||
			parseInt(hexColor.slice(5, 7), 16)
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static getAll(): Color[] {
 | 
			
		||||
		return COLOR_NAMES.map((color) => Color.fromName(color));
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue