diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index fc2ec1e..49a3607 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -6,20 +6,19 @@ jobs:
steps:
- uses: actions/checkout@v3
- - name: Set Node Version to 18
+ - name: Set Node Version to 22
uses: actions/setup-node@v2
with:
- node-version: '18'
+ node-version: '22'
+
+ - name: Enable Corepack
+ run: corepack enable
- name: Install Dependencies
- uses: borales/actions-yarn@v4
- with:
- cmd: install
+ run: yarn install
- - name: Build Production Bundle
- uses: borales/actions-yarn@v4
- with:
- cmd: build
+ - name: Build
+ run: yarn build
- name: Push to Build Branch
if: github.ref == 'refs/heads/main'
@@ -30,3 +29,6 @@ jobs:
FOLDER: build # The directory where your assets are generated
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # GitHub will automatically add this - you don't need to bother getting a token
MESSAGE: 'Build: ({sha}) {msg}' # The commit message
+ # Env Secrets
+ PUBLIC_ALGOLIA_ID: ${{ secrets.PUBLIC_ALGOLIA_ID }}
+ PUBLIC_ALGOLIA_SEARCH_KEY: ${{ secrets.PUBLIC_ALGOLIA_SEARCH_KEY }}
diff --git a/.prettierrc b/.prettierrc
index da7ed34..71a51b6 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,9 +1,41 @@
{
+ "$schema": "http://json.schemastore.org/prettierrc",
+ "tabWidth": 4,
"useTabs": true,
+ "semi": false,
"singleQuote": true,
- "trailingComma": "none",
+ "arrowParens": "avoid",
"printWidth": 100,
- "plugins": ["prettier-plugin-svelte"],
- "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }],
- "semi": false
+ "trailingComma": "es5",
+ "bracketSameLine": false,
+ "endOfLine": "auto",
+ "overrides": [
+ {
+ "files": ["**/*.yml", "**/*.yaml"],
+ "options": {
+ "parser": "yaml",
+ "tabWidth": 2,
+ "useTabs": false
+ }
+ },
+ {
+ "files": "**/*.ts",
+ "options": {
+ "parser": "typescript"
+ }
+ },
+ {
+ "files": "**/*.svelte",
+ "options": {
+ "parser": "svelte",
+ "plugins": ["prettier-plugin-svelte"]
+ }
+ },
+ {
+ "files": "**/*.svg",
+ "options": {
+ "parser": "html"
+ }
+ }
+ ]
}
diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz
new file mode 100644
index 0000000..6fd7298
Binary files /dev/null and b/.yarn/install-state.gz differ
diff --git a/.yarnrc.yml b/.yarnrc.yml
new file mode 100644
index 0000000..3186f3f
--- /dev/null
+++ b/.yarnrc.yml
@@ -0,0 +1 @@
+nodeLinker: node-modules
diff --git a/eslint.config.js b/eslint.config.js
deleted file mode 100644
index 5a7eb2c..0000000
--- a/eslint.config.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import js from '@eslint/js'
-import ts from 'typescript-eslint'
-import svelte from 'eslint-plugin-svelte'
-import prettier from 'eslint-config-prettier'
-import globals from 'globals'
-
-/** @type {import('eslint').Linter.FlatConfig[]} */
-export default [
- js.configs.recommended,
- ...ts.configs.recommended,
- ...svelte.configs['flat/recommended'],
- prettier,
- ...svelte.configs['flat/prettier'],
- {
- languageOptions: {
- globals: {
- ...globals.browser,
- ...globals.node
- }
- }
- },
- {
- files: ['**/*.svelte'],
- languageOptions: {
- parserOptions: {
- parser: ts.parser
- }
- }
- },
- {
- ignores: ['build/', '.svelte-kit/', 'dist/']
- }
-]
diff --git a/eslint.config.ts b/eslint.config.ts
new file mode 100644
index 0000000..a0a29b1
--- /dev/null
+++ b/eslint.config.ts
@@ -0,0 +1,266 @@
+import svelteEslint from 'eslint-plugin-svelte'
+import svelteParser from 'svelte-eslint-parser'
+import tsESLint, { type ConfigWithExtends } from 'typescript-eslint'
+import svelteConfig from './svelte.config'
+import type { NamingConventionRule } from './tslintNamingConventionRule'
+
+console.log(`[${new Date().toLocaleTimeString()}] Loading ESLint config`)
+
+const IGNORE_PATTERNS = [
+ '.DS_Store',
+ '.env',
+ '.env.*',
+ '.github',
+ '.vscode',
+ '**/node_modules/**',
+
+ // Blockbench Plugin Template
+ 'dist/**/*',
+
+ // Ignore files for PNPM, NPM and YARN
+ 'pnpm-lock.yaml',
+ 'package-lock.json',
+ 'yarn.lock'
+]
+
+const CUSTOM_RULES: ConfigWithExtends['rules'] = {
+ // ESLint
+ semi: ['error', 'never'],
+ 'prefer-const': 'warn',
+ 'no-fallthrough': 'off',
+ 'no-mixed-spaces-and-tabs': 'off',
+ 'no-unreachable': 'warn',
+ '@typescript-eslint/no-unused-vars': [
+ 'warn',
+ {
+ vars: 'local',
+ args: 'after-used',
+ argsIgnorePattern: '^_',
+ ignoreRestSiblings: true
+ }
+ ],
+ // Svelte
+ 'svelte/html-quotes': ['warn', { prefer: 'double' }],
+ 'svelte/block-lang': ['error', { script: ['ts', null], style: null }],
+ 'svelte/comment-directive': ['error', { reportUnusedDisableDirectives: true }],
+ // Check File
+ 'check-file/filename-naming-convention': [
+ 'error',
+ {
+ 'src/**/*.{ts.d.ts}': 'CAMEL_CASE',
+ 'tools/**/*.{ts.d.ts}': 'CAMEL_CASE'
+ }
+ ],
+ 'check-file/folder-naming-convention': [
+ 'error',
+ {
+ 'src/**': 'KEBAB_CASE',
+ 'tools/**': 'KEBAB_CASE'
+ }
+ ],
+ // TypeScript
+ '@typescript-eslint/no-explicit-any': 'off',
+ '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
+ '@typescript-eslint/array-type': ['warn', { default: 'array-simple' }],
+ '@typescript-eslint/consistent-indexed-object-style': ['warn', 'record'],
+ '@typescript-eslint/consistent-generic-constructors': 'warn',
+ '@typescript-eslint/no-namespace': 'off',
+ '@typescript-eslint/restrict-template-expressions': 'off',
+ '@typescript-eslint/no-unsafe-member-access': 'off',
+ '@typescript-eslint/no-unsafe-assignment': 'off',
+ '@typescript-eslint/ban-ts-comment': 'off',
+ '@typescript-eslint/require-await': 'warn',
+ '@typescript-eslint/no-unsafe-call': 'off',
+ '@typescript-eslint/unbound-method': 'off',
+ '@typescript-eslint/no-non-null-assertion': 'off',
+ '@typescript-eslint/triple-slash-reference': 'off',
+ // Naming conventions
+ '@typescript-eslint/naming-convention': [
+ 'warn',
+ {
+ // DFU Version imports
+ selector: ['import'],
+ modifiers: ['default'],
+ filter: {
+ regex: 'v\\d+_\\d+_\\d+$',
+ match: true
+ },
+ custom: {
+ match: true,
+ regex: 'v\\d+_\\d+_\\d+$'
+ },
+ format: null
+ },
+ {
+ selector: ['import'],
+ modifiers: ['default'],
+ format: ['camelCase', 'PascalCase', 'UPPER_CASE']
+ },
+ {
+ selector: 'class',
+ format: ['PascalCase']
+ },
+ {
+ selector: ['classProperty', 'classMethod'],
+ format: ['camelCase']
+ },
+ {
+ selector: ['classProperty', 'classMethod'],
+ leadingUnderscore: 'allow',
+ format: ['camelCase']
+ },
+ {
+ selector: ['classProperty', 'classMethod'],
+ modifiers: ['private'],
+ leadingUnderscore: 'allowDouble',
+ trailingUnderscore: 'allowDouble',
+ format: ['camelCase']
+ },
+ {
+ selector: 'typeProperty',
+ format: null
+ },
+ {
+ selector: 'variable',
+ modifiers: ['const', 'destructured'],
+ format: null
+ },
+ {
+ selector: 'variable',
+ modifiers: ['const', 'global'],
+ types: ['function'],
+ leadingUnderscore: 'allow',
+ format: ['UPPER_CASE', 'camelCase']
+ },
+ {
+ selector: 'variable',
+ modifiers: ['const', 'global'],
+ leadingUnderscore: 'allow',
+ format: ['UPPER_CASE']
+ },
+ {
+ selector: 'variable',
+ modifiers: ['const', 'exported'],
+ format: ['camelCase', 'UPPER_CASE']
+ },
+ {
+ selector: 'variableLike',
+ format: ['camelCase']
+ },
+ { selector: 'interface', format: ['PascalCase'] },
+ {
+ selector: 'interface',
+ modifiers: ['exported'],
+ format: ['PascalCase'],
+ prefix: ['I']
+ },
+ { selector: 'typeLike', format: ['PascalCase'] },
+ { selector: 'objectLiteralProperty', format: null },
+ { selector: 'default', format: ['camelCase'] },
+ {
+ selector: 'parameter',
+ modifiers: ['unused'],
+ format: ['camelCase'],
+ leadingUnderscore: 'allow'
+ },
+ {
+ selector: 'parameter',
+ format: ['camelCase']
+ },
+ {
+ selector: 'enumMember',
+ format: ['camelCase', 'PascalCase', 'UPPER_CASE']
+ },
+ {
+ selector: 'enum',
+ format: ['UPPER_CASE']
+ }
+ ] satisfies NamingConventionRule
+}
+
+export default tsESLint.config(
+ {
+ ignores: IGNORE_PATTERNS
+ },
+ ...tsESLint.configs.stylisticTypeChecked,
+ ...svelteEslint.configs['flat/prettier'],
+ {
+ plugins: {
+ '@typescript-eslint': tsESLint.plugin,
+ svelte: svelteEslint
+ }
+ },
+ {
+ rules: CUSTOM_RULES
+ },
+ {
+ languageOptions: {
+ parser: tsESLint.parser,
+ parserOptions: {
+ project: './tsconfig.json',
+ extraFileExtensions: ['.svelte']
+ },
+ globals: {
+ browser: true,
+ node: true
+ }
+ }
+ },
+ {
+ files: ['**/*.svelte'],
+ rules: {
+ // Causes issues with Svelte and global types
+ 'no-undef': 'off',
+ '@typescript-eslint/naming-convention': [
+ 'warn',
+ {
+ selector: 'variable',
+ modifiers: ['exported'],
+ format: ['camelCase']
+ },
+ {
+ selector: 'variable',
+ modifiers: ['const', 'global'],
+ format: ['UPPER_CASE']
+ },
+ {
+ selector: 'variable',
+ modifiers: ['const', 'global'],
+ types: ['function'],
+ format: ['camelCase']
+ },
+ {
+ selector: 'variable',
+ format: ['camelCase'],
+ leadingUnderscore: 'allow'
+ }
+ ] satisfies NamingConventionRule
+ },
+ languageOptions: {
+ parser: svelteParser,
+ parserOptions: {
+ parser: tsESLint.parser,
+ svelteConfig: svelteConfig,
+ extraFileExtensions: ['.svelte']
+ },
+ globals: {
+ browser: true,
+ node: true
+ }
+ },
+ settings: {
+ ignoreWarnings: ['svelte/a11y-no-onchange', 'a11y-no-onchange']
+ }
+ },
+ {
+ languageOptions: {
+ parserOptions: {
+ projectService: true,
+ tsconfigRootDir: '.'
+ }
+ },
+ linterOptions: {
+ reportUnusedDisableDirectives: true
+ }
+ }
+)
diff --git a/package.json b/package.json
index 4e6e08c..906a50c 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,9 @@
"format": "prettier --write ."
},
"devDependencies": {
+ "@algolia/client-search": "^5.20.3",
+ "@docsearch/css": "^3.9.0",
+ "@docsearch/js": "^3.9.0",
"@iconify-json/ri": "^1.0.0",
"@iconify/json": "^2.2.219",
"@sveltejs/adapter-auto": "^3.0.0",
@@ -20,19 +23,24 @@
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@svelteness/kit-docs": "^1.1.5",
"@types/eslint": "^8.56.7",
+ "@types/react": "^19.0.10",
"clsx": "^1.0.0",
- "eslint": "^9.0.0",
+ "eslint": "^9.21.0",
"eslint-config-prettier": "^9.1.0",
- "eslint-plugin-svelte": "^2.36.0",
+ "eslint-plugin-svelte": "^3.0.2",
"globals": "^15.0.0",
+ "jiti": "^2.4.2",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
"shiki": "^0.12.0",
"svelte": "^4.2.7",
"svelte-check": "^3.6.0",
+ "svelte-eslint-parser": "^1.0.0",
"tslib": "^2.4.1",
"typescript": "^5.0.0",
- "typescript-eslint": "^8.0.0-alpha.20",
+ "typescript-eslint": "^8.25.0",
"unplugin-icons": "^0.19.0",
"vite": "^5.0.3"
},
@@ -40,5 +48,5 @@
"dependencies": {
"svelte-youtube-embed": "^0.3.0"
},
- "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
+ "packageManager": "yarn@4.7.0+sha512.5a0afa1d4c1d844b3447ee3319633797bcd6385d9a44be07993ae52ff4facabccafb4af5dcd1c2f9a94ac113e5e9ff56f6130431905884414229e284e37bb7c9"
}
diff --git a/src/app.d.ts b/src/app.d.ts
index efabaec..dc1e9d2 100644
--- a/src/app.d.ts
+++ b/src/app.d.ts
@@ -1,3 +1,4 @@
+///
Loading Title...
{:then title} @@ -102,6 +116,15 @@ display: flex; flex-direction: column; align-items: center; + transition: + transform 0.2s ease 0s, + opacity 0.2s ease 0s; + transform: translateY(16px) scale(0.9); + opacity: 0; + } + .thumbnail-container:global(.transition-in) { + transform: translateY(0) scale(1); + opacity: 1; } .thumbnail-container :global(button span) { display: flex; diff --git a/src/kit-docs/WigglyText.svelte b/src/kit-docs/WigglyText.svelte index 65969cc..f13eed5 100644 --- a/src/kit-docs/WigglyText.svelte +++ b/src/kit-docs/WigglyText.svelte @@ -27,4 +27,10 @@ animation: wave 1.5s infinite; animation-timing-function: ease-in-out; } + + @media (prefers-reduced-motion: reduce) { + .wiggly-text { + animation: none; + } + } diff --git a/src/kit-docs/kofiLogo.svelte b/src/kit-docs/kofiLogo.svelte new file mode 100644 index 0000000..d8a2c88 --- /dev/null +++ b/src/kit-docs/kofiLogo.svelte @@ -0,0 +1,8 @@ + diff --git a/src/lib/inView.ts b/src/lib/inView.ts index cb26ece..fbcea18 100644 --- a/src/lib/inView.ts +++ b/src/lib/inView.ts @@ -4,10 +4,10 @@ interface ISetObserverOptions { bottom?: number } -export default function inView(node: HTMLElement, options: ISetObserverOptions = {}) { +export function inView(node: HTMLElement, options: ISetObserverOptions = {}) { let observer: IntersectionObserver - const handleIntersect: IntersectionObserverCallback = (e) => { + const handleIntersect: IntersectionObserverCallback = e => { const v = e[0].isIntersecting ? 'enter' : 'exit' node.dispatchEvent(new CustomEvent(v)) } @@ -31,6 +31,6 @@ export default function inView(node: HTMLElement, options: ISetObserverOptions = destroy() { if (observer) observer.disconnect() - } + }, } } diff --git a/src/lib/index.ts b/src/lib/index.ts index b2decee..fa9efd3 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,2 +1,3 @@ // place files you want to import through the `$lib` alias in this folder. -export { default as inView } from './inView' +export * from './scrollAnim' +export * from './inView' diff --git a/src/lib/scrollAnim.ts b/src/lib/scrollAnim.ts new file mode 100644 index 0000000..39db2a5 --- /dev/null +++ b/src/lib/scrollAnim.ts @@ -0,0 +1,67 @@ +import { quartOut } from 'svelte/easing' + +interface IScrollAnimatorOptions { + x?: number + yOffset?: number + opacity?: number + scale?: number + rate?: number + easing?: (t: number) => number +} + +export function scrollAnimator(element: HTMLElement, options: IScrollAnimatorOptions = {}) { + const rect = element.getBoundingClientRect() + const docRect = document.body.getBoundingClientRect() + element.style.opacity = '0' + element.style.transition = 'opacity 0.1s ease, transform 0.1s ease' + + const rate = options.rate || 1 + + let top = rect.top - docRect.top - window.innerHeight / 2 + if (options.yOffset) top += options.yOffset + else top += -rect.height / 2 + + const moveX = options.x || 0 + const scale = options.scale + + const updateTransform = (t: number) => { + t = (options.easing ?? quartOut)(t) + const x = -moveX + moveX * t + let s = 1 + if (scale) { + s = scale + (1 - scale) * t + } + element.style.transform = `translateX(${x}px) scale(${s})` + } + + const updateOpacity = (t: number) => { + element.style.opacity = `${Math.min(t * 1.25, 1)}` + } + + const observer = () => { + const scroll = window.scrollY + const localScroll = Math.min(Math.max(scroll - top, 0), rect.height) + const percent = Math.min(Math.max(localScroll / (rect.height * rate), 0), 1) + updateTransform(percent) + updateOpacity(percent) + } + + let intervalID: number | undefined + const setObserver = ({}: IScrollAnimatorOptions) => { + if (intervalID) clearInterval(intervalID) + intervalID = setInterval(observer, 16) + observer() + } + + setObserver(options) + + return { + update(args: IScrollAnimatorOptions) { + setObserver(args) + }, + + destroy() { + if (intervalID) clearInterval(intervalID) + }, + } +} diff --git a/src/lib/strings.ts b/src/lib/strings.ts new file mode 100644 index 0000000..6be0f12 --- /dev/null +++ b/src/lib/strings.ts @@ -0,0 +1 @@ +export const SLOGAN = 'Effortlessly craft complex animations for Minecraft: Java Edition' diff --git a/src/lib/styles/kit-docs.css b/src/lib/styles/kit-docs.css index f92791a..67f4596 100644 --- a/src/lib/styles/kit-docs.css +++ b/src/lib/styles/kit-docs.css @@ -1,20 +1,6 @@ -:root, -.prefers-light-scheme { - --kd-color-brand: 0 172 237; - --kd-color-focus: 79 70 229; - --kd-color-soft: 68 78 94; - --kd-color-body: 250 250 250; - --kd-color-elevate: 243 244 246; - --kd-color-inverse: 5 11 23; - --kd-color-border: 209 213 219; - - --kd-code-fence-bg: rgb(212 217 251); - --kd-code-fence-fg: rgb(26, 29, 36); -} - :root { font-size: 16px; - scroll-padding-top: 6rem; + scroll-padding-top: 8rem; --kd-font-family-sans: Inter VF, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', @@ -64,18 +50,18 @@ } } -:root.dark, -.prefers-dark-scheme { +:root { color-scheme: dark; + --kd-color-focus: 0 172 237 !important; --kd-color-brand: 0 172 237; --kd-color-soft: 181 186 199; --kd-color-inverse: 245 245 245; --kd-color-border: 38 48 64; - --kd-color-elevate: 43 44 50; + --kd-color-elevate: 48 52 65; --kd-color-body: 31 33 40; --kd-color-focus: 129 140 248; - --kd-color-subtle: rgb(106, 116, 132); + --kd-color-subtle: rgb(144 156 176); --kd-code-fence-bg: rgb(22 23 27); --kd-code-fence-fg: rgb(186 190 216); @@ -96,6 +82,14 @@ code::after { content: '' !important; } +.code-fence { + border-radius: 4px 4px 4px 4px; +} + +.kit-docs .code-fence .code pre { + margin-bottom: 4px; +} + code:not(pre code) { background-color: #16171b !important; padding: 4px 6px !important; @@ -106,6 +100,81 @@ code:not(pre code) { text-wrap: nowrap !important; } +a.link { + color: var(--tw-prose-links) !important; + text-decoration: none; + font-weight: 400; + border-bottom: 1px solid rgb(var(--kd-color-brand)); +} + td { text-wrap: balance !important; } + +p > img { + max-width: 75% !important; +} + +#main-sidebar { + width: 64px !important; + max-width: 64px !important; +} + +.on-this-page:not(:has(*)) { + display: none !important; +} +.on-this-page { + width: 25%; + padding-left: 1rem; +} +.on-this-page li { + list-style: disc; + font-size: small; +} + +* { + scrollbar-width: unset !important; +} + +.scrollbar::-webkit-scrollbar { + width: 8px !important; + height: 8px !important; +} +.scrollbar::-webkit-scrollbar-thumb { + background-color: rgb(var(--kd-color-brand)) !important; + border-radius: 2px !important; +} +.scrollbar::-webkit-scrollbar-track { + background-color: rgb(var(--kd-color-elevate)) !important; + border-radius: 2px !important; +} + +::-webkit-scrollbar { + width: 8px !important; + height: 8px !important; +} + +::-webkit-scrollbar-thumb { + background-color: rgb(var(--kd-color-brand)) !important; + border-radius: 2px !important; +} + +::-webkit-scrollbar-track { + background-color: rgb(var(--kd-color-elevate)) !important; + border-radius: 2px !important; + margin: 0 4px !important; +} + +::-webkit-scrollbar-thumb:hover { + background-color: rgb(var(--kd-color-brand)) !important; +} + +table { + box-shadow: inset 0 0 0 1px rgb(var(--kd-color-border)); + background-color: #1c1e24; +} + +th { + padding: 0.3rem 0.6rem !important; + vertical-align: middle !important; +} diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte new file mode 100644 index 0000000..3d7cdc1 --- /dev/null +++ b/src/routes/+error.svelte @@ -0,0 +1,7 @@ + diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index b491f01..03bbdda 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,73 +1,121 @@ -