generated from tpl/obsidian-sample-plugin
			Move all book designs into book element and fix text sizing a bit
This commit is contained in:
		
							parent
							
								
									db732fd8a6
								
							
						
					
					
						commit
						63221fb946
					
				| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
		"@popperjs/core": "^2.11.8",
 | 
			
		||||
		"@types/chroma-js": "^3.1.1",
 | 
			
		||||
		"@types/node": "^24.0.6",
 | 
			
		||||
		"@types/textfit": "^2.4.5",
 | 
			
		||||
		"@typescript-eslint/eslint-plugin": "5.29.0",
 | 
			
		||||
		"@typescript-eslint/parser": "5.29.0",
 | 
			
		||||
		"builtin-modules": "3.3.0",
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +47,7 @@
 | 
			
		|||
		"chart.js": "^4.5.0",
 | 
			
		||||
		"chroma-js": "^3.1.2",
 | 
			
		||||
		"esbuild-sass-plugin": "^3.3.1",
 | 
			
		||||
		"textfit": "^2.4.0",
 | 
			
		||||
		"uuid": "^11.1.0",
 | 
			
		||||
		"yaml": "^2.8.0",
 | 
			
		||||
		"zod": "^3.25.67"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,9 @@ importers:
 | 
			
		|||
      esbuild-sass-plugin:
 | 
			
		||||
        specifier: ^3.3.1
 | 
			
		||||
        version: 3.3.1(esbuild@0.17.3)(sass-embedded@1.89.2)
 | 
			
		||||
      textfit:
 | 
			
		||||
        specifier: ^2.4.0
 | 
			
		||||
        version: 2.4.0
 | 
			
		||||
      uuid:
 | 
			
		||||
        specifier: ^11.1.0
 | 
			
		||||
        version: 11.1.0
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +45,9 @@ importers:
 | 
			
		|||
      '@types/node':
 | 
			
		||||
        specifier: ^24.0.6
 | 
			
		||||
        version: 24.0.6
 | 
			
		||||
      '@types/textfit':
 | 
			
		||||
        specifier: ^2.4.5
 | 
			
		||||
        version: 2.4.5
 | 
			
		||||
      '@typescript-eslint/eslint-plugin':
 | 
			
		||||
        specifier: 5.29.0
 | 
			
		||||
        version: 5.29.0(@typescript-eslint/parser@5.29.0(eslint@9.30.0)(typescript@5.0.4))(eslint@9.30.0)(typescript@5.0.4)
 | 
			
		||||
| 
						 | 
				
			
			@ -453,15 +459,24 @@ packages:
 | 
			
		|||
  '@types/estree@1.0.8':
 | 
			
		||||
    resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
 | 
			
		||||
 | 
			
		||||
  '@types/jquery@3.5.32':
 | 
			
		||||
    resolution: {integrity: sha512-b9Xbf4CkMqS02YH8zACqN1xzdxc3cO735Qe5AbSUFmyOiaWAbcpqh9Wna+Uk0vgACvoQHpWDg2rGdHkYPLmCiQ==}
 | 
			
		||||
 | 
			
		||||
  '@types/json-schema@7.0.15':
 | 
			
		||||
    resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
 | 
			
		||||
 | 
			
		||||
  '@types/node@24.0.6':
 | 
			
		||||
    resolution: {integrity: sha512-ZOyn+gOs749xU7ovp+Ibj0g1o3dFRqsfPnT22C2t5JzcRvgsEDpGawPbCISGKLudJk9Y0wiu9sYd6kUh0pc9TA==}
 | 
			
		||||
 | 
			
		||||
  '@types/sizzle@2.3.9':
 | 
			
		||||
    resolution: {integrity: sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==}
 | 
			
		||||
 | 
			
		||||
  '@types/tern@0.23.9':
 | 
			
		||||
    resolution: {integrity: sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==}
 | 
			
		||||
 | 
			
		||||
  '@types/textfit@2.4.5':
 | 
			
		||||
    resolution: {integrity: sha512-C/1i+vGFD7xi1UZPePa6pNdoR0eGFCOe7QrZlTuPGPF+Y4JnFcp9cSJGZko+6tW8GmdDdKt7S9W6sCf3ncvk5g==}
 | 
			
		||||
 | 
			
		||||
  '@typescript-eslint/eslint-plugin@5.29.0':
 | 
			
		||||
    resolution: {integrity: sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==}
 | 
			
		||||
    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
 | 
			
		||||
| 
						 | 
				
			
			@ -1676,6 +1691,9 @@ packages:
 | 
			
		|||
    resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==}
 | 
			
		||||
    engines: {node: '>=16.0.0'}
 | 
			
		||||
 | 
			
		||||
  textfit@2.4.0:
 | 
			
		||||
    resolution: {integrity: sha512-/x4aoY5+/tJmu+iwpBH1yw75TFp86M6X15SvaaY/Eep7YySQYtqdOifEtfvVyMwzl7SZ+G4RQw00FD9g5R6i1Q==}
 | 
			
		||||
 | 
			
		||||
  to-regex-range@5.0.1:
 | 
			
		||||
    resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
 | 
			
		||||
    engines: {node: '>=8.0'}
 | 
			
		||||
| 
						 | 
				
			
			@ -2047,16 +2065,26 @@ snapshots:
 | 
			
		|||
 | 
			
		||||
  '@types/estree@1.0.8': {}
 | 
			
		||||
 | 
			
		||||
  '@types/jquery@3.5.32':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@types/sizzle': 2.3.9
 | 
			
		||||
 | 
			
		||||
  '@types/json-schema@7.0.15': {}
 | 
			
		||||
 | 
			
		||||
  '@types/node@24.0.6':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      undici-types: 7.8.0
 | 
			
		||||
 | 
			
		||||
  '@types/sizzle@2.3.9': {}
 | 
			
		||||
 | 
			
		||||
  '@types/tern@0.23.9':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@types/estree': 1.0.8
 | 
			
		||||
 | 
			
		||||
  '@types/textfit@2.4.5':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@types/jquery': 3.5.32
 | 
			
		||||
 | 
			
		||||
  '@typescript-eslint/eslint-plugin@5.29.0(@typescript-eslint/parser@5.29.0(eslint@9.30.0)(typescript@5.0.4))(eslint@9.30.0)(typescript@5.0.4)':
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@typescript-eslint/parser': 5.29.0(eslint@9.30.0)(typescript@5.0.4)
 | 
			
		||||
| 
						 | 
				
			
			@ -3374,6 +3402,8 @@ snapshots:
 | 
			
		|||
 | 
			
		||||
  sync-message-port@1.1.3: {}
 | 
			
		||||
 | 
			
		||||
  textfit@2.4.0: {}
 | 
			
		||||
 | 
			
		||||
  to-regex-range@5.0.1:
 | 
			
		||||
    dependencies:
 | 
			
		||||
      is-number: 7.0.0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,19 +1,9 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import Self from "./Book.svelte";
 | 
			
		||||
	import {
 | 
			
		||||
		Color,
 | 
			
		||||
		COLOR_NAMES,
 | 
			
		||||
		isColorName,
 | 
			
		||||
		type ColorName,
 | 
			
		||||
	} from "@utils/color";
 | 
			
		||||
	import BookTiltedDefault from "./designs/tilted/BookTiltedDefault.svelte";
 | 
			
		||||
	import BookOnDisplay from "./designs/book/BookOnDisplay.svelte";
 | 
			
		||||
	import { Color, isColorName, type ColorName } from "@utils/color";
 | 
			
		||||
	import BookTilted from "./BookTilted.svelte";
 | 
			
		||||
	import BookOnDisplay from "./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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -57,12 +47,22 @@
 | 
			
		|||
			: Color.fromCSSColor(colorRaw),
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	const backgroundColor = $derived(
 | 
			
		||||
		design === "colored-spine"
 | 
			
		||||
			? color.chroma.mix("black", 0.14)
 | 
			
		||||
			: color.chroma,
 | 
			
		||||
	);
 | 
			
		||||
	const borderLeftColor = $derived(color.chroma.mix("white", 0.04));
 | 
			
		||||
	const borderRightColor = $derived(color.chroma.mix("black", 0.04));
 | 
			
		||||
	const bandColor = $derived(color.chroma.mix("black", 0.14));
 | 
			
		||||
	const textColor = $derived(new Color(backgroundColor).contrastColor.hex);
 | 
			
		||||
 | 
			
		||||
	const verifiedWidth = $derived(normalizeWidth(width));
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
{#if orientation}
 | 
			
		||||
	{#if orientation === "tilted"}
 | 
			
		||||
		<BookTiltedDefault {design} width={verifiedWidth}>
 | 
			
		||||
		<BookTilted {design} width={verifiedWidth}>
 | 
			
		||||
			<Self
 | 
			
		||||
				{title}
 | 
			
		||||
				{subtitle}
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +73,7 @@
 | 
			
		|||
				{width}
 | 
			
		||||
				{onClick}
 | 
			
		||||
			/>
 | 
			
		||||
		</BookTiltedDefault>
 | 
			
		||||
		</BookTilted>
 | 
			
		||||
	{:else if orientation === "on-display"}
 | 
			
		||||
		<BookOnDisplay color={color.hex} {onClick}>
 | 
			
		||||
			<div
 | 
			
		||||
| 
						 | 
				
			
			@ -86,25 +86,30 @@
 | 
			
		|||
			{/if}
 | 
			
		||||
		</BookOnDisplay>
 | 
			
		||||
	{/if}
 | 
			
		||||
{:else if design === "split-bands"}
 | 
			
		||||
	<BookSplitBands color={color.hex} width={verifiedWidth} {onClick}>
 | 
			
		||||
		<BookText {title} {subtitle} />
 | 
			
		||||
	</BookSplitBands>
 | 
			
		||||
{:else if design === "dual-top-bands"}
 | 
			
		||||
	<BookDualTopBands color={color.hex} width={verifiedWidth} {onClick}>
 | 
			
		||||
		<BookText {title} {subtitle} />
 | 
			
		||||
	</BookDualTopBands>
 | 
			
		||||
{:else if design === "colored-spine"}
 | 
			
		||||
	<BookColoredSpine color={color.hex} width={verifiedWidth} {onClick}>
 | 
			
		||||
		<BookText {title} {subtitle} />
 | 
			
		||||
	</BookColoredSpine>
 | 
			
		||||
{:else}
 | 
			
		||||
	<BookDefault color={color.hex} width={verifiedWidth} {onClick}>
 | 
			
		||||
	<div
 | 
			
		||||
		class="bookshelf__book-wrapper"
 | 
			
		||||
		class:default={design === "default"}
 | 
			
		||||
		class:colored-spine={design === "colored-spine"}
 | 
			
		||||
		class:dual-top-bands={design === "dual-top-bands"}
 | 
			
		||||
		class:split-bands={design === "split-bands"}
 | 
			
		||||
		style:--book-color={backgroundColor.css()}
 | 
			
		||||
		style:--book-border-left-color={borderLeftColor.css()}
 | 
			
		||||
		style:--book-border-right-color={borderRightColor.css()}
 | 
			
		||||
		style:--book-band-color={bandColor.css()}
 | 
			
		||||
		style:--book-width={verifiedWidth + "px"}
 | 
			
		||||
		style:width={verifiedWidth + "px"}
 | 
			
		||||
		style:color={textColor}
 | 
			
		||||
		onclick={onClick}
 | 
			
		||||
		onkeydown={(ev) => ev.key === "Enter" && onClick?.()}
 | 
			
		||||
		role="link"
 | 
			
		||||
		tabindex="0"
 | 
			
		||||
	>
 | 
			
		||||
		<BookText {title} {subtitle} />
 | 
			
		||||
	</BookDefault>
 | 
			
		||||
	</div>
 | 
			
		||||
{/if}
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	.book-display-crease {
 | 
			
		||||
		background-color: color-mix(in srgb, var(--book-color), black 14%);
 | 
			
		||||
		width: 5px;
 | 
			
		||||
| 
						 | 
				
			
			@ -113,4 +118,107 @@
 | 
			
		|||
		top: 0;
 | 
			
		||||
		left: 8px;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	div.bookshelf__book-wrapper {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid var(--book-border-left-color);
 | 
			
		||||
		border-right: 2px solid var(--book-border-right-color);
 | 
			
		||||
 | 
			
		||||
		&.default,
 | 
			
		||||
		&.colored-spine {
 | 
			
		||||
			:global(.bookshelf__book-content) {
 | 
			
		||||
				height: calc(var(--book-width));
 | 
			
		||||
				margin: 0 var(--book-width);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&.colored-spine {
 | 
			
		||||
			&:before {
 | 
			
		||||
				content: " ";
 | 
			
		||||
				display: block;
 | 
			
		||||
				background: var(--book-background-color);
 | 
			
		||||
				height: 100%;
 | 
			
		||||
				width: calc(var(--book-width));
 | 
			
		||||
				border-radius: 4px;
 | 
			
		||||
 | 
			
		||||
				position: absolute;
 | 
			
		||||
				top: 0px;
 | 
			
		||||
				left: -2px;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&.dual-top-bands {
 | 
			
		||||
			&:after,
 | 
			
		||||
			&:before {
 | 
			
		||||
				content: "";
 | 
			
		||||
				display: block;
 | 
			
		||||
				background: var(--book-band-color);
 | 
			
		||||
				width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
				position: absolute;
 | 
			
		||||
				left: -2px;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			&:after {
 | 
			
		||||
				height: 10px;
 | 
			
		||||
				top: 8px;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			&:before {
 | 
			
		||||
				height: 15px;
 | 
			
		||||
				top: 26px;
 | 
			
		||||
				z-index: 2;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			:global(.bookshelf__book-content) {
 | 
			
		||||
				height: calc(var(--book-width));
 | 
			
		||||
				width: calc(200px - 41px) !important;
 | 
			
		||||
				margin: 41px var(--book-width);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&.split-bands {
 | 
			
		||||
			&:after,
 | 
			
		||||
			&:before {
 | 
			
		||||
				content: "";
 | 
			
		||||
				display: block;
 | 
			
		||||
				background: var(--book-band-color);
 | 
			
		||||
				height: 20px;
 | 
			
		||||
				width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
				position: absolute;
 | 
			
		||||
				left: -2px;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			&:after {
 | 
			
		||||
				content: "";
 | 
			
		||||
				display: block;
 | 
			
		||||
				background: var(--book-band-color);
 | 
			
		||||
				height: 20px;
 | 
			
		||||
				width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
				position: absolute;
 | 
			
		||||
				top: 10px;
 | 
			
		||||
				left: -2px;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			&:before {
 | 
			
		||||
				content: "";
 | 
			
		||||
				display: block;
 | 
			
		||||
				background: var(--book-band-color);
 | 
			
		||||
				height: 20px;
 | 
			
		||||
				width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
				position: absolute;
 | 
			
		||||
				bottom: 10px;
 | 
			
		||||
				z-index: 2;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			:global(.bookshelf__book-content) {
 | 
			
		||||
				height: calc(var(--book-width));
 | 
			
		||||
				width: calc(200px - 60px) !important;
 | 
			
		||||
				margin: 30px var(--book-width);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,6 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import { fitText } from "@ui/directives";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		title?: string;
 | 
			
		||||
		subtitle?: string;
 | 
			
		||||
| 
						 | 
				
			
			@ -12,9 +14,40 @@
 | 
			
		|||
	class:center-content={subtitle === undefined}
 | 
			
		||||
>
 | 
			
		||||
	{#if title}
 | 
			
		||||
		<h2 class="bookshelf__book-title">{title}</h2>
 | 
			
		||||
		<h2
 | 
			
		||||
			class="bookshelf__book-title"
 | 
			
		||||
			style:width="100%"
 | 
			
		||||
			use:fitText={{ minFontSize: 12, maxFontSize: 16 }}
 | 
			
		||||
		>
 | 
			
		||||
			{title}
 | 
			
		||||
		</h2>
 | 
			
		||||
	{/if}
 | 
			
		||||
	{#if subtitle}
 | 
			
		||||
		<h4 class="bookshelf__book-subtitle">{subtitle}</h4>
 | 
			
		||||
		<h4
 | 
			
		||||
			class="bookshelf__book-subtitle"
 | 
			
		||||
			style:width="100%"
 | 
			
		||||
			use:fitText={{ minFontSize: 12, maxFontSize: 16 }}
 | 
			
		||||
		>
 | 
			
		||||
			{subtitle}
 | 
			
		||||
		</h4>
 | 
			
		||||
	{/if}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	.bookshelf__book-title,
 | 
			
		||||
	.bookshelf__book-subtitle {
 | 
			
		||||
		:global(.textFitted) {
 | 
			
		||||
			width: 100%;
 | 
			
		||||
			word-wrap: break-word;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.bookshelf__book-subtitle {
 | 
			
		||||
		:global(.textFitted) {
 | 
			
		||||
			width: 100%;
 | 
			
		||||
			white-space: nowrap;
 | 
			
		||||
			overflow: hidden;
 | 
			
		||||
			text-overflow: ellipsis;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,6 @@ $bookEdge: 2px;
 | 
			
		|||
			align-items: center;
 | 
			
		||||
			font-size: 1.1em;
 | 
			
		||||
			font-weight: 600;
 | 
			
		||||
			line-height: 1.2;
 | 
			
		||||
			letter-spacing: 1.25px;
 | 
			
		||||
			border-radius: 6px;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -205,11 +204,18 @@ $bookEdge: 2px;
 | 
			
		|||
 | 
			
		||||
			.bookshelf__book-title,
 | 
			
		||||
			.bookshelf__book-subtitle {
 | 
			
		||||
				line-height: 2;
 | 
			
		||||
				margin-top: 16px;
 | 
			
		||||
				width: 100%;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.bookshelf__book-title {
 | 
			
		||||
				word-wrap: break-word;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.bookshelf__book-subtitle {
 | 
			
		||||
				white-space: nowrap;
 | 
			
		||||
				text-overflow: ellipsis;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.bookshelf__book-author {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,63 +0,0 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
	import chroma from "chroma-js";
 | 
			
		||||
	import { Color } from "@utils/color";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		width?: number;
 | 
			
		||||
		onClick?: () => void;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", width = 40, onClick }: Props = $props();
 | 
			
		||||
 | 
			
		||||
	const borderLeftColor = $derived(chroma(color).mix("white", 0.04));
 | 
			
		||||
	const borderRightColor = $derived(chroma(color).mix("black", 0.04));
 | 
			
		||||
	const backgroundColor = $derived(chroma(color).mix("black", 0.14));
 | 
			
		||||
	const textColor = $derived(new Color(backgroundColor).contrastColor.hex);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={color}
 | 
			
		||||
	style:--book-border-left-color={borderLeftColor.css()}
 | 
			
		||||
	style:--book-border-right-color={borderRightColor.css()}
 | 
			
		||||
	style:--book-background-color={backgroundColor.css()}
 | 
			
		||||
	style:--book-width={width + "px"}
 | 
			
		||||
	style:width={width + "px"}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
	onclick={onClick}
 | 
			
		||||
	onkeydown={(ev) => ev.key === "Enter" && onClick?.()}
 | 
			
		||||
	role="link"
 | 
			
		||||
	tabindex="0"
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid var(--book-border-left-color);
 | 
			
		||||
		border-right: 2px solid var(--book-border-right-color);
 | 
			
		||||
 | 
			
		||||
		&:before {
 | 
			
		||||
			content: " ";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: var(--book-background-color);
 | 
			
		||||
			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>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,49 +0,0 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
	import chroma from "chroma-js";
 | 
			
		||||
	import { Color } from "@utils/color";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		width?: number;
 | 
			
		||||
		onClick?: () => void;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", width = 40, onClick }: Props = $props();
 | 
			
		||||
 | 
			
		||||
	const backgroundColor = $derived(chroma(color));
 | 
			
		||||
	const borderLeftColor = $derived(chroma(color).mix("white", 0.04));
 | 
			
		||||
	const borderRightColor = $derived(chroma(color).mix("black", 0.04));
 | 
			
		||||
	const textColor = $derived(new Color(backgroundColor).contrastColor.hex);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={backgroundColor.css()}
 | 
			
		||||
	style:--book-border-left-color={borderLeftColor.css()}
 | 
			
		||||
	style:--book-border-right-color={borderRightColor.css()}
 | 
			
		||||
	style:--book-width={width + "px"}
 | 
			
		||||
	style:width={width + "px"}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
	onclick={onClick}
 | 
			
		||||
	onkeydown={(ev) => ev.key === "Enter" && onClick?.()}
 | 
			
		||||
	role="link"
 | 
			
		||||
	tabindex="0"
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid var(--book-border-left-color);
 | 
			
		||||
		border-right: 2px solid var(--book-border-right-color);
 | 
			
		||||
 | 
			
		||||
		:global(.bookshelf__book-content) {
 | 
			
		||||
			height: calc(var(--book-width));
 | 
			
		||||
			width: calc(200px - 60px);
 | 
			
		||||
			margin: 0 var(--book-width);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,76 +0,0 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
	import chroma from "chroma-js";
 | 
			
		||||
	import { Color } from "@utils/color";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		width?: number;
 | 
			
		||||
		onClick?: () => void;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", width = 40, onClick }: Props = $props();
 | 
			
		||||
 | 
			
		||||
	const backgroundColor = $derived(chroma(color));
 | 
			
		||||
	const borderLeftColor = $derived(chroma(color).mix("white", 0.04));
 | 
			
		||||
	const borderRightColor = $derived(chroma(color).mix("black", 0.04));
 | 
			
		||||
	const bandColor = $derived(chroma(color).mix("black", 0.14));
 | 
			
		||||
	const textColor = $derived(new Color(backgroundColor).contrastColor.hex);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={backgroundColor.css()}
 | 
			
		||||
	style:--book-border-left-color={borderLeftColor.css()}
 | 
			
		||||
	style:--book-border-right-color={borderRightColor.css()}
 | 
			
		||||
	style:--book-band-color={bandColor.css()}
 | 
			
		||||
	style:--book-width={width + "px"}
 | 
			
		||||
	style:width={width + "px"}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
	onclick={onClick}
 | 
			
		||||
	onkeydown={(ev) => ev.key === "Enter" && onClick?.()}
 | 
			
		||||
	role="link"
 | 
			
		||||
	tabindex="0"
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid var(--book-border-left-color);
 | 
			
		||||
		border-right: 2px solid var(--book-border-right-color);
 | 
			
		||||
 | 
			
		||||
		&:after {
 | 
			
		||||
			content: "";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: var(--book-band-color);
 | 
			
		||||
			height: 20px;
 | 
			
		||||
			width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 10px;
 | 
			
		||||
			left: -2px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&:before {
 | 
			
		||||
			content: "";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: var(--book-band-color);
 | 
			
		||||
			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>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,76 +0,0 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import type { Snippet } from "svelte";
 | 
			
		||||
	import chroma from "chroma-js";
 | 
			
		||||
	import { Color } from "@utils/color";
 | 
			
		||||
 | 
			
		||||
	interface Props {
 | 
			
		||||
		children?: Snippet;
 | 
			
		||||
		color?: string;
 | 
			
		||||
		width?: number;
 | 
			
		||||
		onClick?: () => void;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let { children, color = "green", width = 40, onClick }: Props = $props();
 | 
			
		||||
 | 
			
		||||
	const backgroundColor = $derived(chroma(color));
 | 
			
		||||
	const borderLeftColor = $derived(chroma(color).mix("white", 0.04));
 | 
			
		||||
	const borderRightColor = $derived(chroma(color).mix("black", 0.04));
 | 
			
		||||
	const bandColor = $derived(chroma(color).mix("black", 0.14));
 | 
			
		||||
	const textColor = $derived(new Color(backgroundColor).contrastColor.hex);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<div
 | 
			
		||||
	class="bookshelf__book-wrapper"
 | 
			
		||||
	style:--book-color={backgroundColor.css()}
 | 
			
		||||
	style:--book-border-left-color={borderLeftColor.css()}
 | 
			
		||||
	style:--book-border-right-color={borderRightColor.css()}
 | 
			
		||||
	style:--book-band-color={bandColor.css()}
 | 
			
		||||
	style:--book-width={width + "px"}
 | 
			
		||||
	style:width={width + "px"}
 | 
			
		||||
	style:color={textColor}
 | 
			
		||||
	onclick={onClick}
 | 
			
		||||
	onkeydown={(ev) => ev.key === "Enter" && onClick?.()}
 | 
			
		||||
	role="link"
 | 
			
		||||
	tabindex="0"
 | 
			
		||||
>
 | 
			
		||||
	{@render children?.()}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
	div {
 | 
			
		||||
		background: var(--book-color);
 | 
			
		||||
		border-left: 2px solid var(--book-border-left-color);
 | 
			
		||||
		border-right: 2px solid var(--book-border-right-color);
 | 
			
		||||
 | 
			
		||||
		&:after {
 | 
			
		||||
			content: "";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: var(--book-band-color);
 | 
			
		||||
			height: 20px;
 | 
			
		||||
			width: calc(100% + 4px);
 | 
			
		||||
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 10px;
 | 
			
		||||
			left: -2px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&:before {
 | 
			
		||||
			content: "";
 | 
			
		||||
			display: block;
 | 
			
		||||
			background: var(--book-band-color);
 | 
			
		||||
			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,16 @@
 | 
			
		|||
import type { ActionReturn } from "svelte/action";
 | 
			
		||||
import { default as doTextFit, type TextFitOption } from "textfit";
 | 
			
		||||
 | 
			
		||||
export function fitText(
 | 
			
		||||
	el: HTMLElement,
 | 
			
		||||
	opts: TextFitOption = {}
 | 
			
		||||
): ActionReturn<TextFitOption> {
 | 
			
		||||
	doTextFit(el, opts);
 | 
			
		||||
 | 
			
		||||
	return {
 | 
			
		||||
		update(opts) {
 | 
			
		||||
			doTextFit(el, opts);
 | 
			
		||||
		},
 | 
			
		||||
		destroy() {},
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1 +1,3 @@
 | 
			
		|||
export { chart } from "./chart";
 | 
			
		||||
export { clickOutside } from "./clickOutside";
 | 
			
		||||
export { fitText } from "./fitText";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@
 | 
			
		|||
    "strictNullChecks": true,
 | 
			
		||||
    "verbatimModuleSyntax": true,
 | 
			
		||||
    "skipLibCheck": true,
 | 
			
		||||
    "allowSyntheticDefaultImports": true,
 | 
			
		||||
    "lib": [
 | 
			
		||||
      "DOM",
 | 
			
		||||
      "ES5",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue