Run prettier
This commit is contained in:
parent
597c071c3d
commit
c9ec9f14de
15
.prettierignore
Normal file
15
.prettierignore
Normal file
@ -0,0 +1,15 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/.svelte-kit
|
||||
/package
|
||||
.mf/
|
||||
build/
|
||||
.idea/
|
||||
.vscode/
|
||||
.vercel_build_output
|
||||
.pnpm-debug.log
|
||||
generated/
|
||||
.pnpm-store/
|
||||
locales/
|
||||
pnpm-lock.yaml
|
||||
.nuxt/
|
||||
15
.vscode/settings.json
vendored
15
.vscode/settings.json
vendored
@ -1,4 +1,19 @@
|
||||
{
|
||||
"prettier.endOfLine": "lf",
|
||||
"cSpell.words": ["unplugin"],
|
||||
"gitlens.showWelcomeOnInstall": false,
|
||||
"gitlens.showWhatsNewAfterUpgrades": false,
|
||||
"gitlens.plusFeatures.enabled": false,
|
||||
"gitlens.currentLine.enabled": false,
|
||||
"gitlens.currentLine.pullRequests.enabled": false,
|
||||
"gitlens.currentLine.scrollable": true,
|
||||
"gitlens.codeLens.enabled": false,
|
||||
"gitlens.hovers.enabled": false,
|
||||
"svelte.enable-ts-plugin": true,
|
||||
"svelte.ask-to-enable-ts-plugin": false,
|
||||
"yaml.schemas": {
|
||||
"https://json.schemastore.org/github-workflow.json": "file:///Users/sha/Code/Modrinth/knossos/.github/workflows/deploy.yml"
|
||||
},
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnPaste": true,
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
"prepare": "svelte-kit sync",
|
||||
"check": "svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
|
||||
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ."
|
||||
"lint": "prettier --ignore-path .prettierignore --check --plugin-search-dir=. . && eslint --ignore-path .prettierignore .",
|
||||
"format": "prettier --ignore-path .prettierignore --write --plugin-search-dir=. ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-static": "^1.0.0-next.29",
|
||||
@ -25,6 +25,7 @@
|
||||
"mdsvexamples": "^0.3.0",
|
||||
"nodemon": "^2.0.15",
|
||||
"prettier": "^2.6.2",
|
||||
"prettier-plugin-svelte": "^2.7.0",
|
||||
"sveld": "^0.13.4",
|
||||
"svelte": "^3.48.0",
|
||||
"svelte-check": "^2.2.6",
|
||||
|
||||
30
pnpm-lock.yaml
generated
30
pnpm-lock.yaml
generated
@ -36,6 +36,7 @@ specifiers:
|
||||
postcss-pxtorem: ^6.0.0
|
||||
postcss-strip-inline-comments: ^0.1.5
|
||||
prettier: ^2.6.2
|
||||
prettier-plugin-svelte: ^2.7.0
|
||||
sanitize.css: ^13.0.0
|
||||
sveld: ^0.13.4
|
||||
svelte: ^3.48.0
|
||||
@ -84,7 +85,7 @@ dependencies:
|
||||
|
||||
devDependencies:
|
||||
'@sveltejs/adapter-static': 1.0.0-next.29
|
||||
'@sveltejs/kit': 1.0.0-next.345_svelte@3.48.0
|
||||
'@sveltejs/kit': 1.0.0-next.348_svelte@3.48.0
|
||||
'@typescript-eslint/eslint-plugin': 5.14.0_4p27j37cxves4nxlnqogdhp4ta
|
||||
'@typescript-eslint/parser': 5.14.0_e6rt7vlgxfprtuallp2t3cvyi4
|
||||
eslint: 7.32.0
|
||||
@ -94,6 +95,7 @@ devDependencies:
|
||||
mdsvexamples: 0.3.0
|
||||
nodemon: 2.0.15
|
||||
prettier: 2.6.2
|
||||
prettier-plugin-svelte: 2.7.0_kkjbqzpydplecjtkxrgomroeru
|
||||
sveld: 0.13.4_jw3wiphoy34i6ad2hx6ga3jifa
|
||||
svelte: 3.48.0
|
||||
svelte-check: 2.4.5_2pvebpkgu3ohgo43qaf5qmcxwm
|
||||
@ -758,14 +760,14 @@ packages:
|
||||
tiny-glob: 0.2.9
|
||||
dev: true
|
||||
|
||||
/@sveltejs/kit/1.0.0-next.345_svelte@3.48.0:
|
||||
resolution: {integrity: sha512-2nLZoXZ02uXMSxqRAMRCr/J4aCphqgKLxEhRRyh3c3aWLAjWiDWLDcvSB770eHt3y0MkYrTvp7JrDF7RhfyuBA==}
|
||||
/@sveltejs/kit/1.0.0-next.348_svelte@3.48.0:
|
||||
resolution: {integrity: sha512-K9dfgzIbotWmbcdCsQ6ROGs9R+bsGWwmSdN6l6km1QV5esQehqg1UYHGD9q0VJsg4rJg/zmKVBYo0oBquSHPZw==}
|
||||
engines: {node: '>=16.7'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
svelte: ^3.44.0
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 1.0.0-next.44_svelte@3.48.0+vite@2.9.9
|
||||
'@sveltejs/vite-plugin-svelte': 1.0.0-next.47_svelte@3.48.0+vite@2.9.9
|
||||
chokidar: 3.5.3
|
||||
sade: 1.8.1
|
||||
svelte: 3.48.0
|
||||
@ -778,8 +780,8 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@sveltejs/vite-plugin-svelte/1.0.0-next.44_svelte@3.48.0+vite@2.9.9:
|
||||
resolution: {integrity: sha512-n+sssEWbzykPS447FmnNyU5GxEhrBPDVd0lxNZnxRGz9P6651LjjwAnISKr3CKgT9v8IybP8VD0n2i5XzbqExg==}
|
||||
/@sveltejs/vite-plugin-svelte/1.0.0-next.47_svelte@3.48.0+vite@2.9.9:
|
||||
resolution: {integrity: sha512-J6n8UN51aq/TEZGQ89/EtdXTtca3cRcTJGzi6fi+xK8LkgsHQLCZhRj+PJ+swktRSWTX9IOmQS55SqVg6bz5fA==}
|
||||
engines: {node: ^14.13.1 || >= 16}
|
||||
peerDependencies:
|
||||
diff-match-patch: ^1.0.5
|
||||
@ -795,7 +797,7 @@ packages:
|
||||
kleur: 4.1.4
|
||||
magic-string: 0.26.2
|
||||
svelte: 3.48.0
|
||||
svelte-hmr: 0.14.11_svelte@3.48.0
|
||||
svelte-hmr: 0.14.12_svelte@3.48.0
|
||||
vite: 2.9.9
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -3986,6 +3988,16 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/prettier-plugin-svelte/2.7.0_kkjbqzpydplecjtkxrgomroeru:
|
||||
resolution: {integrity: sha512-fQhhZICprZot2IqEyoiUYLTRdumULGRvw0o4dzl5jt0jfzVWdGqeYW27QTWAeXhoupEZJULmNoH3ueJwUWFLIA==}
|
||||
peerDependencies:
|
||||
prettier: ^1.16.4 || ^2.0.0
|
||||
svelte: ^3.2.0
|
||||
dependencies:
|
||||
prettier: 2.6.2
|
||||
svelte: 3.48.0
|
||||
dev: true
|
||||
|
||||
/prettier/2.6.2:
|
||||
resolution: {integrity: sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
@ -4519,8 +4531,8 @@ packages:
|
||||
- sugarss
|
||||
dev: true
|
||||
|
||||
/svelte-hmr/0.14.11_svelte@3.48.0:
|
||||
resolution: {integrity: sha512-R9CVfX6DXxW1Kn45Jtmx+yUe+sPhrbYSUp7TkzbW0jI5fVPn6lsNG9NEs5dFg5qRhFNAoVdRw5qQDLALNKhwbQ==}
|
||||
/svelte-hmr/0.14.12_svelte@3.48.0:
|
||||
resolution: {integrity: sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==}
|
||||
engines: {node: ^12.20 || ^14.13.1 || >= 16}
|
||||
peerDependencies:
|
||||
svelte: '>=3.19.0'
|
||||
|
||||
@ -1,73 +1,72 @@
|
||||
<script lang="ts">
|
||||
import { Button } from 'omorphia';
|
||||
import IconMoon from 'virtual:icons/heroicons-outline/moon';
|
||||
import IconSun from 'virtual:icons/heroicons-outline/sun';
|
||||
import { Button } from 'omorphia'
|
||||
import IconMoon from 'virtual:icons/heroicons-outline/moon'
|
||||
import IconSun from 'virtual:icons/heroicons-outline/sun'
|
||||
|
||||
export let meta: { raised: boolean };
|
||||
export let meta: { raised: boolean }
|
||||
|
||||
let theme = 'light';
|
||||
let background = meta.raised ? 'var(--color-raised-bg)' : 'var(--color-bg)';
|
||||
let theme = 'light'
|
||||
let background = meta.raised ? 'var(--color-raised-bg)' : 'var(--color-bg)'
|
||||
</script>
|
||||
|
||||
<div class="example">
|
||||
<div class="example__preview theme-{theme} base" style:background>
|
||||
<slot name="example" />
|
||||
</div>
|
||||
<div class="example__source">
|
||||
<div class="example__source__options">
|
||||
<Button
|
||||
color="primary-light"
|
||||
on:click={() => (theme === 'light' ? (theme = 'dark') : (theme = 'light'))}
|
||||
>
|
||||
{#if theme === 'light'}
|
||||
<IconMoon />
|
||||
{:else}
|
||||
<IconSun />
|
||||
{/if}
|
||||
</Button>
|
||||
</div>
|
||||
<pre class="example__source__code language-svelte"><slot name="code" /></pre>
|
||||
</div>
|
||||
<div class="example__preview theme-{theme} base" style:background>
|
||||
<slot name="example" />
|
||||
</div>
|
||||
<div class="example__source">
|
||||
<div class="example__source__options">
|
||||
<Button
|
||||
color="primary-light"
|
||||
on:click={() => (theme === 'light' ? (theme = 'dark') : (theme = 'light'))}>
|
||||
{#if theme === 'light'}
|
||||
<IconMoon />
|
||||
{:else}
|
||||
<IconSun />
|
||||
{/if}
|
||||
</Button>
|
||||
</div>
|
||||
<pre class="example__source__code language-svelte"><slot name="code" /></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.example {
|
||||
margin: 15px 0 32px;
|
||||
.example {
|
||||
margin: 15px 0 32px;
|
||||
|
||||
&__preview {
|
||||
border-radius: var(--rounded-sm-top);
|
||||
border: solid 2px hsl(0, 0%, 20%);
|
||||
border-bottom: none;
|
||||
display: flex;
|
||||
grid-gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
justify-content: flex-start;
|
||||
z-index: 1;
|
||||
padding: 16px;
|
||||
}
|
||||
&__preview {
|
||||
border-radius: var(--rounded-sm-top);
|
||||
border: solid 2px hsl(0, 0%, 20%);
|
||||
border-bottom: none;
|
||||
display: flex;
|
||||
grid-gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
justify-content: flex-start;
|
||||
z-index: 1;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
&__source {
|
||||
position: relative;
|
||||
&__source {
|
||||
position: relative;
|
||||
|
||||
&__options {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 8px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
&__options {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 8px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
:global(button) {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
:global(button) {
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
&__code {
|
||||
margin: 0;
|
||||
border-radius: var(--rounded-sm-bottom) !important;
|
||||
background: hsl(220, 13%, 22%);
|
||||
}
|
||||
}
|
||||
}
|
||||
&__code {
|
||||
margin: 0;
|
||||
border-radius: var(--rounded-sm-bottom) !important;
|
||||
background: hsl(220, 13%, 22%);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,112 +1,111 @@
|
||||
<script lang="ts">
|
||||
import OmorphiaLogo from '../assets/omorphia.svg';
|
||||
import IconLogoGithub from 'virtual:icons/carbon/logo-github';
|
||||
import IconChat from 'virtual:icons/heroicons-outline/chat-alt-2';
|
||||
import { onMount } from 'svelte';
|
||||
import OmorphiaLogo from '../assets/omorphia.svg'
|
||||
import IconLogoGithub from 'virtual:icons/carbon/logo-github'
|
||||
import IconChat from 'virtual:icons/heroicons-outline/chat-alt-2'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
let headerElement;
|
||||
let headerElement
|
||||
|
||||
onMount(() => {
|
||||
let lastScrollTop: number;
|
||||
window.addEventListener('scroll', () => {
|
||||
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
||||
if (scrollTop > lastScrollTop && headerElement) {
|
||||
headerElement.style.top = '-100%';
|
||||
} else if (headerElement) {
|
||||
headerElement.style.top = '0';
|
||||
}
|
||||
lastScrollTop = scrollTop;
|
||||
});
|
||||
});
|
||||
onMount(() => {
|
||||
let lastScrollTop: number
|
||||
window.addEventListener('scroll', () => {
|
||||
let scrollTop = window.pageYOffset || document.documentElement.scrollTop
|
||||
if (scrollTop > lastScrollTop && headerElement) {
|
||||
headerElement.style.top = '-100%'
|
||||
} else if (headerElement) {
|
||||
headerElement.style.top = '0'
|
||||
}
|
||||
lastScrollTop = scrollTop
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<header class="header" bind:this={headerElement}>
|
||||
<OmorphiaLogo class="header__logo" />
|
||||
<div class="header__title">Omorphia</div>
|
||||
<div class="header__links">
|
||||
<a class="hide-sm" href="https://modrinth.com">Modrinth.com</a>
|
||||
<span class="spacer-dot hide-sm" />
|
||||
<a href="https://www.npmjs.com/package/omorphia">NPM</a>
|
||||
<span class="spacer-dot" />
|
||||
<a href="https://rewrite.modrinth.com/discord">
|
||||
<IconChat />
|
||||
</a>
|
||||
<a href="https://github.com/modrinth/omorphia">
|
||||
<IconLogoGithub />
|
||||
</a>
|
||||
</div>
|
||||
<OmorphiaLogo class="header__logo" />
|
||||
<div class="header__title">Omorphia</div>
|
||||
<div class="header__links">
|
||||
<a class="hide-sm" href="https://modrinth.com">Modrinth.com</a>
|
||||
<span class="spacer-dot hide-sm" />
|
||||
<a href="https://www.npmjs.com/package/omorphia">NPM</a>
|
||||
<span class="spacer-dot" />
|
||||
<a href="https://rewrite.modrinth.com/discord">
|
||||
<IconChat />
|
||||
</a>
|
||||
<a href="https://github.com/modrinth/omorphia">
|
||||
<IconLogoGithub />
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<style lang="postcss">
|
||||
.header {
|
||||
display: flex;
|
||||
grid-gap: 10px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 16px 24px;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
background-color: hsl(0, 0%, 100%);
|
||||
box-shadow: hsla(221, 39%, 11%, 0.2) 0 2px 4px 0,
|
||||
hsla(221, 39%, 11%, 0.05) 0 -2px 2px 0 inset;
|
||||
transition: top 0.3s ease-in-out;
|
||||
.header {
|
||||
display: flex;
|
||||
grid-gap: 10px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 16px 24px;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
background-color: hsl(0, 0%, 100%);
|
||||
box-shadow: hsla(221, 39%, 11%, 0.2) 0 2px 4px 0, hsla(221, 39%, 11%, 0.05) 0 -2px 2px 0 inset;
|
||||
transition: top 0.3s ease-in-out;
|
||||
|
||||
@media not (--sm) {
|
||||
top: 0 !important;
|
||||
}
|
||||
@media not (--sm) {
|
||||
top: 0 !important;
|
||||
}
|
||||
|
||||
@media (--sm) {
|
||||
padding: 10px 32px;
|
||||
}
|
||||
@media (--sm) {
|
||||
padding: 10px 32px;
|
||||
}
|
||||
|
||||
:global(&__logo) {
|
||||
max-width: 32px;
|
||||
min-width: 32px;
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
:global(&__logo) {
|
||||
max-width: 32px;
|
||||
min-width: 32px;
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
&__title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&__links {
|
||||
margin-left: auto;
|
||||
grid-gap: 16px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
&__links {
|
||||
margin-left: auto;
|
||||
grid-gap: 16px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
|
||||
:global(svg) {
|
||||
height: 22px;
|
||||
width: auto;
|
||||
}
|
||||
:global(svg) {
|
||||
height: 22px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.hide-sm {
|
||||
display: none;
|
||||
.hide-sm {
|
||||
display: none;
|
||||
|
||||
@media (--sm) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
@media (--sm) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
&:not(:hover) {
|
||||
color: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:not(:hover) {
|
||||
color: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.spacer-dot {
|
||||
background-color: hsla(0, 0%, 0%, 0.2);
|
||||
border-radius: 999px;
|
||||
width: 5px;
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
.spacer-dot {
|
||||
background-color: hsla(0, 0%, 0%, 0.2);
|
||||
border-radius: 999px;
|
||||
width: 5px;
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,162 +1,157 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/stores'
|
||||
|
||||
import IconMenu from 'virtual:icons/lucide/menu';
|
||||
import IconMenu from 'virtual:icons/lucide/menu'
|
||||
|
||||
const components = Object.keys(import.meta.glob('../../routes/components/**'))
|
||||
.map((it) => it.replace('../../routes/components/', '').replace('.md', ''))
|
||||
.sort();
|
||||
const components = Object.keys(import.meta.glob('../../routes/components/**'))
|
||||
.map((it) => it.replace('../../routes/components/', '').replace('.md', ''))
|
||||
.sort()
|
||||
|
||||
const classes = Object.keys(import.meta.glob('../../routes/classes/**'))
|
||||
.map((it) => it.replace('../../routes/classes/', '').replace('.md', ''))
|
||||
.sort();
|
||||
const classes = Object.keys(import.meta.glob('../../routes/classes/**'))
|
||||
.map((it) => it.replace('../../routes/classes/', '').replace('.md', ''))
|
||||
.sort()
|
||||
|
||||
let slideIn = false;
|
||||
let slideIn = false
|
||||
|
||||
$: if ($page.url.pathname) {
|
||||
slideIn = false;
|
||||
}
|
||||
$: if ($page.url.pathname) {
|
||||
slideIn = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<nav class="sidebar" class:slideIn>
|
||||
<div class="sidebar__content">
|
||||
<div class="section">
|
||||
<span class="section__title">Getting started</span>
|
||||
<a href="/" class="section__link">Introduction</a>
|
||||
<a href="/getting-started/configure" class="section__link">Configure</a>
|
||||
<a href="/getting-started/icons" class="section__link">Using Icons</a>
|
||||
<!-- <a href="/getting-started/css" class="section__link">Writing CSS</a> -->
|
||||
<a href="/getting-started/illustrations" class="section__link">Illustrations</a>
|
||||
<a href="/getting-started/utils" class="section__link">Built-in utilities</a>
|
||||
<a href="/getting-started/generator" class="section__link">Generator plugin</a>
|
||||
</div>
|
||||
<div class="sidebar__content">
|
||||
<div class="section">
|
||||
<span class="section__title">Getting started</span>
|
||||
<a href="/" class="section__link">Introduction</a>
|
||||
<a href="/getting-started/configure" class="section__link">Configure</a>
|
||||
<a href="/getting-started/icons" class="section__link">Using Icons</a>
|
||||
<!-- <a href="/getting-started/css" class="section__link">Writing CSS</a> -->
|
||||
<a href="/getting-started/illustrations" class="section__link">Illustrations</a>
|
||||
<a href="/getting-started/utils" class="section__link">Built-in utilities</a>
|
||||
<a href="/getting-started/generator" class="section__link">Generator plugin</a>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<span class="section__title">Components</span>
|
||||
{#each components as component}
|
||||
<a href="/components/{component}" class="section__link">{component}</a>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="section">
|
||||
<span class="section__title">Components</span>
|
||||
{#each components as component}
|
||||
<a href="/components/{component}" class="section__link">{component}</a>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<span class="section__title">Classes</span>
|
||||
{#each classes as page}
|
||||
<a href="/classes/{page}" class="section__link">{page}</a>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<span class="section__title">Classes</span>
|
||||
{#each classes as page}
|
||||
<a href="/classes/{page}" class="section__link">{page}</a>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="sidebar__toggle" on:click={() => (slideIn = !slideIn)}>
|
||||
<IconMenu />
|
||||
</button>
|
||||
<button class="sidebar__toggle" on:click={() => (slideIn = !slideIn)}>
|
||||
<IconMenu />
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<style lang="postcss">
|
||||
:root {
|
||||
--sidebar-color: hsl(220, 15%, 40%);
|
||||
--title-color: hsl(216, 10%, 80%);
|
||||
--link-color: hsl(216, 10%, 90%);
|
||||
--scrollbar-thumb-color: hsl(216, 10%, 70%);
|
||||
}
|
||||
:root {
|
||||
--sidebar-color: hsl(220, 15%, 40%);
|
||||
--title-color: hsl(216, 10%, 80%);
|
||||
--link-color: hsl(216, 10%, 90%);
|
||||
--scrollbar-thumb-color: hsl(216, 10%, 70%);
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-color: var(--sidebar-color);
|
||||
color: var(--title-color);
|
||||
width: var(--sidebar-width);
|
||||
max-width: 70vw;
|
||||
position: fixed;
|
||||
left: -100%;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
transition: left 0.2s ease-in-out;
|
||||
box-shadow: 2px 0px 4px hsla(221, 39%, 11%, 0.2);
|
||||
.sidebar {
|
||||
background-color: var(--sidebar-color);
|
||||
color: var(--title-color);
|
||||
width: var(--sidebar-width);
|
||||
max-width: 70vw;
|
||||
position: fixed;
|
||||
left: -100%;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
transition: left 0.2s ease-in-out;
|
||||
box-shadow: 2px 0px 4px hsla(221, 39%, 11%, 0.2);
|
||||
|
||||
@media (--md) {
|
||||
left: 0;
|
||||
}
|
||||
@media (--md) {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&__content {
|
||||
mask-image: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
hsla(0, 0%, 0%, 1) 5% 95%,
|
||||
transparent
|
||||
);
|
||||
padding: 88px 32px 32px;
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
grid-gap: 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&__content {
|
||||
mask-image: linear-gradient(to bottom, transparent, hsla(0, 0%, 0%, 1) 5% 95%, transparent);
|
||||
padding: 88px 32px 32px;
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
grid-gap: 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-gap: 0.5rem;
|
||||
.section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-gap: 0.5rem;
|
||||
|
||||
&__title {
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
}
|
||||
&__title {
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&__link {
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
&__link {
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
color: white;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__toggle {
|
||||
position: fixed;
|
||||
left: 16px;
|
||||
bottom: 16px;
|
||||
padding: 8px;
|
||||
aspect-ratio: 1 / 1;
|
||||
background-color: var(--accent-color);
|
||||
z-index: 20;
|
||||
border-radius: var(--rounded);
|
||||
color: white;
|
||||
box-shadow: var(--shadow-inset-sm), var(--shadow-floating);
|
||||
transition: left 0.2s cubic-bezier(0.38, 0.52, 0.37, 1.27);
|
||||
&__toggle {
|
||||
position: fixed;
|
||||
left: 16px;
|
||||
bottom: 16px;
|
||||
padding: 8px;
|
||||
aspect-ratio: 1 / 1;
|
||||
background-color: var(--accent-color);
|
||||
z-index: 20;
|
||||
border-radius: var(--rounded);
|
||||
color: white;
|
||||
box-shadow: var(--shadow-inset-sm), var(--shadow-floating);
|
||||
transition: left 0.2s cubic-bezier(0.38, 0.52, 0.37, 1.27);
|
||||
|
||||
:global(.icon) {
|
||||
width: 32px;
|
||||
height: auto;
|
||||
}
|
||||
:global(.icon) {
|
||||
width: 32px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@media (--md) {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@media (--md) {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&.slideIn {
|
||||
left: 0;
|
||||
&.slideIn {
|
||||
left: 0;
|
||||
|
||||
.sidebar__toggle {
|
||||
left: calc(32px + min(70vw, var(--sidebar-width)));
|
||||
}
|
||||
}
|
||||
.sidebar__toggle {
|
||||
left: calc(32px + min(70vw, var(--sidebar-width)));
|
||||
}
|
||||
}
|
||||
|
||||
scrollbar-color: var(--scrollbar-thumb-color) var(--sidebar-color);
|
||||
scrollbar-color: var(--scrollbar-thumb-color) var(--sidebar-color);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 14px;
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: var(--sidebar-color);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: var(--sidebar-color);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--scrollbar-thumb-color);
|
||||
border-radius: 999px;
|
||||
border: 3px solid var(--sidebar-color);
|
||||
}
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--scrollbar-thumb-color);
|
||||
border-radius: 999px;
|
||||
border: 3px solid var(--sidebar-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,147 +1,143 @@
|
||||
<script lang="ts">
|
||||
import IconPencil from 'virtual:icons/heroicons-outline/pencil';
|
||||
import { page } from '$app/stores';
|
||||
import COMPONENT_API from '../../generated/COMPONENT_API.json';
|
||||
import IconPencil from 'virtual:icons/heroicons-outline/pencil'
|
||||
import { page } from '$app/stores'
|
||||
import COMPONENT_API from '../../generated/COMPONENT_API.json'
|
||||
|
||||
export let fileName = $page.url.pathname
|
||||
.substring($page.url.pathname.lastIndexOf('/') + 1)
|
||||
.replace('.html', '');
|
||||
export let fileName = $page.url.pathname
|
||||
.substring($page.url.pathname.lastIndexOf('/') + 1)
|
||||
.replace('.html', '')
|
||||
|
||||
export let title = fileName;
|
||||
export let title = fileName
|
||||
|
||||
export let description = 'Learn about Omorphia, the component & style library';
|
||||
export let description = 'Learn about Omorphia, the component & style library'
|
||||
|
||||
let editUrl = `https://github.com/modrinth/omorphia/edit/main/src/routes/${
|
||||
$page.url.pathname.replace('/', '') || 'index'
|
||||
}.md`;
|
||||
let editUrl = `https://github.com/modrinth/omorphia/edit/main/src/routes/${
|
||||
$page.url.pathname.replace('/', '') || 'index'
|
||||
}.md`
|
||||
|
||||
let api;
|
||||
if ($page.url.pathname.includes('components')) {
|
||||
if (import.meta.env.DEV) {
|
||||
import(`../../../package/components/${title}.svelte?raw&sveld`).then(
|
||||
(output) => (api = output.default)
|
||||
);
|
||||
} else {
|
||||
api = COMPONENT_API[`${title}.svelte`];
|
||||
}
|
||||
}
|
||||
let api
|
||||
if ($page.url.pathname.includes('components')) {
|
||||
if (import.meta.env.DEV) {
|
||||
import(`../../../package/components/${title}.svelte?raw&sveld`).then(
|
||||
(output) => (api = output.default)
|
||||
)
|
||||
} else {
|
||||
api = COMPONENT_API[`${title}.svelte`]
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{title ? `${title} • Omorphia` : 'Omorphia'}</title>
|
||||
<meta name="description" content={description} />
|
||||
<title>{title ? `${title} • Omorphia` : 'Omorphia'}</title>
|
||||
<meta name="description" content={description} />
|
||||
</svelte:head>
|
||||
|
||||
{#if title}<h1>{title}</h1>{/if}
|
||||
<a class="edit-link" href={editUrl}>
|
||||
<IconPencil />
|
||||
Edit this page on GitHub</a
|
||||
>
|
||||
<IconPencil />
|
||||
Edit this page on GitHub</a>
|
||||
<slot />
|
||||
|
||||
{#if api}
|
||||
<div class="extra-info">
|
||||
{#if api.props.length > 0}
|
||||
<h2>Properties</h2>
|
||||
<table class="api-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each api.props as prop}
|
||||
<tr>
|
||||
<td><code>{prop.name}</code></td>
|
||||
<td><code>{prop.type ?? ''}</code></td>
|
||||
<td><code>{prop.value ?? ''}</code></td>
|
||||
<td
|
||||
>{prop.constant ? '[Read only] ' : ''}{prop.description?.replace(
|
||||
'null',
|
||||
''
|
||||
) || ''}</td
|
||||
>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
{#if api.events.length > 0}
|
||||
<h2>Events</h2>
|
||||
<table class="api-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Forwarded</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each api.events as event}
|
||||
<tr>
|
||||
<td><code>{event.name}</code></td>
|
||||
<td>{!!event.parent}</td>
|
||||
<td>{event.description?.replace('null', '') || ''}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
{#if api.slots.length > 0}
|
||||
<h2>Slots</h2>
|
||||
<table class="api-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Fallback</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each api.slots as slot}
|
||||
<tr>
|
||||
<td><code>{slot.name}</code></td>
|
||||
<td>{slot.fallback ?? 'None'}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="extra-info">
|
||||
{#if api.props.length > 0}
|
||||
<h2>Properties</h2>
|
||||
<table class="api-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Default</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each api.props as prop}
|
||||
<tr>
|
||||
<td><code>{prop.name}</code></td>
|
||||
<td><code>{prop.type ?? ''}</code></td>
|
||||
<td><code>{prop.value ?? ''}</code></td>
|
||||
<td
|
||||
>{prop.constant ? '[Read only] ' : ''}{prop.description?.replace('null', '') ||
|
||||
''}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
{#if api.events.length > 0}
|
||||
<h2>Events</h2>
|
||||
<table class="api-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Forwarded</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each api.events as event}
|
||||
<tr>
|
||||
<td><code>{event.name}</code></td>
|
||||
<td>{!!event.parent}</td>
|
||||
<td>{event.description?.replace('null', '') || ''}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
{#if api.slots.length > 0}
|
||||
<h2>Slots</h2>
|
||||
<table class="api-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Fallback</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each api.slots as slot}
|
||||
<tr>
|
||||
<td><code>{slot.name}</code></td>
|
||||
<td>{slot.fallback ?? 'None'}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
.edit-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
grid-gap: 8px;
|
||||
margin-bottom: 54px;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
.edit-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
grid-gap: 8px;
|
||||
margin-bottom: 54px;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.extra-info {
|
||||
margin-top: 64px;
|
||||
}
|
||||
.extra-info {
|
||||
margin-top: 64px;
|
||||
}
|
||||
|
||||
.api-table {
|
||||
border-collapse: collapse;
|
||||
margin-top: -6px;
|
||||
}
|
||||
.api-table {
|
||||
border-collapse: collapse;
|
||||
margin-top: -6px;
|
||||
}
|
||||
|
||||
.api-table tr {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
.api-table tr {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.api-table tbody {
|
||||
border: 2px solid grey;
|
||||
}
|
||||
.api-table tbody {
|
||||
border: 2px solid grey;
|
||||
}
|
||||
|
||||
.api-table th {
|
||||
text-transform: uppercase;
|
||||
font-size: 12.5px;
|
||||
border: none;
|
||||
}
|
||||
.api-table th {
|
||||
text-transform: uppercase;
|
||||
font-size: 12.5px;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,102 +1,100 @@
|
||||
<script lang="ts">
|
||||
// TODO: Make square icon `md` more rounded
|
||||
// TODO: Make square icon `md` more rounded
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
import { classCombine } from '../utils/classCombine';
|
||||
import { onMount } from 'svelte'
|
||||
import { classCombine } from '../utils/classCombine'
|
||||
|
||||
/** Optional, as a default icon will be substituted if no image was specified */
|
||||
export let src: string | undefined;
|
||||
export let size: 'xs' | 'sm' | 'md' | 'lg';
|
||||
export let circle = false;
|
||||
export let floatUp = false;
|
||||
/** Optional, as a default icon will be substituted if no image was specified */
|
||||
export let src: string | undefined
|
||||
export let size: 'xs' | 'sm' | 'md' | 'lg'
|
||||
export let circle = false
|
||||
export let floatUp = false
|
||||
|
||||
let className: string;
|
||||
$: className = classCombine([
|
||||
'avatar',
|
||||
circle && 'avatar--circle',
|
||||
`avatar--size-${size}`,
|
||||
floatUp && 'avatar--float-up',
|
||||
]);
|
||||
let className: string
|
||||
$: className = classCombine([
|
||||
'avatar',
|
||||
circle && 'avatar--circle',
|
||||
`avatar--size-${size}`,
|
||||
floatUp && 'avatar--float-up',
|
||||
])
|
||||
|
||||
let img;
|
||||
let img
|
||||
|
||||
onMount(() => {
|
||||
if (img && img.naturalWidth) {
|
||||
const isPixelated = () => {
|
||||
if (img.naturalWidth < 96 && img.naturalWidth > 0) {
|
||||
img.style = 'image-rendering: pixelated;';
|
||||
}
|
||||
};
|
||||
onMount(() => {
|
||||
if (img && img.naturalWidth) {
|
||||
const isPixelated = () => {
|
||||
if (img.naturalWidth < 96 && img.naturalWidth > 0) {
|
||||
img.style = 'image-rendering: pixelated;'
|
||||
}
|
||||
}
|
||||
|
||||
if (img.naturalWidth) {
|
||||
isPixelated();
|
||||
} else {
|
||||
img.onload = isPixelated;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (img.naturalWidth) {
|
||||
isPixelated()
|
||||
} else {
|
||||
img.onload = isPixelated
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if src}
|
||||
<img {src} bind:this={img} class={className} alt="" />
|
||||
<img {src} bind:this={img} class={className} alt="" />
|
||||
{:else}
|
||||
<svg
|
||||
class={className}
|
||||
xml:space="preserve"
|
||||
fill-rule="evenodd"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-miterlimit="1.5"
|
||||
clip-rule="evenodd"
|
||||
viewBox="0 0 104 104"
|
||||
>
|
||||
<path fill="none" d="M0 0h103.4v103.4H0z" />
|
||||
<path
|
||||
fill="none"
|
||||
stroke="#9a9a9a"
|
||||
stroke-width="5"
|
||||
d="M51.7 92.5V51.7L16.4 31.3l35.3 20.4L87 31.3 51.7 11 16.4 31.3v40.8l35.3 20.4L87 72V31.3L51.7 11"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
class={className}
|
||||
xml:space="preserve"
|
||||
fill-rule="evenodd"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-miterlimit="1.5"
|
||||
clip-rule="evenodd"
|
||||
viewBox="0 0 104 104">
|
||||
<path fill="none" d="M0 0h103.4v103.4H0z" />
|
||||
<path
|
||||
fill="none"
|
||||
stroke="#9a9a9a"
|
||||
stroke-width="5"
|
||||
d="M51.7 92.5V51.7L16.4 31.3l35.3 20.4L87 31.3 51.7 11 16.4 31.3v40.8l35.3 20.4L87 72V31.3L51.7 11" />
|
||||
</svg>
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
.avatar {
|
||||
border-radius: var(--rounded);
|
||||
box-shadow: var(--shadow-inset-lg), var(--shadow-raised-lg);
|
||||
height: var(--size);
|
||||
width: var(--size);
|
||||
background-color: var(--color-button-bg);
|
||||
.avatar {
|
||||
border-radius: var(--rounded);
|
||||
box-shadow: var(--shadow-inset-lg), var(--shadow-raised-lg);
|
||||
height: var(--size);
|
||||
width: var(--size);
|
||||
background-color: var(--color-button-bg);
|
||||
|
||||
&--size {
|
||||
&-xs {
|
||||
--size: 2.25rem;
|
||||
box-shadow: var(--shadow-inset), var(--shadow-raised);
|
||||
}
|
||||
&--size {
|
||||
&-xs {
|
||||
--size: 2.25rem;
|
||||
box-shadow: var(--shadow-inset), var(--shadow-raised);
|
||||
}
|
||||
|
||||
&-sm {
|
||||
--size: 3rem;
|
||||
box-shadow: var(--shadow-inset), var(--shadow-raised);
|
||||
}
|
||||
&-sm {
|
||||
--size: 3rem;
|
||||
box-shadow: var(--shadow-inset), var(--shadow-raised);
|
||||
}
|
||||
|
||||
&-md {
|
||||
--size: 6rem;
|
||||
border-radius: var(--rounded-lg);
|
||||
}
|
||||
&-md {
|
||||
--size: 6rem;
|
||||
border-radius: var(--rounded-lg);
|
||||
}
|
||||
|
||||
&-lg {
|
||||
--size: 9rem;
|
||||
border-radius: var(--rounded-lg);
|
||||
}
|
||||
}
|
||||
&-lg {
|
||||
--size: 9rem;
|
||||
border-radius: var(--rounded-lg);
|
||||
}
|
||||
}
|
||||
|
||||
&--float-up {
|
||||
margin-top: calc(var(--size) * (-2 / 3));
|
||||
z-index: 1;
|
||||
}
|
||||
&--float-up {
|
||||
margin-top: calc(var(--size) * (-2 / 3));
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&--circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
&--circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,51 +1,51 @@
|
||||
<script lang="ts">
|
||||
export let label = ''
|
||||
/** Supports `green`, `yellow`, `red`, & `gray` */
|
||||
export let color = 'gray'
|
||||
export let label = ''
|
||||
/** Supports `green`, `yellow`, `red`, & `gray` */
|
||||
export let color = 'gray'
|
||||
</script>
|
||||
|
||||
<div class="badge badge--color-{color}">
|
||||
{label}
|
||||
{label}
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.badge {
|
||||
font-weight: var(--font-weight-bold);
|
||||
display: inline;
|
||||
position: relative;
|
||||
padding-left: 0.9rem;
|
||||
line-height: 1rem;
|
||||
.badge {
|
||||
font-weight: var(--font-weight-bold);
|
||||
display: inline;
|
||||
position: relative;
|
||||
padding-left: 0.9rem;
|
||||
line-height: 1rem;
|
||||
|
||||
&--color-green {
|
||||
color: var(--color-badge-green-text);
|
||||
--color-dot: var(--color-badge-green-dot);
|
||||
}
|
||||
&--color-green {
|
||||
color: var(--color-badge-green-text);
|
||||
--color-dot: var(--color-badge-green-dot);
|
||||
}
|
||||
|
||||
&--color-yellow {
|
||||
color: var(--color-badge-yellow-text);
|
||||
--color-dot: var(--color-badge-yellow-dot);
|
||||
}
|
||||
&--color-yellow {
|
||||
color: var(--color-badge-yellow-text);
|
||||
--color-dot: var(--color-badge-yellow-dot);
|
||||
}
|
||||
|
||||
&--color-red {
|
||||
color: var(--color-badge-red-text);
|
||||
--color-dot: var(--color-badge-red-dot);
|
||||
}
|
||||
&--color-red {
|
||||
color: var(--color-badge-red-text);
|
||||
--color-dot: var(--color-badge-red-dot);
|
||||
}
|
||||
|
||||
&--color-gray {
|
||||
color: var(--color-badge-gray-text);
|
||||
--color-dot: var(--color-badge-gray-dot);
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: 50%;
|
||||
background-color: var(--color-dot);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 25%;
|
||||
}
|
||||
}
|
||||
&::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: 50%;
|
||||
background-color: var(--color-dot);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 25%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,156 +1,155 @@
|
||||
<script lang="ts">
|
||||
// TODO: sizes
|
||||
// TODO: icon only buttons should have uniform padding
|
||||
// TODO: Could be a class
|
||||
// TODO: sizes
|
||||
// TODO: icon only buttons should have uniform padding
|
||||
|
||||
import { classCombine } from '../utils/classCombine';
|
||||
import { classCombine } from '../utils/classCombine'
|
||||
|
||||
/** The element to be styled as a button */
|
||||
export let as: 'button' | 'a' | 'summary' | 'input' = 'button';
|
||||
export let href = '';
|
||||
if (href) as = 'a';
|
||||
/** The element to be styled as a button */
|
||||
export let as: 'button' | 'a' | 'summary' | 'input' = 'button'
|
||||
export let href = ''
|
||||
if (href) as = 'a'
|
||||
|
||||
/** Use `value` if the button is an `<input`> */
|
||||
export let value = '';
|
||||
/** Use `value` if the button is an `<input`> */
|
||||
export let value = ''
|
||||
|
||||
export let size: 'sm' | 'md' | 'lg' = 'md';
|
||||
export let color:
|
||||
| ''
|
||||
| 'raised'
|
||||
| 'primary'
|
||||
| 'primary-light'
|
||||
| 'secondary'
|
||||
| 'tertiary'
|
||||
| 'danger'
|
||||
| 'danger-light'
|
||||
| 'transparent' = '';
|
||||
export let size: 'sm' | 'md' | 'lg' = 'md'
|
||||
export let color:
|
||||
| ''
|
||||
| 'raised'
|
||||
| 'primary'
|
||||
| 'primary-light'
|
||||
| 'secondary'
|
||||
| 'tertiary'
|
||||
| 'danger'
|
||||
| 'danger-light'
|
||||
| 'transparent' = ''
|
||||
|
||||
/** Show notification badge in the upper right of button */
|
||||
export let badge = false;
|
||||
/** Show notification badge in the upper right of button */
|
||||
export let badge = false
|
||||
|
||||
export let disabled = false;
|
||||
export let disabled = false
|
||||
|
||||
/** Hover title for accessibility */
|
||||
export let title = '';
|
||||
/** Hover title for accessibility */
|
||||
export let title = ''
|
||||
|
||||
/** Link target */
|
||||
export let target = '';
|
||||
/** Link target */
|
||||
export let target = ''
|
||||
|
||||
let className: string;
|
||||
$: className = classCombine([
|
||||
'button',
|
||||
`button--size-${size}`,
|
||||
`button--color-${color}`,
|
||||
badge && 'has-badge',
|
||||
]);
|
||||
let className: string
|
||||
$: className = classCombine([
|
||||
'button',
|
||||
`button--size-${size}`,
|
||||
`button--color-${color}`,
|
||||
badge && 'has-badge',
|
||||
])
|
||||
</script>
|
||||
|
||||
{#if as === 'a'}
|
||||
<a class={className} {href} {disabled} {title} {target} on:click>
|
||||
<slot />
|
||||
</a>
|
||||
<a class={className} {href} {disabled} {title} {target} on:click>
|
||||
<slot />
|
||||
</a>
|
||||
{:else if as === 'input'}
|
||||
<input class={className} {value} {disabled} {title} on:click />
|
||||
<input class={className} {value} {disabled} {title} on:click />
|
||||
{:else}
|
||||
<svelte:element this={as} class={className} {disabled} {title} on:click>
|
||||
<slot />
|
||||
</svelte:element>
|
||||
<svelte:element this={as} class={className} {disabled} {title} on:click>
|
||||
<slot />
|
||||
</svelte:element>
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
.button {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 0.25rem 1rem;
|
||||
grid-gap: 14px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
.button {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 0.25rem 1rem;
|
||||
grid-gap: 14px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
|
||||
color: var(--color-bg-contrast);
|
||||
color: var(--color-bg-contrast);
|
||||
|
||||
box-shadow: var(--shadow-inset-sm);
|
||||
background-color: var(--color-button-bg);
|
||||
box-shadow: var(--shadow-inset-sm);
|
||||
background-color: var(--color-button-bg);
|
||||
|
||||
border-radius: var(--rounded);
|
||||
transition: opacity 0.5s ease-in-out, filter 0.05s ease-in-out;
|
||||
border-radius: var(--rounded);
|
||||
transition: opacity 0.5s ease-in-out, filter 0.2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
&:hover {
|
||||
filter: brightness(0.85);
|
||||
}
|
||||
|
||||
&--color {
|
||||
&-raised {
|
||||
background-color: var(--color-raised-bg);
|
||||
}
|
||||
&--color {
|
||||
&-raised {
|
||||
background-color: var(--color-raised-bg);
|
||||
}
|
||||
|
||||
&-primary {
|
||||
background-color: var(--color-brand);
|
||||
color: var(--color-brand-contrast);
|
||||
}
|
||||
&-primary {
|
||||
background-color: var(--color-brand);
|
||||
color: var(--color-brand-contrast);
|
||||
}
|
||||
|
||||
&-primary-light {
|
||||
background-color: var(--color-brand-light);
|
||||
}
|
||||
&-primary-light {
|
||||
background-color: var(--color-brand-light);
|
||||
}
|
||||
|
||||
&-secondary {
|
||||
background-color: var(--color-secondary);
|
||||
color: var(--color-brand-contrast);
|
||||
}
|
||||
&-secondary {
|
||||
background-color: var(--color-secondary);
|
||||
color: var(--color-brand-contrast);
|
||||
}
|
||||
|
||||
&-tertiary {
|
||||
background-color: var(--color-tertiary);
|
||||
}
|
||||
&-tertiary {
|
||||
background-color: var(--color-tertiary);
|
||||
}
|
||||
|
||||
&-transparent {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
&-transparent {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&-danger {
|
||||
background-color: var(--color-badge-red-dot);
|
||||
color: var(--color-brand-contrast);
|
||||
}
|
||||
&-danger {
|
||||
background-color: var(--color-badge-red-dot);
|
||||
color: var(--color-brand-contrast);
|
||||
}
|
||||
|
||||
&-danger-light {
|
||||
background-color: var(--color-popup-danger-bg);
|
||||
color: var(--color-popup-danger-text);
|
||||
}
|
||||
}
|
||||
&-danger-light {
|
||||
background-color: var(--color-popup-danger-bg);
|
||||
color: var(--color-popup-danger-text);
|
||||
}
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 50%;
|
||||
cursor: not-allowed;
|
||||
filter: grayscale(50%);
|
||||
&:disabled {
|
||||
opacity: 50%;
|
||||
cursor: not-allowed;
|
||||
filter: grayscale(50%);
|
||||
|
||||
/* Not ideal, but preventing events being fired needs to be implemented */
|
||||
pointer-events: none;
|
||||
}
|
||||
/* Not ideal, but preventing events being fired needs to be implemented */
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&--pad-even {
|
||||
padding: 0.5rem;
|
||||
font-size: 1rem;
|
||||
line-height: 0;
|
||||
min-width: 2rem;
|
||||
min-height: 2rem;
|
||||
justify-content: center;
|
||||
}
|
||||
&--pad-even {
|
||||
padding: 0.5rem;
|
||||
font-size: 1rem;
|
||||
line-height: 0;
|
||||
min-width: 2rem;
|
||||
min-height: 2rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&.has-badge::after {
|
||||
content: '';
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: var(--rounded-max);
|
||||
background-color: var(--color-brand);
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
}
|
||||
&.has-badge::after {
|
||||
content: '';
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: var(--rounded-max);
|
||||
background-color: var(--color-brand);
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
}
|
||||
|
||||
/* Only child doesn't work as intended because text is passed through as `innerText` */
|
||||
:global(.icon:only-child) {
|
||||
margin: 4px -7px;
|
||||
}
|
||||
}
|
||||
/* Only child doesn't work as intended because text is passed through as `innerText` */
|
||||
:global(.icon:only-child) {
|
||||
margin: 4px -7px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,66 +1,66 @@
|
||||
<script lang="ts">
|
||||
import { uniqueId } from '../utils/uniqueId'
|
||||
import IconCheck from 'virtual:icons/heroicons-outline/check'
|
||||
import { uniqueId } from '../utils/uniqueId'
|
||||
import IconCheck from 'virtual:icons/heroicons-outline/check'
|
||||
|
||||
export let checked = false;
|
||||
export let checked = false
|
||||
|
||||
const id = `checkbox-${uniqueId()}`
|
||||
const id = `checkbox-${uniqueId()}`
|
||||
</script>
|
||||
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" bind:checked={checked} on:change id={id} name={id}>
|
||||
<label for={id} class="checkbox__label">
|
||||
<span class="checkbox__label__box">
|
||||
<IconCheck />
|
||||
</span>
|
||||
<slot/>
|
||||
</label>
|
||||
<input type="checkbox" bind:checked on:change {id} name={id} />
|
||||
<label for={id} class="checkbox__label">
|
||||
<span class="checkbox__label__box">
|
||||
<IconCheck />
|
||||
</span>
|
||||
<slot />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.checkbox {
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
.checkbox {
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
grid-gap: 0.5rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
grid-gap: 0.5rem;
|
||||
|
||||
&__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
&__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
> :global(.icon) {
|
||||
width: 1.1rem;
|
||||
margin-right: -0.1rem;
|
||||
}
|
||||
> :global(.icon) {
|
||||
width: 1.1rem;
|
||||
margin-right: -0.1rem;
|
||||
}
|
||||
|
||||
&__box {
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
display: flex;
|
||||
border-radius: 0.25rem;
|
||||
background-color: var(--color-button-bg);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
&__box {
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
display: flex;
|
||||
border-radius: 0.25rem;
|
||||
background-color: var(--color-button-bg);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> :global(.icon) {
|
||||
display: none;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
color: var(--color-raised-bg)
|
||||
}
|
||||
}
|
||||
}
|
||||
> :global(.icon) {
|
||||
display: none;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
color: var(--color-raised-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[type=checkbox]:checked + label span {
|
||||
background-color: var(--color-brand);
|
||||
[type='checkbox']:checked + label span {
|
||||
background-color: var(--color-brand);
|
||||
|
||||
:global(.icon) {
|
||||
display: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
:global(.icon) {
|
||||
display: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,46 +1,46 @@
|
||||
<script lang="ts">
|
||||
import Checkbox from './Checkbox.svelte';
|
||||
import type { Option } from './types';
|
||||
import Checkbox from './Checkbox.svelte'
|
||||
import type { Option } from './types'
|
||||
|
||||
export let value = [];
|
||||
export let options: Option[] = [];
|
||||
export let value = []
|
||||
export let options: Option[] = []
|
||||
|
||||
/** Wrap the options horizontally */
|
||||
export let wrap = false;
|
||||
/** Wrap the options horizontally */
|
||||
export let wrap = false
|
||||
|
||||
const handleChange = (e, key) => {
|
||||
if (e.target.checked) {
|
||||
if (!value) value = [];
|
||||
value = [key, ...value];
|
||||
} else {
|
||||
value = value.filter((it) => key !== it);
|
||||
}
|
||||
};
|
||||
const handleChange = (e, key) => {
|
||||
if (e.target.checked) {
|
||||
if (!value) value = []
|
||||
value = [key, ...value]
|
||||
} else {
|
||||
value = value.filter((it) => key !== it)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="checkbox-list" class:wrap>
|
||||
{#each options as option}
|
||||
<Checkbox on:change={(e) => handleChange(e, option.value)}>
|
||||
{#if option.icon && typeof option.icon === 'string'}
|
||||
{@html option.icon}
|
||||
{:else if option.icon}
|
||||
<svelte:component this={option.icon} />
|
||||
{/if}
|
||||
{option.label}
|
||||
</Checkbox>
|
||||
{/each}
|
||||
{#each options as option}
|
||||
<Checkbox on:change={(e) => handleChange(e, option.value)}>
|
||||
{#if option.icon && typeof option.icon === 'string'}
|
||||
{@html option.icon}
|
||||
{:else if option.icon}
|
||||
<svelte:component this={option.icon} />
|
||||
{/if}
|
||||
{option.label}
|
||||
</Checkbox>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.checkbox-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
.checkbox-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
|
||||
&.wrap {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
grid-gap: 2rem;
|
||||
}
|
||||
}
|
||||
&.wrap {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
grid-gap: 2rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,45 +1,43 @@
|
||||
<script lang="ts">
|
||||
// TODO: Add fade out styling on top and bottom
|
||||
// TODO: Add fade out styling on top and bottom
|
||||
|
||||
import Checkbox from './Checkbox.svelte';
|
||||
import VirtualList from 'svelte-tiny-virtual-list';
|
||||
import type { Option } from './types';
|
||||
import Checkbox from './Checkbox.svelte'
|
||||
import VirtualList from 'svelte-tiny-virtual-list'
|
||||
import type { Option } from './types'
|
||||
|
||||
/** Height in pixels of list */
|
||||
export let height = 200;
|
||||
/** Height in pixels of list */
|
||||
export let height = 200
|
||||
|
||||
export let value = [];
|
||||
export let options: Option[] = [];
|
||||
export let value = []
|
||||
export let options: Option[] = []
|
||||
|
||||
const handleChange = (e, key) => {
|
||||
if (e.target.checked) {
|
||||
if (!value) value = [];
|
||||
value = [key, ...value];
|
||||
} else {
|
||||
value = value.filter((it) => key !== it);
|
||||
}
|
||||
};
|
||||
const handleChange = (e, key) => {
|
||||
if (e.target.checked) {
|
||||
if (!value) value = []
|
||||
value = [key, ...value]
|
||||
} else {
|
||||
value = value.filter((it) => key !== it)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<VirtualList width="100%" {height} itemCount={options.length} itemSize={26}>
|
||||
<div
|
||||
slot="item"
|
||||
let:index
|
||||
let:style
|
||||
{style}
|
||||
style:padding-bottom={options.length - 1 === index ? '2.5rem' : ''}
|
||||
>
|
||||
{@const option = options[index]}
|
||||
<Checkbox
|
||||
checked={value && value.includes(option.value)}
|
||||
on:change={(e) => handleChange(e, option.value)}
|
||||
>
|
||||
{#if option.icon && typeof option.icon === 'string'}
|
||||
{@html option.icon}
|
||||
{:else if option.icon}
|
||||
<svelte:component this={option.icon} />
|
||||
{/if}
|
||||
{option.label}
|
||||
</Checkbox>
|
||||
</div>
|
||||
<div
|
||||
slot="item"
|
||||
let:index
|
||||
let:style
|
||||
{style}
|
||||
style:padding-bottom={options.length - 1 === index ? '2.5rem' : ''}>
|
||||
{@const option = options[index]}
|
||||
<Checkbox
|
||||
checked={value && value.includes(option.value)}
|
||||
on:change={(e) => handleChange(e, option.value)}>
|
||||
{#if option.icon && typeof option.icon === 'string'}
|
||||
{@html option.icon}
|
||||
{:else if option.icon}
|
||||
<svelte:component this={option.icon} />
|
||||
{/if}
|
||||
{option.label}
|
||||
</Checkbox>
|
||||
</div>
|
||||
</VirtualList>
|
||||
|
||||
@ -1,48 +1,45 @@
|
||||
<script lang="ts">
|
||||
import Button from "./Button.svelte";
|
||||
import IconCheck from 'virtual:icons/heroicons-outline/check'
|
||||
import Button from './Button.svelte'
|
||||
import IconCheck from 'virtual:icons/heroicons-outline/check'
|
||||
|
||||
interface Option {
|
||||
label: string;
|
||||
value: string | number;
|
||||
}
|
||||
interface Option {
|
||||
label: string
|
||||
value: string | number
|
||||
}
|
||||
|
||||
export let options: Option[] = [];
|
||||
export let value: string | number;
|
||||
// If set to true, one chip is always selected
|
||||
export let neverEmpty = false;
|
||||
export let options: Option[] = []
|
||||
export let value: string | number
|
||||
// If set to true, one chip is always selected
|
||||
export let neverEmpty = false
|
||||
|
||||
let selected: Option | null = options.find((option) => option.value === (value || ''));
|
||||
let selected: Option | null = options.find((option) => option.value === (value || ''))
|
||||
|
||||
$: if (selected) {
|
||||
value = selected.value;
|
||||
} else {
|
||||
value = ''
|
||||
}
|
||||
$: if (selected) {
|
||||
value = selected.value
|
||||
} else {
|
||||
value = ''
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="chips">
|
||||
{#each options as option}
|
||||
{@const isSelected = selected?.value === option.value}
|
||||
<Button
|
||||
color={isSelected ? 'primary-light' : undefined}
|
||||
on:click={() => {
|
||||
isSelected && !neverEmpty
|
||||
? selected = null
|
||||
: selected = option
|
||||
}}
|
||||
>
|
||||
{#if isSelected}
|
||||
<IconCheck />
|
||||
{/if}
|
||||
{option.label}
|
||||
</Button>
|
||||
{/each}
|
||||
{#each options as option}
|
||||
{@const isSelected = selected?.value === option.value}
|
||||
<Button
|
||||
color={isSelected ? 'primary-light' : undefined}
|
||||
on:click={() => {
|
||||
isSelected && !neverEmpty ? (selected = null) : (selected = option)
|
||||
}}>
|
||||
{#if isSelected}
|
||||
<IconCheck />
|
||||
{/if}
|
||||
{option.label}
|
||||
</Button>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.chips {
|
||||
display: flex;
|
||||
grid-gap: 0.5rem;
|
||||
}
|
||||
.chips {
|
||||
display: flex;
|
||||
grid-gap: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,24 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { uniqueId } from '../utils/uniqueId'
|
||||
import { uniqueId } from '../utils/uniqueId'
|
||||
|
||||
export let required = false;
|
||||
export let label: string;
|
||||
export let required = false
|
||||
export let label: string
|
||||
|
||||
const id = `form-field-${uniqueId()}`
|
||||
const id = `form-field-${uniqueId()}`
|
||||
</script>
|
||||
|
||||
<div class="form-field">
|
||||
<label for={id} class="text-input__label" class:required>
|
||||
{label}
|
||||
</label>
|
||||
<slot {id} />
|
||||
<label for={id} class="text-input__label" class:required>
|
||||
{label}
|
||||
</label>
|
||||
<slot {id} />
|
||||
</div>
|
||||
|
||||
|
||||
<style lang="postcss">
|
||||
.form-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.form-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,80 +1,79 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/stores'
|
||||
|
||||
interface Link {
|
||||
href: string;
|
||||
label: string;
|
||||
}
|
||||
interface Link {
|
||||
href: string
|
||||
label: string
|
||||
}
|
||||
|
||||
export let links: Link[];
|
||||
export let query = '';
|
||||
export let links: Link[]
|
||||
export let query = ''
|
||||
|
||||
export let resetScroll = false;
|
||||
export let resetScroll = false
|
||||
|
||||
/** Path level in URL, zero-indexed */
|
||||
export let level = 0;
|
||||
/** Path level in URL, zero-indexed */
|
||||
export let level = 0
|
||||
|
||||
let path: string[];
|
||||
$: path = [
|
||||
...$page.url.pathname
|
||||
.substring(1)
|
||||
.split('/')
|
||||
.map((route) => '/' + route),
|
||||
'/',
|
||||
];
|
||||
let path: string[]
|
||||
$: path = [
|
||||
...$page.url.pathname
|
||||
.substring(1)
|
||||
.split('/')
|
||||
.map((route) => '/' + route),
|
||||
'/',
|
||||
]
|
||||
|
||||
$: basePath = path.slice(0, level).join('');
|
||||
$: basePath = path.slice(0, level).join('')
|
||||
</script>
|
||||
|
||||
<nav class="navigation">
|
||||
{#each links as link}
|
||||
<a
|
||||
href={query
|
||||
? link.href
|
||||
? `?${query}=${link.href}`
|
||||
: '?'
|
||||
: level === 0
|
||||
? link.href
|
||||
: basePath + link.href}
|
||||
on:click={() => {
|
||||
if (resetScroll) document.body.scrollTo(0, 0);
|
||||
}}
|
||||
class="navigation__link"
|
||||
class:is-active={query
|
||||
? ($page.url.searchParams.get(query) || '') === link.href
|
||||
: path[level] === link.href || path[level] === link.href.slice(0, -1)}
|
||||
sveltekit:noscroll={!resetScroll}>{link.label}</a
|
||||
>
|
||||
{/each}
|
||||
{#each links as link}
|
||||
<a
|
||||
href={query
|
||||
? link.href
|
||||
? `?${query}=${link.href}`
|
||||
: '?'
|
||||
: level === 0
|
||||
? link.href
|
||||
: basePath + link.href}
|
||||
on:click={() => {
|
||||
if (resetScroll) document.body.scrollTo(0, 0)
|
||||
}}
|
||||
class="navigation__link"
|
||||
class:is-active={query
|
||||
? ($page.url.searchParams.get(query) || '') === link.href
|
||||
: path[level] === link.href || path[level] === link.href.slice(0, -1)}
|
||||
sveltekit:noscroll={!resetScroll}>{link.label}</a>
|
||||
{/each}
|
||||
</nav>
|
||||
|
||||
<style lang="postcss">
|
||||
.navigation {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
grid-gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
.navigation {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
grid-gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&__link {
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--color-text-light);
|
||||
&__link {
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--color-text-light);
|
||||
|
||||
&.is-active {
|
||||
color: var(--color-text);
|
||||
position: relative;
|
||||
&.is-active {
|
||||
color: var(--color-text);
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: -0.1rem;
|
||||
width: 100%;
|
||||
border-radius: var(--rounded-max);
|
||||
height: 0.2rem;
|
||||
background-color: var(--color-brand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: -0.1rem;
|
||||
width: 100%;
|
||||
border-radius: var(--rounded-max);
|
||||
height: 0.2rem;
|
||||
background-color: var(--color-brand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,77 +1,75 @@
|
||||
<script lang="ts">
|
||||
// TODO: Fix mobile support, currently just cuts off buttons
|
||||
// TODO: Fix mobile support, currently just cuts off buttons
|
||||
|
||||
import IconArrowRight from 'virtual:icons/heroicons-outline/arrow-right';
|
||||
import IconArrowLeft from 'virtual:icons/heroicons-outline/arrow-left';
|
||||
import IconMinus from 'virtual:icons/heroicons-outline/minus';
|
||||
import Button from './Button.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import IconArrowRight from 'virtual:icons/heroicons-outline/arrow-right'
|
||||
import IconArrowLeft from 'virtual:icons/heroicons-outline/arrow-left'
|
||||
import IconMinus from 'virtual:icons/heroicons-outline/minus'
|
||||
import Button from './Button.svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let page: number;
|
||||
export let count: number;
|
||||
export let page: number
|
||||
export let count: number
|
||||
|
||||
$: options =
|
||||
count > 4
|
||||
? page + 3 >= count
|
||||
? [1, '-', count - 4, count - 3, count - 2, count - 1, count]
|
||||
: page > 4
|
||||
? [1, '-', page - 1, page, page + 1, '-', count]
|
||||
: [1, 2, 3, 4, 5, '-', count]
|
||||
: Array.from({ length: count }, (_, i) => i + 1);
|
||||
$: options =
|
||||
count > 4
|
||||
? page + 3 >= count
|
||||
? [1, '-', count - 4, count - 3, count - 2, count - 1, count]
|
||||
: page > 4
|
||||
? [1, '-', page - 1, page, page + 1, '-', count]
|
||||
: [1, 2, 3, 4, 5, '-', count]
|
||||
: Array.from({ length: count }, (_, i) => i + 1)
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
{#if count > 1}
|
||||
<div class="pagination">
|
||||
<Button
|
||||
color="raised"
|
||||
on:click={() => dispatch('change', page - 1)}
|
||||
disabled={page <= 1}
|
||||
title="Last page"
|
||||
><IconArrowLeft height="20px" />
|
||||
</Button>
|
||||
{#each options as option}
|
||||
{#if option === '-'}
|
||||
<IconMinus class="pagination__dash" />
|
||||
{:else}
|
||||
<Button
|
||||
color={option === page ? 'primary' : 'raised'}
|
||||
on:click={() => dispatch('change', option)}>{option}</Button
|
||||
>
|
||||
{/if}
|
||||
{/each}
|
||||
<Button
|
||||
color="raised"
|
||||
on:click={() => dispatch('change', page + 1)}
|
||||
disabled={page >= count}
|
||||
title="Next page"
|
||||
>
|
||||
<IconArrowRight height="20px" />
|
||||
</Button>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<Button
|
||||
color="raised"
|
||||
on:click={() => dispatch('change', page - 1)}
|
||||
disabled={page <= 1}
|
||||
title="Last page"
|
||||
><IconArrowLeft height="20px" />
|
||||
</Button>
|
||||
{#each options as option}
|
||||
{#if option === '-'}
|
||||
<IconMinus class="pagination__dash" />
|
||||
{:else}
|
||||
<Button
|
||||
color={option === page ? 'primary' : 'raised'}
|
||||
on:click={() => dispatch('change', option)}>{option}</Button>
|
||||
{/if}
|
||||
{/each}
|
||||
<Button
|
||||
color="raised"
|
||||
on:click={() => dispatch('change', page + 1)}
|
||||
disabled={page >= count}
|
||||
title="Next page">
|
||||
<IconArrowRight height="20px" />
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
.pagination {
|
||||
align-self: center;
|
||||
display: flex;
|
||||
grid-gap: 0.5rem;
|
||||
align-items: center;
|
||||
.pagination {
|
||||
align-self: center;
|
||||
display: flex;
|
||||
grid-gap: 0.5rem;
|
||||
align-items: center;
|
||||
|
||||
:global(&__dash) {
|
||||
margin: 0 0.5rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
:global(&__dash) {
|
||||
margin: 0 0.5rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
@media (width <= 500px) {
|
||||
grid-gap: 0.25rem;
|
||||
@media (width <= 500px) {
|
||||
grid-gap: 0.25rem;
|
||||
|
||||
:global(> *:nth-child(4)),
|
||||
:global(> *:nth-child(6)) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
:global(> *:nth-child(4)),
|
||||
:global(> *:nth-child(6)) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,204 +1,220 @@
|
||||
<script lang="ts">
|
||||
import IconChevronDown from 'virtual:icons/lucide/chevron-down'
|
||||
import { debounce } from 'throttle-debounce'
|
||||
import { clickOutside } from 'svelte-use-click-outside'
|
||||
import { onMount } from 'svelte'
|
||||
import IconChevronDown from 'virtual:icons/lucide/chevron-down'
|
||||
import { debounce } from 'throttle-debounce'
|
||||
import { clickOutside } from 'svelte-use-click-outside'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
interface Option {
|
||||
label: string;
|
||||
value: string | number;
|
||||
}
|
||||
interface Option {
|
||||
label: string
|
||||
value: string | number
|
||||
}
|
||||
|
||||
export let options: Option[] = []
|
||||
export let value: string | number
|
||||
export let selected: Option = options.find((option) => option.value === (value || ''))
|
||||
export let color = ''
|
||||
export let label = ''
|
||||
export let icon = null
|
||||
export let options: Option[] = []
|
||||
export let value: string | number
|
||||
export let selected: Option = options.find((option) => option.value === (value || ''))
|
||||
export let color = ''
|
||||
export let label = ''
|
||||
export let icon = null
|
||||
|
||||
let open = false
|
||||
let open = false
|
||||
|
||||
$: if (selected) {
|
||||
value = selected.value
|
||||
}
|
||||
$: if (selected) {
|
||||
value = selected.value
|
||||
}
|
||||
|
||||
const minWidth = options
|
||||
.map(it => it.label || it.value)
|
||||
.reduce((it, acc) => String(it).length > acc ? it : acc, '')
|
||||
.length * 9
|
||||
// Returns the width of a string based on the font size and family
|
||||
const getTextWidth = Object.assign(
|
||||
(text: string, font: string) => {
|
||||
if (typeof document !== 'undefined') {
|
||||
const canvas =
|
||||
getTextWidth.canvas || (getTextWidth.canvas = document.createElement('canvas'))
|
||||
const context = canvas.getContext('2d')
|
||||
context.font = font
|
||||
const metrics = context.measureText(text)
|
||||
return metrics.width
|
||||
} else {
|
||||
// Return estimate if SSR
|
||||
return text.length * 7.75
|
||||
}
|
||||
},
|
||||
// Reuses the same canvas object
|
||||
{ canvas: null }
|
||||
)
|
||||
|
||||
let shouldOpenUp = false
|
||||
let element: HTMLElement
|
||||
const minWidth = Math.max(
|
||||
...options.map((it) => getTextWidth(String(it.label || it.value), '16px Inter'))
|
||||
)
|
||||
|
||||
const checkShouldOpenUp = debounce(100, false, () => {
|
||||
if (element) {
|
||||
const bounding = element.getBoundingClientRect()
|
||||
let shouldOpenUp = false
|
||||
let element: HTMLElement
|
||||
|
||||
shouldOpenUp =
|
||||
bounding.bottom + 32 * options.length + 16 >
|
||||
(window.innerHeight || document.documentElement.clientHeight)
|
||||
}
|
||||
})
|
||||
const checkShouldOpenUp = debounce(100, false, () => {
|
||||
if (element) {
|
||||
const bounding = element.getBoundingClientRect()
|
||||
|
||||
onMount(() => {
|
||||
checkShouldOpenUp()
|
||||
window.addEventListener('resize', checkShouldOpenUp)
|
||||
})
|
||||
shouldOpenUp =
|
||||
bounding.bottom + 32 * options.length + 16 >
|
||||
(window.innerHeight || document.documentElement.clientHeight)
|
||||
}
|
||||
})
|
||||
|
||||
function keydown(event: KeyboardEvent) {
|
||||
if ((event.key === ' ' || event.key === 'Enter') && !open) {
|
||||
open = true
|
||||
} else if (event.key === 'ArrowUp') {
|
||||
if (selected) {
|
||||
const index = options.findIndex((option) => option.value === selected.value)
|
||||
if (index > 0) {
|
||||
selected = options[index - 1]
|
||||
}
|
||||
}
|
||||
} else if (event.key === 'ArrowDown') {
|
||||
if (selected) {
|
||||
const index = options.findIndex((option) => option.value === selected.value)
|
||||
if (index < options.length - 1) {
|
||||
selected = options[index + 1]
|
||||
}
|
||||
}
|
||||
} else if ((event.key === 'Escape' || event.key === 'Enter') && open) {
|
||||
open = false
|
||||
}
|
||||
}
|
||||
onMount(() => {
|
||||
checkShouldOpenUp()
|
||||
window.addEventListener('resize', checkShouldOpenUp)
|
||||
})
|
||||
|
||||
function keydown(event: KeyboardEvent) {
|
||||
if ((event.key === ' ' || event.key === 'Enter') && !open) {
|
||||
open = true
|
||||
} else if (event.key === 'ArrowUp') {
|
||||
if (selected) {
|
||||
const index = options.findIndex((option) => option.value === selected.value)
|
||||
if (index > 0) {
|
||||
selected = options[index - 1]
|
||||
}
|
||||
}
|
||||
} else if (event.key === 'ArrowDown') {
|
||||
if (selected) {
|
||||
const index = options.findIndex((option) => option.value === selected.value)
|
||||
if (index < options.length - 1) {
|
||||
selected = options[index + 1]
|
||||
}
|
||||
}
|
||||
} else if ((event.key === 'Escape' || event.key === 'Enter') && open) {
|
||||
open = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="select select--color-{color}"
|
||||
class:is-open={open}
|
||||
class:select--opens-up={shouldOpenUp}
|
||||
use:clickOutside={() => {
|
||||
open = false;
|
||||
class="select select--color-{color}"
|
||||
class:is-open={open}
|
||||
class:select--opens-up={shouldOpenUp}
|
||||
use:clickOutside={() => {
|
||||
open = false
|
||||
}}
|
||||
bind:this={element}
|
||||
tabindex="0"
|
||||
on:keydown={keydown}
|
||||
>
|
||||
<div
|
||||
class="select__input"
|
||||
on:click={() => {
|
||||
open = !open;
|
||||
}}
|
||||
>
|
||||
{#if icon}
|
||||
<svelte:component this={icon}/>
|
||||
{/if}
|
||||
<span class="select__input__value" style:min-width="{minWidth}px">{label || selected?.label || value || 'Choose...'}</span>
|
||||
{#if !icon}
|
||||
<div class="select__input__arrow">
|
||||
<slot name="expandIcon">
|
||||
<IconChevronDown/>
|
||||
</slot>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if open}
|
||||
<ul class="select__options">
|
||||
{#each options as option (option.value)}
|
||||
<li
|
||||
on:click={() => {
|
||||
selected = option;
|
||||
open = false;
|
||||
bind:this={element}
|
||||
tabindex="0"
|
||||
on:keydown={keydown}>
|
||||
<div
|
||||
class="select__input"
|
||||
on:click={() => {
|
||||
open = !open
|
||||
}}>
|
||||
{#if icon}
|
||||
<svelte:component this={icon} />
|
||||
{/if}
|
||||
<span class="select__input__value" style:min-width="{minWidth}px"
|
||||
>{label || selected?.label || value || 'Choose...'}</span>
|
||||
{#if !icon}
|
||||
<div class="select__input__arrow">
|
||||
<slot name="expandIcon">
|
||||
<IconChevronDown />
|
||||
</slot>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if open}
|
||||
<ul class="select__options">
|
||||
{#each options as option (option.value)}
|
||||
<li
|
||||
on:click={() => {
|
||||
selected = option
|
||||
open = false
|
||||
}}
|
||||
class:is-selected={selected?.value === option.value}
|
||||
>
|
||||
{option.label || option.value}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
class:is-selected={selected?.value === option.value}>
|
||||
{option.label || option.value}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.select {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: var(--color-button-text);
|
||||
cursor: pointer;
|
||||
border-radius: var(--rounded);
|
||||
align-self: flex-start;
|
||||
.select {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: var(--color-button-text);
|
||||
cursor: pointer;
|
||||
border-radius: var(--rounded);
|
||||
align-self: flex-start;
|
||||
|
||||
&__input {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.25rem 0.9rem;
|
||||
grid-gap: 0.4rem;
|
||||
background-color: var(--color-button-bg);
|
||||
box-shadow: var(--shadow-inset-sm);
|
||||
border-radius: var(--rounded);
|
||||
}
|
||||
&__input {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.25rem 0.9rem;
|
||||
grid-gap: 0.4rem;
|
||||
background-color: var(--color-button-bg);
|
||||
box-shadow: var(--shadow-inset-sm);
|
||||
border-radius: var(--rounded);
|
||||
}
|
||||
|
||||
&__options {
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
background-color: var(--color-button-bg);
|
||||
border-radius: var(--rounded-bottom);
|
||||
box-shadow: var(--shadow-inset-sm), var(--shadow-floating);
|
||||
overflow: hidden;
|
||||
border-top: 0.1rem solid var(--color-divider);
|
||||
z-index: 5;
|
||||
&__options {
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
background-color: var(--color-button-bg);
|
||||
border-radius: var(--rounded-bottom);
|
||||
box-shadow: var(--shadow-inset-sm), var(--shadow-floating);
|
||||
overflow: hidden;
|
||||
border-top: 0.1rem solid var(--color-divider);
|
||||
z-index: 5;
|
||||
|
||||
li {
|
||||
padding: 0.25rem 1rem;
|
||||
li {
|
||||
padding: 0.25rem 1rem;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-button-bg-hover);
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--color-button-bg-hover);
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
background-color: var(--color-brand-dark);
|
||||
color: var(--color-brand-contrast);
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.is-selected {
|
||||
background-color: var(--color-brand-dark);
|
||||
color: var(--color-brand-contrast);
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-open {
|
||||
z-index: 10;
|
||||
&.is-open {
|
||||
z-index: 10;
|
||||
|
||||
.select__input {
|
||||
border-radius: var(--rounded-top);
|
||||
box-shadow: none;
|
||||
.select__input {
|
||||
border-radius: var(--rounded-top);
|
||||
box-shadow: none;
|
||||
|
||||
&__arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
&__arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--color-raised {
|
||||
> * {
|
||||
background-color: var(--color-raised-bg);
|
||||
}
|
||||
}
|
||||
&--color-raised {
|
||||
> * {
|
||||
background-color: var(--color-raised-bg);
|
||||
}
|
||||
}
|
||||
|
||||
&--opens-up {
|
||||
.select__options {
|
||||
bottom: 100%;
|
||||
top: auto;
|
||||
border-radius: var(--rounded-top);
|
||||
box-shadow: none;
|
||||
border-top: none;
|
||||
border-bottom: 0.1rem solid var(--color-divider);
|
||||
}
|
||||
&--opens-up {
|
||||
.select__options {
|
||||
bottom: 100%;
|
||||
top: auto;
|
||||
border-radius: var(--rounded-top);
|
||||
box-shadow: none;
|
||||
border-top: none;
|
||||
border-bottom: 0.1rem solid var(--color-divider);
|
||||
}
|
||||
|
||||
&.is-open .select__input {
|
||||
border-radius: var(--rounded-bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.is-open .select__input {
|
||||
border-radius: var(--rounded-bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,48 +1,48 @@
|
||||
<script lang="ts">
|
||||
export let value: number;
|
||||
export let min: number;
|
||||
export let max: number;
|
||||
export let id: string = undefined;
|
||||
export let value: number
|
||||
export let min: number
|
||||
export let max: number
|
||||
export let id: string = undefined
|
||||
</script>
|
||||
|
||||
<div class="slider">
|
||||
<input class="slider-input" type="range" name={id} {min} {max} bind:value />
|
||||
<span>{value}</span>
|
||||
<input class="slider-input" type="range" name={id} {min} {max} bind:value />
|
||||
<span>{value}</span>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.slider {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
.slider {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.slider-input {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
border-radius: var(--rounded-sm);
|
||||
box-shadow: var(--shadow-inset-sm);
|
||||
background-color: var(--color-button-bg);
|
||||
border: none;
|
||||
padding: 0.25rem 0;
|
||||
width: 20rem;
|
||||
height: 0.5rem;
|
||||
max-width: 100%;
|
||||
cursor: pointer;
|
||||
.slider-input {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
border-radius: var(--rounded-sm);
|
||||
box-shadow: var(--shadow-inset-sm);
|
||||
background-color: var(--color-button-bg);
|
||||
border: none;
|
||||
padding: 0.25rem 0;
|
||||
width: 20rem;
|
||||
height: 0.5rem;
|
||||
max-width: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
cursor: ew-resize;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 0.5rem;
|
||||
height: 1.25rem;
|
||||
border-radius: var(--rounded-sm);
|
||||
background-color: var(--color-brand);
|
||||
&::-webkit-slider-thumb {
|
||||
cursor: ew-resize;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 0.5rem;
|
||||
height: 1.25rem;
|
||||
border-radius: var(--rounded-sm);
|
||||
background-color: var(--color-brand);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-brand-dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--color-brand-dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,56 +1,56 @@
|
||||
<script lang="ts">
|
||||
import type { SvelteComponent } from 'svelte';
|
||||
import type { SvelteComponent } from 'svelte'
|
||||
|
||||
export let placeholder = '';
|
||||
export let icon: SvelteComponent = undefined;
|
||||
export let value = '';
|
||||
export let multiline = false;
|
||||
export let id: string = undefined;
|
||||
export let placeholder = ''
|
||||
export let icon: SvelteComponent = undefined
|
||||
export let value = ''
|
||||
export let multiline = false
|
||||
export let id: string = undefined
|
||||
</script>
|
||||
|
||||
<div class="text-input">
|
||||
{#if multiline}
|
||||
<textarea name={id} {placeholder} bind:value />
|
||||
{:else}
|
||||
<input type="text" name={id} {placeholder} bind:value class:has-icon={icon} />
|
||||
{#if icon}
|
||||
<svelte:component this={icon} />
|
||||
{/if}
|
||||
{/if}
|
||||
{#if multiline}
|
||||
<textarea name={id} {placeholder} bind:value />
|
||||
{:else}
|
||||
<input type="text" name={id} {placeholder} bind:value class:has-icon={icon} />
|
||||
{#if icon}
|
||||
<svelte:component this={icon} />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.text-input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
position: relative;
|
||||
.text-input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
position: relative;
|
||||
|
||||
input,
|
||||
textarea {
|
||||
border-radius: var(--rounded-sm);
|
||||
box-shadow: var(--shadow-inset-sm);
|
||||
background-color: var(--color-button-bg);
|
||||
border: none;
|
||||
padding: 6px 14px;
|
||||
width: 20rem;
|
||||
max-width: 100%;
|
||||
}
|
||||
input,
|
||||
textarea {
|
||||
border-radius: var(--rounded-sm);
|
||||
box-shadow: var(--shadow-inset-sm);
|
||||
background-color: var(--color-button-bg);
|
||||
border: none;
|
||||
padding: 6px 14px;
|
||||
width: 20rem;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 2.5rem;
|
||||
}
|
||||
textarea {
|
||||
min-height: 2.5rem;
|
||||
}
|
||||
|
||||
:global(.icon) {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
left: 14px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
:global(.icon) {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
left: 14px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
input.has-icon {
|
||||
padding-left: 40px;
|
||||
}
|
||||
}
|
||||
input.has-icon {
|
||||
padding-left: 40px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -43,7 +43,15 @@ export async function tags(API_URL) {
|
||||
// Write JSON file
|
||||
await fs.writeFile(
|
||||
'./generated/tags.json',
|
||||
JSON.stringify({ categories, loaders, projectTypes, licenses, donationPlatforms, reportTypes, tagIcons })
|
||||
JSON.stringify({
|
||||
categories,
|
||||
loaders,
|
||||
projectTypes,
|
||||
licenses,
|
||||
donationPlatforms,
|
||||
reportTypes,
|
||||
tagIcons,
|
||||
})
|
||||
)
|
||||
progressBar.increment()
|
||||
|
||||
|
||||
@ -1,63 +1,63 @@
|
||||
<script lang="ts">
|
||||
import '$package/styles.postcss';
|
||||
import '../docs/styles/prism-one-dark.css';
|
||||
import '../docs/styles/gh-markdown.postcss';
|
||||
import Sidebar from '../docs/components/Sidebar.svelte';
|
||||
import Header from '../docs/components/Header.svelte';
|
||||
import '$package/styles.postcss'
|
||||
import '../docs/styles/prism-one-dark.css'
|
||||
import '../docs/styles/gh-markdown.postcss'
|
||||
import Sidebar from '../docs/components/Sidebar.svelte'
|
||||
import Header from '../docs/components/Header.svelte'
|
||||
</script>
|
||||
|
||||
<div class="app theme-light">
|
||||
<Header />
|
||||
<Sidebar />
|
||||
<main class="app__content">
|
||||
<article>
|
||||
<slot />
|
||||
</article>
|
||||
</main>
|
||||
<Header />
|
||||
<Sidebar />
|
||||
<main class="app__content">
|
||||
<article>
|
||||
<slot />
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
:global {
|
||||
html {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
:global {
|
||||
html {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-size: var(--font-size);
|
||||
font-family: var(--body-font);
|
||||
body {
|
||||
margin: 0;
|
||||
font-size: var(--font-size);
|
||||
font-family: var(--body-font);
|
||||
|
||||
--accent-color: hsl(331, 80%, 45%);
|
||||
--accent-color-transparent: hsla(331, 80%, 45%, 0.15);
|
||||
}
|
||||
}
|
||||
--accent-color: hsl(331, 80%, 45%);
|
||||
--accent-color-transparent: hsla(331, 80%, 45%, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
.app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
overflow: hidden;
|
||||
background-color: var(--color-bg);
|
||||
.app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
overflow: hidden;
|
||||
background-color: var(--color-bg);
|
||||
|
||||
--sidebar-width: 275px;
|
||||
--sidebar-width: 275px;
|
||||
|
||||
&__content {
|
||||
@media (--md) {
|
||||
padding-left: var(--sidebar-width);
|
||||
}
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
&__content {
|
||||
@media (--md) {
|
||||
padding-left: var(--sidebar-width);
|
||||
}
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
article {
|
||||
max-width: 800px;
|
||||
padding-block: 140px 64px;
|
||||
padding-inline: 24px;
|
||||
article {
|
||||
max-width: 800px;
|
||||
padding-block: 140px 64px;
|
||||
padding-inline: 24px;
|
||||
|
||||
@media (--sm) {
|
||||
padding-inline: 48px;
|
||||
padding-block: 140px 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (--sm) {
|
||||
padding-inline: 48px;
|
||||
padding-block: 140px 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
```svelte example raised
|
||||
<script>
|
||||
import { Button } from 'omorphia'
|
||||
import IconHeartSolid from 'virtual:icons/heroicons-solid/heart'
|
||||
import IconCalendar from 'virtual:icons/lucide/calendar'
|
||||
import { Button } from 'omorphia'
|
||||
import IconHeartSolid from 'virtual:icons/heroicons-solid/heart'
|
||||
import IconCalendar from 'virtual:icons/lucide/calendar'
|
||||
</script>
|
||||
|
||||
<div class="actions">
|
||||
<Button><IconHeartSolid /> Unfollow </Button>
|
||||
<span class="stat">
|
||||
<IconCalendar/>
|
||||
Updated 12 days ago
|
||||
</span>
|
||||
<Button><IconHeartSolid /> Unfollow</Button>
|
||||
<span class="stat">
|
||||
<IconCalendar />
|
||||
Updated 12 days ago
|
||||
</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
Base should be applied to a "root" element, like `<body>`, to provide base styles for common things like text. The theme mode, `light-theme`, `dark-theme`, or `oled-theme`, should also be added to this element.
|
||||
|
||||
```svelte example
|
||||
<div class="base theme-light">
|
||||
...
|
||||
</div>
|
||||
<div class="base theme-light">...</div>
|
||||
```
|
||||
|
||||
@ -2,11 +2,13 @@
|
||||
|
||||
```svelte example
|
||||
<div class="card">
|
||||
<h3>Moon/Distance to Earth</h3>
|
||||
<h2>238,900 mi</h2>
|
||||
<p>
|
||||
The moon's distance from Earth affects the strength of ocean tides and the appearance of solar eclipses in our skies. The average distance between the blue planet and its only natural satellite is about 238,855 miles (384,400 kilometers), according to NASA.
|
||||
</p>
|
||||
<h3>Moon/Distance to Earth</h3>
|
||||
<h2>238,900 mi</h2>
|
||||
<p>
|
||||
The moon's distance from Earth affects the strength of ocean tides and the appearance of solar
|
||||
eclipses in our skies. The average distance between the blue planet and its only natural
|
||||
satellite is about 238,855 miles (384,400 kilometers), according to NASA.
|
||||
</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -14,18 +16,18 @@
|
||||
|
||||
```svelte example
|
||||
<script lang="ts">
|
||||
import { Button } from "omorphia";
|
||||
import IconPencil from 'virtual:icons/heroicons-outline/pencil'
|
||||
import { Avatar } from "omorphia";
|
||||
import { Button } from 'omorphia'
|
||||
import IconPencil from 'virtual:icons/heroicons-outline/pencil'
|
||||
import { Avatar } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<div class="card">
|
||||
<div class="card__overlay">
|
||||
<Button color="raised"><IconPencil /> Edit</Button>
|
||||
</div>
|
||||
<div class="card__banner card__banner--short card__banner--dark" ></div>
|
||||
<Avatar size="md" floatUp/>
|
||||
<h1 class="title">Project</h1>
|
||||
<p class="summary">A project that has a description right here.</p>
|
||||
<div class="card__overlay">
|
||||
<Button color="raised"><IconPencil /> Edit</Button>
|
||||
</div>
|
||||
<div class="card__banner card__banner--short card__banner--dark" />
|
||||
<Avatar size="md" floatUp />
|
||||
<h1 class="title">Project</h1>
|
||||
<p class="summary">A project that has a description right here.</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -6,8 +6,8 @@ Some words could go here.
|
||||
And some other words could go here.
|
||||
|
||||
<style>
|
||||
.example__source__code {
|
||||
flex-direction: column;
|
||||
}
|
||||
.example__source__code {
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
```svelte example raised
|
||||
<div class="info-table">
|
||||
<span class="info-table__label">License</span>
|
||||
<a href="#mit" class="link">MIT</a>
|
||||
<span class="info-table__label">Project ID</span>
|
||||
<span>11223344</span>
|
||||
<span class="info-table__label">Visibilty</span>
|
||||
<span>Approved</span>
|
||||
</div>
|
||||
<div class="info-table">
|
||||
<span class="info-table__label">License</span>
|
||||
<a href="#mit" class="link">MIT</a>
|
||||
<span class="info-table__label">Project ID</span>
|
||||
<span>11223344</span>
|
||||
<span class="info-table__label">Visibilty</span>
|
||||
<span>Approved</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -8,15 +8,15 @@
|
||||
|
||||
```svelte example raised
|
||||
<script>
|
||||
import IconIssues from 'virtual:icons/heroicons-outline/exclamation'
|
||||
import IconCode from 'virtual:icons/heroicons-outline/code'
|
||||
import IconClock from 'virtual:icons/lucide/flag-triangle-right'
|
||||
import IconWiki from 'virtual:icons/heroicons-outline/book-open'
|
||||
import IconIssues from 'virtual:icons/heroicons-outline/exclamation'
|
||||
import IconCode from 'virtual:icons/heroicons-outline/code'
|
||||
import IconClock from 'virtual:icons/lucide/flag-triangle-right'
|
||||
import IconWiki from 'virtual:icons/heroicons-outline/book-open'
|
||||
</script>
|
||||
|
||||
<div class="link-group">
|
||||
<a class="link" href="#issues"><IconIssues /> Issues</a>
|
||||
<a class="link" href="#source"><IconCode /> Source</a>
|
||||
<a class="link" href="#wiki"><IconWiki /> Wiki</a>
|
||||
<a class="link" href="#issues"><IconIssues /> Issues</a>
|
||||
<a class="link" href="#source"><IconCode /> Source</a>
|
||||
<a class="link" href="#wiki"><IconWiki /> Wiki</a>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Avatar } from "omorphia";
|
||||
import { Avatar } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<a class="member" href="#user">
|
||||
<Avatar src="https://avatars1.githubusercontent.com/u/6166773" size="sm" circle/>
|
||||
<div class="member__info">
|
||||
<span class="member__info__link">Prospector</span>
|
||||
<span>Owner</span>
|
||||
</div>
|
||||
<Avatar src="https://avatars1.githubusercontent.com/u/6166773" size="sm" circle />
|
||||
<div class="member__info">
|
||||
<span class="member__info__link">Prospector</span>
|
||||
<span>Owner</span>
|
||||
</div>
|
||||
</a>
|
||||
```
|
||||
|
||||
@ -2,12 +2,12 @@
|
||||
|
||||
```svelte example raised
|
||||
<script>
|
||||
import IconStar from 'virtual:icons/heroicons-outline/star'
|
||||
import IconStar from 'virtual:icons/heroicons-outline/star'
|
||||
</script>
|
||||
|
||||
<div class="stat">
|
||||
<IconStar/>
|
||||
123K stars
|
||||
<IconStar />
|
||||
123K stars
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -15,18 +15,18 @@
|
||||
|
||||
```svelte example raised
|
||||
<script>
|
||||
import IconDownload from 'virtual:icons/heroicons-outline/download'
|
||||
import IconHeart from 'virtual:icons/heroicons-outline/heart'
|
||||
import IconDownload from 'virtual:icons/heroicons-outline/download'
|
||||
import IconHeart from 'virtual:icons/heroicons-outline/heart'
|
||||
</script>
|
||||
|
||||
<div class="stat-group">
|
||||
<div class="stat">
|
||||
<IconDownload/>
|
||||
4.1B downloads
|
||||
</div>
|
||||
<div class="stat stat--light">
|
||||
<IconHeart/>
|
||||
3 followers
|
||||
</div>
|
||||
<div class="stat">
|
||||
<IconDownload />
|
||||
4.1B downloads
|
||||
</div>
|
||||
<div class="stat stat--light">
|
||||
<IconHeart />
|
||||
3 followers
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
```svelte example raised
|
||||
<script>
|
||||
import IconCarrot from 'virtual:icons/lucide/carrot'
|
||||
import IconGlobe from 'virtual:icons/heroicons-outline/globe'
|
||||
import IconCarrot from 'virtual:icons/lucide/carrot'
|
||||
import IconGlobe from 'virtual:icons/heroicons-outline/globe'
|
||||
</script>
|
||||
|
||||
<div class="tag-group">
|
||||
<div class="tag">
|
||||
<IconCarrot/> Food
|
||||
</div>
|
||||
<div class="tag">
|
||||
<IconGlobe/> World generation
|
||||
</div>
|
||||
<div class="tag">
|
||||
<IconCarrot /> Food
|
||||
</div>
|
||||
<div class="tag">
|
||||
<IconGlobe /> World generation
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -2,12 +2,14 @@ Avatars are used for project icons and user profile pictures. Low resolution ima
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Avatar } from "omorphia";
|
||||
import { Avatar } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<Avatar size="lg" circle src="https://avatars3.githubusercontent.com/u/44736536?v=4" />
|
||||
<Avatar size="md" src="https://cdn.modrinth.com/data/AANobbMI/icon.png" />
|
||||
<Avatar size="md" src="https://staging-cdn.modrinth.com/data/d1SqMrzw/9a39b0c80a49976b0c04053682708374e18105fe.png" />
|
||||
<Avatar
|
||||
size="md"
|
||||
src="https://staging-cdn.modrinth.com/data/d1SqMrzw/9a39b0c80a49976b0c04053682708374e18105fe.png" />
|
||||
<Avatar size="sm" />
|
||||
<Avatar size="xs" circle src="https://avatars1.githubusercontent.com/u/6166773?v=4" />
|
||||
```
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Badge } from "omorphia";
|
||||
import { Badge } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<Badge color="red" label="Tomato" />
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
|
||||
```svelte example
|
||||
<script lang="ts">
|
||||
import { Button } from "omorphia";
|
||||
import IconDownload from 'virtual:icons/heroicons-outline/download'
|
||||
import { Button } from 'omorphia'
|
||||
import IconDownload from 'virtual:icons/heroicons-outline/download'
|
||||
</script>
|
||||
|
||||
<Button color="raised"><IconDownload /> Download</Button>
|
||||
@ -13,21 +13,21 @@
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Button } from "omorphia";
|
||||
import IconDownload from 'virtual:icons/heroicons-outline/download'
|
||||
import { Button } from 'omorphia'
|
||||
import IconDownload from 'virtual:icons/heroicons-outline/download'
|
||||
</script>
|
||||
|
||||
<div class="button-group">
|
||||
<Button>Default</Button>
|
||||
<Button color="raised">Raised</Button>
|
||||
<Button color="primary">Primary</Button>
|
||||
<Button color="primary-light">Light primary</Button>
|
||||
<Button color="secondary">Secondary</Button>
|
||||
<Button color="tertiary">Tertiary</Button>
|
||||
<Button color="danger">Danger</Button>
|
||||
<Button color="danger-light">Light danger</Button>
|
||||
<Button color="transparent">Transparent</Button>
|
||||
<Button disabled>Disabled</Button>
|
||||
<Button>Default</Button>
|
||||
<Button color="raised">Raised</Button>
|
||||
<Button color="primary">Primary</Button>
|
||||
<Button color="primary-light">Light primary</Button>
|
||||
<Button color="secondary">Secondary</Button>
|
||||
<Button color="tertiary">Tertiary</Button>
|
||||
<Button color="danger">Danger</Button>
|
||||
<Button color="danger-light">Light danger</Button>
|
||||
<Button color="transparent">Transparent</Button>
|
||||
<Button disabled>Disabled</Button>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -35,13 +35,13 @@
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Button } from "omorphia";
|
||||
import IconDownload from 'virtual:icons/heroicons-outline/download'
|
||||
import IconHeart from 'virtual:icons/heroicons-outline/heart'
|
||||
import { Button } from 'omorphia'
|
||||
import IconDownload from 'virtual:icons/heroicons-outline/download'
|
||||
import IconHeart from 'virtual:icons/heroicons-outline/heart'
|
||||
</script>
|
||||
|
||||
<div class="button-group">
|
||||
<Button color="primary"><IconDownload /></Button>
|
||||
<Button><IconHeart /> Follow mod </Button>
|
||||
<Button color="primary"><IconDownload /></Button>
|
||||
<Button><IconHeart /> Follow mod</Button>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Checkbox } from "omorphia";
|
||||
import { Checkbox } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<Checkbox>Extra components</Checkbox>
|
||||
@ -12,9 +12,9 @@
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Checkbox } from "omorphia";
|
||||
import IconCarrot from 'virtual:icons/lucide/carrot'
|
||||
import { Checkbox } from 'omorphia'
|
||||
import IconCarrot from 'virtual:icons/lucide/carrot'
|
||||
</script>
|
||||
|
||||
<Checkbox><IconCarrot /> Food </Checkbox>
|
||||
<Checkbox><IconCarrot /> Food</Checkbox>
|
||||
```
|
||||
|
||||
@ -1,37 +1,36 @@
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { CheckboxList } from "omorphia";
|
||||
import IconSquare from 'virtual:icons/lucide/square'
|
||||
import IconCircle from 'virtual:icons/lucide/circle'
|
||||
import IconTriangle from 'virtual:icons/lucide/triangle'
|
||||
import { CheckboxList } from 'omorphia'
|
||||
import IconSquare from 'virtual:icons/lucide/square'
|
||||
import IconCircle from 'virtual:icons/lucide/circle'
|
||||
import IconTriangle from 'virtual:icons/lucide/triangle'
|
||||
|
||||
let selected = []
|
||||
let selected = []
|
||||
</script>
|
||||
|
||||
<CheckboxList
|
||||
bind:value={selected}
|
||||
options={[
|
||||
{
|
||||
label: 'Circle',
|
||||
icon: IconCircle,
|
||||
value: 'CIR',
|
||||
},
|
||||
{
|
||||
label: 'Triangle',
|
||||
icon: IconTriangle,
|
||||
value: 'TRI',
|
||||
},
|
||||
{
|
||||
label: 'Square',
|
||||
icon: IconSquare,
|
||||
value: 'SQU',
|
||||
},
|
||||
{
|
||||
label: 'Blank',
|
||||
value: 'BLA',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
bind:value={selected}
|
||||
options={[
|
||||
{
|
||||
label: 'Circle',
|
||||
icon: IconCircle,
|
||||
value: 'CIR',
|
||||
},
|
||||
{
|
||||
label: 'Triangle',
|
||||
icon: IconTriangle,
|
||||
value: 'TRI',
|
||||
},
|
||||
{
|
||||
label: 'Square',
|
||||
icon: IconSquare,
|
||||
value: 'SQU',
|
||||
},
|
||||
{
|
||||
label: 'Blank',
|
||||
value: 'BLA',
|
||||
},
|
||||
]} />
|
||||
|
||||
Selected: {selected}
|
||||
```
|
||||
|
||||
@ -1,23 +1,21 @@
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { CheckboxVirtualList } from "omorphia";
|
||||
import IconStar from 'virtual:icons/heroicons-outline/star'
|
||||
import { uniqueId } from 'omorphia/utils/uniqueId'
|
||||
import { CheckboxVirtualList } from 'omorphia'
|
||||
import IconStar from 'virtual:icons/heroicons-outline/star'
|
||||
import { uniqueId } from 'omorphia/utils/uniqueId'
|
||||
|
||||
let options = Array(100).fill({})
|
||||
.map(option => ({
|
||||
label: 'Star-' + uniqueId(),
|
||||
icon: IconStar,
|
||||
value: uniqueId(),
|
||||
}))
|
||||
let options = Array(100)
|
||||
.fill({})
|
||||
.map((option) => ({
|
||||
label: 'Star-' + uniqueId(),
|
||||
icon: IconStar,
|
||||
value: uniqueId(),
|
||||
}))
|
||||
|
||||
let selected = ['2', '6']
|
||||
let selected = ['2', '6']
|
||||
</script>
|
||||
|
||||
<CheckboxVirtualList
|
||||
bind:value={selected}
|
||||
{options}
|
||||
/>
|
||||
<CheckboxVirtualList bind:value={selected} {options} />
|
||||
|
||||
Selected: {selected}
|
||||
```
|
||||
|
||||
@ -2,42 +2,46 @@
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Chips } from "omorphia";
|
||||
import { Chips } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<Chips options={[
|
||||
{
|
||||
label: 'One',
|
||||
value: 'one'
|
||||
},
|
||||
{
|
||||
label: 'Two',
|
||||
value: 'two'
|
||||
}]}
|
||||
/>
|
||||
<Chips
|
||||
options={[
|
||||
{
|
||||
label: 'One',
|
||||
value: 'one',
|
||||
},
|
||||
{
|
||||
label: 'Two',
|
||||
value: 'two',
|
||||
},
|
||||
]} />
|
||||
```
|
||||
|
||||
### Force an option to be selected with `neverEmpty`
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Chips } from "omorphia";
|
||||
import { Chips } from 'omorphia'
|
||||
|
||||
let foo = 'modpack'
|
||||
let foo = 'modpack'
|
||||
</script>
|
||||
|
||||
<Chips neverEmpty bind:value={foo} options={[
|
||||
{
|
||||
label: 'Mod',
|
||||
value: 'mod'
|
||||
},
|
||||
{
|
||||
label: 'Modpack',
|
||||
value: 'modpack'
|
||||
},
|
||||
{
|
||||
label: 'World',
|
||||
value: 'world'
|
||||
}]}
|
||||
/>
|
||||
<Chips
|
||||
neverEmpty
|
||||
bind:value={foo}
|
||||
options={[
|
||||
{
|
||||
label: 'Mod',
|
||||
value: 'mod',
|
||||
},
|
||||
{
|
||||
label: 'Modpack',
|
||||
value: 'modpack',
|
||||
},
|
||||
{
|
||||
label: 'World',
|
||||
value: 'world',
|
||||
},
|
||||
]} />
|
||||
```
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { FormField } from "omorphia";
|
||||
import { Slider } from "omorphia";
|
||||
import { TextInput } from "omorphia";
|
||||
import { FormField } from 'omorphia'
|
||||
import { Slider } from 'omorphia'
|
||||
import { TextInput } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<FormField label="Favorite number">
|
||||
<Slider min=0 max=100 value=69 />
|
||||
<Slider min="0" max="100" value="69" />
|
||||
</FormField>
|
||||
<FormField label="Favorite color">
|
||||
<TextInput placeholder="Enter another color..." />
|
||||
<TextInput placeholder="Enter another color..." />
|
||||
</FormField>
|
||||
```
|
||||
|
||||
@ -2,25 +2,25 @@
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { NavRow } from "omorphia";
|
||||
import { NavRow } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<NavRow
|
||||
level={1}
|
||||
links={[
|
||||
{
|
||||
href: '/Button',
|
||||
label: 'Button'
|
||||
},
|
||||
{
|
||||
href: '/Chips',
|
||||
label: 'Chips'
|
||||
},
|
||||
{
|
||||
href: '/NavRow',
|
||||
label: 'NavRow'
|
||||
}
|
||||
]}>
|
||||
Click for fun
|
||||
level={1}
|
||||
links={[
|
||||
{
|
||||
href: '/Button',
|
||||
label: 'Button',
|
||||
},
|
||||
{
|
||||
href: '/Chips',
|
||||
label: 'Chips',
|
||||
},
|
||||
{
|
||||
href: '/NavRow',
|
||||
label: 'NavRow',
|
||||
},
|
||||
]}>
|
||||
Click for fun
|
||||
</NavRow>
|
||||
```
|
||||
|
||||
@ -2,7 +2,7 @@ Use pagination to show a set of page numbers and navigation directions to move t
|
||||
|
||||
```svelte example
|
||||
<script lang="ts">
|
||||
import { Pagination } from "omorphia"
|
||||
import { Pagination } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<Pagination page={20} count={50} />
|
||||
|
||||
@ -1,19 +1,17 @@
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Select } from "omorphia";
|
||||
import { Select } from 'omorphia'
|
||||
|
||||
let sortMethod = "downloads"
|
||||
let sortMethod = 'downloads'
|
||||
</script>
|
||||
|
||||
<Select
|
||||
color="raised"
|
||||
options={[
|
||||
{ value: "", label: "Relevance" },
|
||||
{ value: "downloads", label: "Downloads" },
|
||||
{ value: "follows", label: "Followers" },
|
||||
{ value: "newest", label: "Recently created" },
|
||||
{ value: "updated", label: "Recently updated" },
|
||||
]}
|
||||
bind:value={sortMethod}
|
||||
/>
|
||||
options={[
|
||||
{ value: '', label: 'Relevance' },
|
||||
{ value: 'downloads', label: 'Downloads' },
|
||||
{ value: 'follows', label: 'Followers' },
|
||||
{ value: 'newest', label: 'Recently' },
|
||||
{ value: 'updated', label: 'Recently updated really fast whoot' },
|
||||
]}
|
||||
bind:value={sortMethod} />
|
||||
```
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Slider } from "omorphia";
|
||||
import { Slider } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<Slider min=0 max=10 value=4 />
|
||||
<Slider min="0" max="10" value="4" />
|
||||
```
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { TextInput } from "omorphia";
|
||||
import IconSearch from 'virtual:icons/heroicons-outline/search'
|
||||
import { TextInput } from 'omorphia'
|
||||
import IconSearch from 'virtual:icons/heroicons-outline/search'
|
||||
</script>
|
||||
|
||||
<TextInput placeholder="Enter another color..." />
|
||||
|
||||
@ -20,8 +20,8 @@ Then use the icon as if it were a Svelte component:
|
||||
|
||||
```svelte example
|
||||
<script lang="ts">
|
||||
import IconHeart from 'virtual:icons/heroicons-outline/heart'
|
||||
import IconHeart from 'virtual:icons/heroicons-outline/heart'
|
||||
</script>
|
||||
|
||||
<p> That's lovely <IconHeart height="14px" />! </p>
|
||||
<p>That's lovely <IconHeart height="14px" />!</p>
|
||||
```
|
||||
|
||||
@ -14,7 +14,7 @@ Import the SVG in the `<script>` of your svelte file, and treat the illustration
|
||||
|
||||
```svelte
|
||||
<script>
|
||||
import NoData from '$assets/images/illustrations/undraw_no_data.svg'
|
||||
import NoData from '$assets/images/illustrations/undraw_no_data.svg'
|
||||
</script>
|
||||
|
||||
<NoData />
|
||||
|
||||
@ -14,16 +14,17 @@ The `markdown` parser is designed for bodies of markdown text and supports image
|
||||
|
||||
```svelte example
|
||||
<script lang="ts">
|
||||
import { markdown } from "omorphia/utils"
|
||||
import { markdown } from 'omorphia/utils'
|
||||
|
||||
const source = '## Example markdown \n\
|
||||
const source =
|
||||
'## Example markdown \n\
|
||||
This is **some** *text*! \n\
|
||||
#### An image \n\
|
||||
<img src="https://cdn.modrinth.com/data/YL57xq9U/images/d382106b9a2b943d06107c31c139c77849f1a0e8.png" />'
|
||||
</script>
|
||||
|
||||
<div class="card markdown">
|
||||
{@html markdown(source)}
|
||||
{@html markdown(source)}
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -33,9 +34,9 @@ The `markdownInline` parser is perfect for translations and short bios. It doesn
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { markdownInline } from "omorphia/utils"
|
||||
import { markdownInline } from 'omorphia/utils'
|
||||
|
||||
const source = "This is some **bolded** and *italicized* text."
|
||||
const source = 'This is some **bolded** and *italicized* text.'
|
||||
</script>
|
||||
|
||||
<p>{@html markdownInline(source)}</p>
|
||||
@ -45,7 +46,7 @@ The `markdownInline` parser is perfect for translations and short bios. It doesn
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { ago } from 'omorphia/utils';
|
||||
import { ago } from 'omorphia/utils'
|
||||
</script>
|
||||
|
||||
<p>Something happened {ago(Date.now())}.</p>
|
||||
@ -60,19 +61,19 @@ The `Permissions` class provides an easy way to manage user permissions.
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Permissions } from 'omorphia/utils'
|
||||
import { Permissions } from 'omorphia/utils'
|
||||
|
||||
const permissions = new Permissions(128) // Can be integer or 'ALL'
|
||||
const permissions = new Permissions(128) // Can be integer or 'ALL'
|
||||
</script>
|
||||
|
||||
<p>
|
||||
<input type="checkbox" bind:checked={permissions.uploadVersions} id="ex-1"/>
|
||||
<label for="ex-1">Can edit versions</label><br>
|
||||
<input type="checkbox" bind:checked={permissions.deleteProject} id="ex-2"/>
|
||||
<label for="ex-2">Can delete project</label><br><br>
|
||||
<input type="checkbox" bind:checked={permissions.uploadVersions} id="ex-1" />
|
||||
<label for="ex-1">Can edit versions</label><br />
|
||||
<input type="checkbox" bind:checked={permissions.deleteProject} id="ex-2" />
|
||||
<label for="ex-2">Can delete project</label><br /><br />
|
||||
|
||||
Integer: {permissions.toInteger()}<br>
|
||||
Can access settings page: {permissions.settingsPage}
|
||||
Integer: {permissions.toInteger()}<br />
|
||||
Can access settings page: {permissions.settingsPage}
|
||||
</p>
|
||||
```
|
||||
|
||||
@ -82,8 +83,8 @@ The `formatVersions` function provides an easy way to parse a project's versions
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { formatVersions } from 'omorphia/utils';
|
||||
import { formatVersions } from 'omorphia/utils'
|
||||
</script>
|
||||
|
||||
<p>{formatVersions(["1.18", "1.18.1", "1.18.2", "1.17.1"])}</p>
|
||||
<p>{formatVersions(['1.18', '1.18.1', '1.18.2', '1.17.1'])}</p>
|
||||
```
|
||||
|
||||
@ -22,7 +22,7 @@ Use a component by importing from `omorphia`. For example, use the [Button compo
|
||||
|
||||
```svelte example raised
|
||||
<script lang="ts">
|
||||
import { Button } from "omorphia"
|
||||
import { Button } from 'omorphia'
|
||||
</script>
|
||||
|
||||
<Button color="primary">I'm a button!</Button>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user