commit d04c218f365c18a81f99ae21dc5580243b367bae Author: Ben Aultowski Date: Wed Feb 25 21:21:50 2026 -0500 Squashed 'graphics-components-src/' content from commit 247be9ce git-subtree-dir: graphics-components-src git-subtree-split: 247be9ce40bd338d3934534fb6392504a0cdc81f diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..e5b6d8d --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..1c879e2 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.0.2/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": true, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..25a4c4b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @hobbes7878 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..eb08400 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +### What's in this pull request + +Tell us what this PR does or link to any related issues that describe the goal here. + +### Before submitting, please check that you've ... + +- [x] Read our [contributing guide](https://github.com/reuters-graphics/graphics-components/blob/master/CONTRIBUTING.md) +- [ ] Documented any new components or features +- [ ] Tagged an editor to review this PR diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml new file mode 100644 index 0000000..c2b8819 --- /dev/null +++ b/.github/workflows/check.yaml @@ -0,0 +1,29 @@ +name: Check + +on: + pull_request: + branches: + - main + +jobs: + svelte-check: + name: Run svelte-check + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + - name: Install dependencies + run: | + pnpm i + pnpm svelte-kit sync + - name: Run svelte-check + run: pnpm svelte-check --output machine diff --git a/.github/workflows/chromatic.yaml b/.github/workflows/chromatic.yaml new file mode 100644 index 0000000..62ed342 --- /dev/null +++ b/.github/workflows/chromatic.yaml @@ -0,0 +1,31 @@ +name: 'Chromatic' + +on: + pull_request: + branches: + - main + +jobs: + chromatic: + name: Run Chromatic + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup pnpm + uses: pnpm/action-setup@v4 + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: 22.12.0 + cache: pnpm + - name: Install dependencies + run: pnpm i + - name: Run Chromatic + uses: chromaui/action@latest + with: + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + buildScriptName: 'build:docs' + # exitZeroOnChanges: false diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 0000000..5fce578 --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,11 @@ +name: Manually publish docs + +on: + workflow_dispatch: + +jobs: + docs: + uses: reuters-graphics/action-workflows/.github/workflows/docs.yaml@main + secrets: inherit + with: + node_version: '20' diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..1f59833 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,11 @@ +name: Lint + +on: + pull_request: + branches: + - main + +jobs: + lint: + uses: reuters-graphics/action-workflows/.github/workflows/lint.yaml@main + secrets: inherit diff --git a/.github/workflows/pkg.pr.new.yaml b/.github/workflows/pkg.pr.new.yaml new file mode 100644 index 0000000..71c28a1 --- /dev/null +++ b/.github/workflows/pkg.pr.new.yaml @@ -0,0 +1,32 @@ +name: Publish preview +on: + push: + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build + run: pnpm build + + - name: Publish to pkg.pr.new + run: pnpm dlx pkg-pr-new publish --packageManager=pnpm diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..7f58594 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,29 @@ +name: Release + +on: + push: + branches: + - main + +jobs: + release: + uses: reuters-graphics/action-workflows/.github/workflows/changesets-release.yaml@main + secrets: inherit + with: + node_version: '20' + publish_docs: true + + notify-downstream: + needs: release + if: needs.release.outputs.published == 'true' + runs-on: ubuntu-latest + steps: + - name: Wait for npm propagation + run: sleep 30 + + - name: Dispatch to bluprint_graphics-kit + uses: peter-evans/repository-dispatch@v4 + with: + token: ${{ secrets.REPO_PAT_TOKEN }} + repository: reuters-graphics/bluprint_graphics-kit + event-type: dependency-updated diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba7f352 --- /dev/null +++ b/.gitignore @@ -0,0 +1,194 @@ +# Created by https://www.toptal.com/developers/gitignore/api/node,macos,linux +# Edit at https://www.toptal.com/developers/gitignore?templates=node,macos,linux + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Node Patch ### +# Serverless Webpack directories +.webpack/ + +# Optional stylelint cache + +# SvelteKit build / generate output +.svelte-kit + +# End of https://www.toptal.com/developers/gitignore/api/node,macos,linux + +*storybook.log diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..4fd0219 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..db4854f --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +docs +dist +node_modules +!src/docs/ +pnpm-lock.yaml \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..095a02c --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,10 @@ +import { svelte as svelteConfig } from '@reuters-graphics/yaks-prettier'; + +/** + * @type {import("prettier").Config} + */ +const config = { + ...svelteConfig, +}; + +export default config; diff --git a/.storybook/Theme.ts b/.storybook/Theme.ts new file mode 100644 index 0000000..a58cb3d --- /dev/null +++ b/.storybook/Theme.ts @@ -0,0 +1,9 @@ +import { create } from '@storybook/theming'; + +export default create({ + base: 'light', + brandTitle: 'Reuters Graphics components', + brandUrl: 'https://reuters-graphics.github.io/graphics-components/', + brandImage: './logo.svg', + brandTarget: '_self', +}); diff --git a/.storybook/Wrapper.svelte b/.storybook/Wrapper.svelte new file mode 100644 index 0000000..34a3779 --- /dev/null +++ b/.storybook/Wrapper.svelte @@ -0,0 +1,12 @@ + + + +
+ +
+
diff --git a/.storybook/main.ts b/.storybook/main.ts new file mode 100644 index 0000000..8cb90af --- /dev/null +++ b/.storybook/main.ts @@ -0,0 +1,18 @@ +import type { StorybookConfig } from '@storybook/sveltekit'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|ts|svelte)'], + addons: [ + '@storybook/addon-svelte-csf', + '@storybook/addon-essentials', + '@chromatic-com/storybook', + '@storybook/addon-interactions', + '@storybook/addon-a11y', + 'storybook-addon-rtl', + ], + framework: { + name: '@storybook/sveltekit', + options: {}, + }, +}; +export default config; diff --git a/.storybook/manager.ts b/.storybook/manager.ts new file mode 100644 index 0000000..f1e9843 --- /dev/null +++ b/.storybook/manager.ts @@ -0,0 +1,25 @@ +import { addons } from '@storybook/manager-api'; +import theme from './Theme'; + +addons.setConfig({ + isFullscreen: false, + showNav: true, + showPanel: true, + panelPosition: 'bottom', + enableShortcuts: true, + showToolbar: true, + selectedPanel: undefined, + initialActive: 'sidebar', + sidebar: { + showRoots: false, + collapsedRoots: ['other'], + }, + toolbar: { + title: { hidden: false }, + zoom: { hidden: false }, + eject: { hidden: false }, + copy: { hidden: false }, + fullscreen: { hidden: false }, + }, + theme, +}); diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html new file mode 100644 index 0000000..22a1e2a --- /dev/null +++ b/.storybook/preview-head.html @@ -0,0 +1,13 @@ + + + + + diff --git a/.storybook/preview.scss b/.storybook/preview.scss new file mode 100644 index 0000000..c99763a --- /dev/null +++ b/.storybook/preview.scss @@ -0,0 +1,136 @@ +@use './syntax.scss'; + +body { + font-family: 'Nunito Sans', Helvetica, Arial, sans-serif; +} + +table.docblock-argstable { + p { + font-family: inherit; + font-size: inherit; + } + + ul { + padding-inline-start: 20px; + } +} + +div.sbdocs :where(p:not(.sb-anchor, .sb-unstyled, .sb-unstyled p)) { + font-size: 16px; +} + +div.sbdocs-content { + h1:not(.sbdocs-preview *) { + font-family: 'Knowledge', sans-serif; + } + & > h2, + & > div > div > h2 { + margin-top: 4rem; + margin-bottom: 2rem; + &:first-of-type { + margin-top: 4rem; + margin-bottom: 2rem; + } + } + + .docblock-source { + margin: 1rem 0 2.5rem; + } + + & > div > :where(p, ul, ol), + .sb-anchor > div > :where(p, ul, ol) { + font-size: 18px; + line-height: 29px; + font-family: 'Knowledge', sans-serif; + + .highlight { + background-color: rgb(254, 254, 160); + padding: 0 4px; + } + .bold { + font-weight: bold; + } + a { + font-family: 'Knowledge', sans-serif; + color: #0071a1; + text-decoration: none; + text-underline-offset: 2px; + &:hover { + text-decoration: underline; + } + } + } +} + +.sbdocs-content { + blockquote:not(.sb-unstyled *) { + background-color: #ededed; + padding: 15px 20px; + border: 1px solid #ccc; + border-radius: 4px; + margin: 2rem auto; + p { + font-size: 16px; + line-height: 22px; + } + } +} + +.sbdocs-content div.sbdocs:not(.sb-unstyled) { + font-family: 'Knowledge', sans-serif; + + h1 { + font-family: 'Knowledge', sans-serif; + } + p, + ul, + li { + font-size: 18px; + line-height: 29px; + font-family: 'Knowledge', sans-serif; + + .highlight { + background-color: rgb(254, 254, 160); + padding: 0 4px; + } + .bold { + font-weight: bold; + } + } + a { + font-family: 'Knowledge', sans-serif; + color: #0071a1; + text-decoration: none; + text-underline-offset: 2px; + &:hover { + text-decoration: underline; + } + } + + &:not(.sbdocs-preview) { + code { + font-size: 90%; + margin-left: 2px; + margin-right: 2px; + background-color: #efefef; + padding: 2px 4px; + } + + img { + display: block; + margin-top: 1rem; + margin-bottom: 2rem; + } + + blockquote { + code { + background-color: #d9d9d9; + } + } + } +} + +div.reset-article { + width: calc(100% + 30px); + margin-left: -15px; +} diff --git a/.storybook/preview.ts b/.storybook/preview.ts new file mode 100644 index 0000000..13fc4bb --- /dev/null +++ b/.storybook/preview.ts @@ -0,0 +1,68 @@ +import '../src/scss/main.scss'; +import './preview.scss'; + +import { SyntaxHighlighter } from '@storybook/components'; +import Wrapper from './Wrapper.svelte'; +import markdown from 'react-syntax-highlighter/dist/esm/languages/prism/markdown'; +import scss from 'react-syntax-highlighter/dist/esm/languages/prism/scss'; +import svelte from './svelte-highlighting.js'; + +import type { Preview } from '@storybook/svelte'; + +SyntaxHighlighter.registerLanguage('scss', scss); +SyntaxHighlighter.registerLanguage('svelte', svelte); +SyntaxHighlighter.registerLanguage('markdown', markdown); + +const preview: Preview = { + // @ts-ignore Is OK + decorators: [() => Wrapper], + tags: ['autodocs', 'autodocs', 'autodocs', 'autodocs'], + parameters: { + viewMode: 'docs', + previewTabs: { 'storybook/docs/panel': { index: -1 } }, + controls: { + expanded: true, + sort: 'requiredFirst', + matchers: { + color: /(background|colour|Colour)$/i, + date: /Date$/, + }, + }, + layout: 'fullscreen', + options: { + // https://storybook.js.org/docs/writing-stories/naming-components-and-hierarchy#sorting-stories + storySort: { + method: 'alphabetical-by-kind', + includeNames: false, + order: [ + 'Intro', + 'Guides', + [ + 'Using these docs', + 'Using with the graphics kit', + 'Using with ArchieML docs', + 'Customising components with SCSS', + '*', + 'Getting help', + ], + 'Components', + ['*', ['Intro', '*']], + 'Styles', + [ + 'Intro', + 'Colours', + ['Intro', 'Primary', 'Thematic', '*'], + 'Tokens', + ['Intro', 'Typography', '*'], + ], + 'Actions', + ['Intro', '*'], + 'Contributing', + ['Quickstart', 'Component Basics', 'Writing Stories', '*'], + ], + }, + }, + }, +}; + +export default preview; diff --git a/.storybook/svelte-highlighting.d.ts b/.storybook/svelte-highlighting.d.ts new file mode 100644 index 0000000..4edb4fb --- /dev/null +++ b/.storybook/svelte-highlighting.d.ts @@ -0,0 +1,7 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +declare function svelte(Prism: any): void; +declare namespace svelte { + let displayName: string; + let aliases: any[]; +} +export default svelte; diff --git a/.storybook/svelte-highlighting.js b/.storybook/svelte-highlighting.js new file mode 100644 index 0000000..bdbd49b --- /dev/null +++ b/.storybook/svelte-highlighting.js @@ -0,0 +1,149 @@ +svelte.displayName = 'svelte'; +svelte.aliases = []; + +export default function svelte(Prism) { + const blocks = '(if|else if|await|then|catch|each|html|debug)'; + + Prism.languages.svelte = Prism.languages.extend('markup', { + each: { + pattern: new RegExp( + '{[#/]each' + + '(?:(?:\\{(?:(?:\\{(?:[^{}])*\\})|(?:[^{}]))*\\})|(?:[^{}]))*}' + ), + inside: { + 'language-javascript': [ + { + pattern: /(as[\s\S]*)\([\s\S]*\)(?=\s*\})/, + lookbehind: true, + inside: Prism.languages['javascript'], + }, + { + pattern: /(as[\s]*)[\s\S]*(?=\s*)/, + lookbehind: true, + inside: Prism.languages['javascript'], + }, + { + pattern: /(#each[\s]*)[\s\S]*(?=as)/, + lookbehind: true, + inside: Prism.languages['javascript'], + }, + ], + keyword: /[#/]each|as/, + punctuation: /{|}/, + }, + }, + block: { + pattern: new RegExp( + '{[#:/@]/s' + + blocks + + '(?:(?:\\{(?:(?:\\{(?:[^{}])*\\})|(?:[^{}]))*\\})|(?:[^{}]))*}' + ), + inside: { + punctuation: /^{|}$/, + keyword: [new RegExp('[#:/@]' + blocks + '( )*'), /as/, /then/], + 'language-javascript': { + pattern: /[\s\S]*/, + inside: Prism.languages['javascript'], + }, + }, + }, + tag: { + pattern: + /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?:"[^"]*"|'[^']*'|{[\s\S]+?}(?=[\s/>])))|(?=[\s/>])))+)?\s*\/?>/i, + greedy: true, + inside: { + tag: { + pattern: /^<\/?[^\s>\/]+/i, + inside: { + punctuation: /^<\/?/, + namespace: /^[^\s>\/:]+:/, + }, + }, + 'language-javascript': { + pattern: + /\{(?:(?:\{(?:(?:\{(?:[^{}])*\})|(?:[^{}]))*\})|(?:[^{}]))*\}/, + inside: Prism.languages['javascript'], + }, + 'attr-value': { + pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i, + inside: { + punctuation: [ + /^=/, + { + pattern: /^(\s*)["']|["']$/, + lookbehind: true, + }, + ], + 'language-javascript': { + pattern: /{[\s\S]+}/, + inside: Prism.languages['javascript'], + }, + }, + }, + punctuation: /\/?>/, + 'attr-name': { + pattern: /[^\s>\/]+/, + inside: { + namespace: /^[^\s>\/:]+:/, + }, + }, + }, + }, + 'language-javascript': { + pattern: /\{(?:(?:\{(?:(?:\{(?:[^{}])*\})|(?:[^{}]))*\})|(?:[^{}]))*\}/, + lookbehind: true, + inside: Prism.languages['javascript'], + }, + }); + + Prism.languages.svelte['tag'].inside['attr-value'].inside['entity'] = + Prism.languages.svelte['entity']; + + Prism.hooks.add('wrap', (env) => { + if (env.type === 'entity') { + env.attributes['title'] = env.content.replace(/&/, '&'); + } + }); + + Object.defineProperty(Prism.languages.svelte.tag, 'addInlined', { + value: function addInlined(tagName, lang) { + const includedCdataInside = {}; + includedCdataInside['language-' + lang] = { + pattern: /(^$)/i, + lookbehind: true, + inside: Prism.languages[lang], + }; + includedCdataInside['cdata'] = /^$/i; + + const inside = { + 'included-cdata': { + pattern: //i, + inside: includedCdataInside, + }, + }; + inside['language-' + lang] = { + pattern: /[\s\S]+/, + inside: Prism.languages[lang], + }; + + const def = {}; + def[tagName] = { + pattern: RegExp( + /(<__[\s\S]*?>)(?:\s*|[\s\S])*?(?=<\/__>)/.source.replace( + /__/g, + tagName + ), + 'i' + ), + lookbehind: true, + greedy: true, + inside, + }; + + Prism.languages.insertBefore('svelte', 'cdata', def); + }, + }); + + Prism.languages.svelte.tag.addInlined('style', 'css'); + Prism.languages.svelte.tag.addInlined('script', 'javascript'); +} diff --git a/.storybook/syntax.scss b/.storybook/syntax.scss new file mode 100644 index 0000000..7c05f63 --- /dev/null +++ b/.storybook/syntax.scss @@ -0,0 +1,145 @@ +/** + * Nord theme styling for source code in docs + */ + +.docblock-source { + border: 6px solid #333 !important; + overflow: hidden; + border-radius: 6px !important; + box-shadow: + 0 10px 20px rgba(0, 0, 0, 0.19), + 0 6px 6px rgba(0, 0, 0, 0.23) !important; + padding: 0 !important; + button { + background-color: #0071a1; + color: white; + border-top-left-radius: 0; + &:focus { + box-shadow: #4ee8c4 0 -3px 0 0 inset; + } + } +} + +div pre.prismjs { + background-color: #2e3440 !important; + color: #f8f8f2; + + code[class*='language-'], + pre[class*='language-'] { + color: #f8f8f2; + background: none; + font-family: + 'Fira Code', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; + } + + /* Code blocks */ + pre[class*='language-'] { + padding: 1em; + margin: 0.5em 0; + overflow: auto; + border-radius: 0.3em; + } + + :not(pre) > code[class*='language-'], + pre[class*='language-'] { + background: #2e3440; + } + + /* Inline code */ + :not(pre) > code[class*='language-'] { + padding: 0.1em; + border-radius: 0.3em; + white-space: normal; + } + + .token.comment, + .token.prolog, + .token.doctype, + .token.cdata { + color: #9199aa; + } + + .token.punctuation { + color: #81a1c1; + } + + .namespace { + opacity: 0.7; + } + + .token.property, + .token.tag, + .token.constant, + .token.symbol, + .token.deleted { + color: #81a1c1; + } + + .token.number { + color: #b48ead; + } + + .token.boolean { + color: #81a1c1; + } + + .token.selector, + .token.attr-name, + .token.string, + .token.char, + .token.builtin, + .token.inserted { + color: #a3be8c; + } + + .token.operator, + .token.entity, + .token.url, + .language-css .token.string, + .style .token.string, + .token.variable { + color: #81a1c1; + } + + .token.atrule, + .token.attr-value, + .token.function, + .token.class-name { + color: #88c0d0; + } + + .token.keyword { + color: #81a1c1; + } + + .token.regex, + .token.important { + color: #ebcb8b; + } + + .token.important, + .token.bold { + font-weight: bold; + } + + .token.italic { + font-style: italic; + } + + .token.entity { + cursor: help; + } +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..20d8bd5 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "unifiedjs.vscode-mdx", + "somewhatstationery.some-sass", + "svelte.svelte-vscode" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a8ef4c9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,18 @@ +{ + "eslint.validate": ["javascript", "javascriptreact", "svelte", "jsx"], + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "emmet.excludeLanguages": ["markdown", "scss"], + "files.associations": { + "*.svx": "mdx" + }, + "[mdx]": { + "editor.wordWrap": "on" + }, + "[svelte]": { + "editor.defaultFormatter": "svelte.svelte-vscode" + }, + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/.vscode/svelte.styles.code-snippets b/.vscode/svelte.styles.code-snippets new file mode 100644 index 0000000..d7a67a8 --- /dev/null +++ b/.vscode/svelte.styles.code-snippets @@ -0,0 +1,8 @@ +{ + "Svelte SCSS style": { + "scope": "svelte", + "prefix": "scss", + "body": [""], + "description": "Add a Svelte SCSS style tag", + }, +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4a5fdea --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,278 @@ +# @reuters-graphics/graphics-components + +## 3.2.1 + +### Patch Changes + +- 94c2346: Fixes fontface definitions for Newsreader typeface to fix issue with bold and bolder weights. + +## 3.2.0 + +### Minor Changes + +- df7c622: Adding a basic pmtiles map component + +## 3.1.0 + +### Minor Changes + +- 0f9248c: Replaces FreightText with Newsreader Text font + +## 3.0.27 + +### Patch Changes + +- 6dc6e54: Removes demo files, docs and stories from the published package. + +## 3.0.26 + +### Patch Changes + +- 27d07e4: Adds Lottie component +- f9aec45: Adds HorizontalScroller component + +## 3.0.25 + +### Patch Changes + +- 257f967: Updates svelte-fa version + +## 3.0.24 + +### Patch Changes + +- 0fce4cd: Removes dev from $app/environment + +## 3.0.23 + +### Patch Changes + +- 022d0dc: Test downstream notification workflow with updated reusable workflow + +## 3.0.22 + +### Patch Changes + +- bf550d5: Test downstream workflow notification system + +## 3.0.21 + +### Patch Changes + +- a2e6e8d: Fixes a bug in PhotoPack that on earlier iPhones would break. Also adds smarter default layouts based on the number of images in the pack and the max width of the PhotoPack. + +## 3.0.20 + +### Patch Changes + +- 6d5c152: Removes stray Google Analytics loading call so GA is only loaded via Google Tag Manager. + +## 3.0.19 + +### Patch Changes + +- 627f267: Enhances progress reactivity for ScrollerVideo + +## 3.0.18 + +### Patch Changes + +- 1402aac: Fix for GTM tags + +## 3.0.17 + +### Patch Changes + +- cd0dc83: Updates analytics scripts to work with GDPR-compliant GTM container + +## 3.0.16 + +### Patch Changes + +- 2b6b4f4: Fixes prettifyDate to format Aug, Oct-Dec + +## 3.0.15 + +### Patch Changes + +- 68b51a1: Adds util function prettifyDate + +## 3.0.14 + +### Patch Changes + +- fdc3c6b: Moves dependencies to dependencies from devDependencies + +## 3.0.13 + +### Patch Changes + +- 36d5896: Adds ScrollerVideo + +## 3.0.12 + +### Patch Changes + +- 771ccb4: Fixes sizing issue for Framer + +## 3.0.11 + +### Patch Changes + +- 31caab2: Fix typos in Scroller + +## 3.0.10 + +### Patch Changes + +- cf7e513: Updated oneTrustId to production ID + +## 3.0.9 + +### Patch Changes + +- 18e49eb: renames Theme and CustomTheme types + +## 3.0.8 + +### Patch Changes + +- bdf3918: Updates Visible to allow unit specification for top, bototm, right, left and adds a demo + +## 3.0.7 + +### Patch Changes + +- f80e450: Removes Parsely page analytics + +## 3.0.6 + +### Patch Changes + +- a205a35: Adds new Headpile component. + +## 3.0.5 + +### Patch Changes + +- f41f79b: Creates ScrollerBase component, which is used in Scroller and can be used to make custom scrollytelling components. + +## 3.0.4 + +### Patch Changes + +- 06beea8: Update tokens and component layouts to accomodate margins and paddings for RTL webpages + +## 3.0.3 + +### Patch Changes + +- c074a18: Allows step.background to be undefined + +## 3.0.2 + +### Patch Changes + +- 737f2e1: Adds a simple dropdown option to search embeds for Framer +- a032218: Don't fetch referrals on non-dotcom domains +- 2d4a641: Cleans up a spare console log left in +- c91807e: a11y fixes for SiteHeader and SiteFooter +- b13463f: fixes for Ad types that were colliding with their component names and a bug in the Framer Resizer +- a48d333: Ignore hydration mismatch in SEO component ld+json + +## 3.0.1 + +### Patch Changes + +- 93a41f3: Exposes bindable props for the Scroller component + +## 3.0.0 + +### Major Changes + +- 7432131: Svelte 5.0+ components. + + #### What's in it? + + 3.0 updates all graphics components to [Svelte 5 syntax](https://svelte.dev/docs/svelte/v5-migration-guide). + + Components are now only compatible with Svelte 5-based versions of the graphics kit, starting with [1.1.0](https://github.com/reuters-graphics/bluprint_graphics-kit/blob/main/CHANGELOG.md#110). + +## 2.0.3 + +### Patch Changes + +- 50f4320: Updates favicons for new kinesis + +## 2.0.2 + +### Patch Changes + +- 64b6d88: Fix for changed thumbnail API schema + +## 2.0.1 + +### Patch Changes + +- ca278c4: ReferralBlock checks if a referral is for the current page and doesn't include it if so. + +## 2.0.0 + +### Major Changes + +- 3e20529: Removes Google Docs-based utils in favour of ArchieML/RNGS.io examples. + +### Patch Changes + +- a5ad543: Docs syntax highlighting and organisation +- 06b4d48: Updates ReferralBlock and SiteFooter +- b44ed64: Reuters Graphics logo refresh +- 05b80fd: Patches up component docs links + +## 1.1.7 + +### Patch Changes + +- 9dec472: Background change to action workflows... + +## 1.1.6 + +### Patch Changes + +- d7d88e1: Adds parsely analytics + +## 1.1.5 + +### Patch Changes + +- 2217848: Adds a skip link to the header component + +## 1.1.4 + +### Patch Changes + +- 4788ee2: Adds Dotcom Knowledge font aliases needed for ads + +## 1.1.3 + +### Patch Changes + +- 146b970: Fixes "more" menu options + +## 1.1.2 + +### Patch Changes + +- d459852: Ads will collapse if unfulfilled + +## 1.1.1 + +### Patch Changes + +- 23b001b: Excludes Google ads from iframe reset + +## 1.1.0 + +### Minor Changes + +- 6e2b8a7: Updates Storybook and makes Svelte 4 minimum. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3534405 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,66 @@ +# Contributing Guide + +## Why this? + +Most Reuters Graphics repos don't include (or need) contributing guidelines. The ones that do represent critical infrastructure. They also are the ones we most want wider contributions from the team to improve and maintain. + +This doc provides for a few simple guidelines to make sure changes are well considered and represent the best ideas for how to move our tools forward while opening up the opportunity for others to ship their next great idea. + +## Who can contribute? + +Contributions are always welcome from members of the Reuters Graphics team. + +Anyone outside our team using these components is welcome to submit PRs or issues, **BUT** if they are designed solely to benefit a use case that isn't ours, they likely won't be merged. + +## How should Reuters Graphics staff contribute? + +### ๐Ÿท๏ธ Make an issue + +We recommend your first step is to create an issue on this repo describing what is missing, broken or could be added or improved. (We'll close that issue when we merge your PR.) + +- It's helpful if that issue describes what changes you propose to make at a high level so we can agree on a general direction before you write code. That's especially true if code you're writing will change how others need to write theirs. +- If needed, provide any links to best practice guidelines that support the change you want to make, e.g., for making accessibility improvements to components. +- Tag others on the team who may have expertise or would contribute to any needed discussion. +- **Always tag an editor.** + +### ๐Ÿงน Follow code standards + +Once you're ready to submit code, be sure it's properly formatted _before_ you ask for a review and run our built-in code linters (eslint + prettier) over your changed files: + +```console +pnpm lint && pnpm format +``` + +Any public methods or component props should be properly typed and documented with comments. (See existing components for examples.) For future developers, also add comments around any tricky bits of _internal_ logic you're adding. + +### ๐Ÿ“ Write Storybook stories + +All new components and component features should be accompanied by [Storybook stories](https://reuters-graphics.github.io/graphics-svelte-components/) included with your PR. See other components for examples of how to add them. + +Be sure to target your Storybook docs for non-developers with real world examples of how to use components within the graphics kit. + +### ๐Ÿบ Submit code with a changeset + +All code contributions should be made through the normal [GitHub Flow](https://www.w3schools.com/git/git_github_flow.asp#:~:text=The%20GitHub%20flow%20is%20a,Make%20changes%20and%20add%20Commits). Basically, make a branch and submit a pull request. + +(Generally, it's better to avoid bundling several new features or components in a single PR. Breaking them apart into smaller, individual contributions makes them easier to review and manage.) + +Each PR should be accompanied by a [changeset](https://github.com/changesets/changesets). You can add one by running: + +```console +pnpm changeset add +``` + +Once you've submitted your PR, tag an editor to review it. + +An editor will approve your PR after addressing any issues they see. Once an editor approves and there are no conflicts or failing tests, you can merge your PR into master. + +### Test in downstream projects + +Once a PR is created, a testable version of the library is published via [pkg.pr.new](https://github.com/stackblitz-labs/pkg.pr.new). A comment will be added to your PR that documents how to install the library's test version. Use it to test any new components or features in the graphics kit. + +### โœ‰๏ธ Publishing to the team + +Publishing is handled via [changesets](https://github.com/changesets/changesets) and should follow [semantic versioning](https://semver.org/) conventions. Most MINOR and all MAJOR version changes should be identified ahead of time during PR review. + +Once a new version of the library is published, a [PR will be created in the graphics kit](https://github.com/reuters-graphics/bluprint_graphics-kit/pulls) to update this dependency. Merge that. diff --git a/README.md b/README.md new file mode 100644 index 0000000..984a2d6 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +![](https://graphics.thomsonreuters.com/style-assets/images/logos/reuters-graphics-logo/svg/graphics-logo-color-dark.svg) + +# โš™๏ธ graphics-components + +[![npm version](https://badge.fury.io/js/@reuters-graphics%2Fgraphics-components.svg)](https://badge.fury.io/js/@reuters-graphics%2Fgraphics-components) + +Svelte components, SCSS and more for Reuters Graphics pages. + +[Read the docs.](https://reuters-graphics.github.io/graphics-components/) diff --git a/chromatic.config.json b/chromatic.config.json new file mode 100644 index 0000000..1a16ff5 --- /dev/null +++ b/chromatic.config.json @@ -0,0 +1,6 @@ +{ + "onlyChanged": true, + "projectId": "Project:64a5c42823795823edcb60f4", + "zip": true, + "buildScriptName": "build:docs" +} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..42f0a81 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,50 @@ +import { svelte } from '@reuters-graphics/yaks-eslint'; +import reactPlugin from 'eslint-plugin-react'; +import * as mdx from 'eslint-plugin-mdx'; +import storybook from 'eslint-plugin-storybook'; + +export default [ + { + files: ['src/**/*.{js,ts,svelte,jsx,tsx,mdx}', '.storybook/**/*'], + }, + { + ignores: [ + 'node_modules/', + 'docs/', + 'dist/', + '.storybook/svelte-highlighting.js', + 'bin/css-to-js/', + 'bin/newComponent/', + '.svelte-kit/', + 'src/docs/guides/archieml.mdx', + ], + }, + ...svelte, + ...storybook.configs['flat/recommended'], + reactPlugin.configs.flat.recommended, + { + settings: { react: { version: '18.2' } }, + rules: { + 'react/prop-types': [ + 'error', + { + skipUndeclared: true, + }, + ], + }, + }, + { + ...mdx.flat, + processor: mdx.createRemarkProcessor({ + lintCodeBlocks: true, + }), + }, + { + ...mdx.flatCodeBlocks, + rules: { + ...mdx.flatCodeBlocks.rules, + 'no-undef': 'off', + '@typescript-eslint/no-unused-vars': 'off', + }, + }, +]; diff --git a/knip.config.ts b/knip.config.ts new file mode 100644 index 0000000..608cb86 --- /dev/null +++ b/knip.config.ts @@ -0,0 +1,14 @@ +import type { KnipConfig } from 'knip'; + +const config: KnipConfig = { + entry: ['src/index.js', 'src/**/*.stories.{svelte,mdx}', 'src/docs/**'], + project: [ + 'src/**/*.{mdx,js,jsx,ts,svelte}', + 'bin/**/*.{js,cjs}', + '.storybook/**/*.{js,ts,svelte}', + ], + ignore: ['**/*.d.ts'], + ignoreDependencies: [/@types\/.*/, 'chromatic', 'prop-types', 'postcss'], +}; + +export default config; diff --git a/package.json b/package.json new file mode 100644 index 0000000..8b01871 --- /dev/null +++ b/package.json @@ -0,0 +1,143 @@ +{ + "name": "@reuters-graphics/graphics-components", + "version": "3.2.1", + "type": "module", + "private": false, + "homepage": "https://reuters-graphics.github.io/graphics-components", + "repository": { + "type": "git", + "url": "git+https://github.com/reuters-graphics/graphics-components.git" + }, + "packageManager": "pnpm@9.13.2", + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, + "scripts": { + "start": "storybook dev -p 3000", + "lint": "eslint --fix", + "format": "prettier . --write", + "build": "rimraf ./dist && svelte-package -i ./src && publint", + "prepare": "svelte-package -i ./src", + "build:docs": "storybook build -o docs", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "changeset:version": "changeset version", + "changeset:publish": "git add --all && changeset publish", + "knip": "knip", + "test": "vitest" + }, + "license": "MIT", + "files": [ + "dist", + "!dist/**/*.stories.*", + "!dist/**/*.mdx", + "!dist/**/demo", + "!dist/docs", + "!dist/**/*.test.*", + "!dist/**/*.spec.*", + "!dist/**/*.mp4", + "!dist/**/*.mov", + "!dist/**/images" + ], + "engines": { + "node": ">=20.18" + }, + "peerDependencies": { + "svelte": "^5.0.0" + }, + "devDependencies": { + "@changesets/cli": "^2.29.2", + "@chromatic-com/storybook": "^3.2.6", + "@reuters-graphics/yaks-eslint": "^0.1.1", + "@reuters-graphics/yaks-prettier": "^0.1.1", + "@storybook/addon-a11y": "^8.6.12", + "@storybook/addon-essentials": "^8.6.12", + "@storybook/addon-interactions": "^8.6.12", + "@storybook/addon-svelte-csf": "5.0.0-next.28", + "@storybook/blocks": "^8.6.12", + "@storybook/components": "^8.6.12", + "@storybook/manager-api": "^8.6.12", + "@storybook/svelte": "^8.6.12", + "@storybook/sveltekit": "^8.6.12", + "@storybook/test": "^8.6.12", + "@storybook/theming": "^8.6.12", + "@sveltejs/package": "^2.3.11", + "@sveltejs/vite-plugin-svelte": "^5.0.3", + "@types/css": "^0.0.37", + "@types/eslint": "^9.6.1", + "@types/fs-extra": "^11.0.4", + "@types/google-publisher-tag": "^1.20250210.0", + "@types/gtag.js": "^0.0.12", + "@types/lodash-es": "^4.17.12", + "@types/mdx": "^2.0.13", + "@types/node": "^22.14.1", + "@types/prompts": "^2.4.9", + "@types/proper-url-join": "^2.1.5", + "@types/pym.js": "^1.3.2", + "@types/react": "^18.3.20", + "@types/react-syntax-highlighter": "^15.5.13", + "chromatic": "^11.28.2", + "css": "^3.0.0", + "css-color-converter": "^2.0.0", + "deep-object-diff": "^1.1.9", + "eslint": "^9.25.0", + "eslint-plugin-mdx": "^3.4.0", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-storybook": "^0.12.0", + "knip": "^5.50.5", + "mermaid": "^10.9.3", + "postcss": "^8.5.3", + "prettier": "^3.5.3", + "prettier-plugin-svelte": "^3.3.3", + "prism-themes": "^1.9.0", + "prop-types": "^15.8.1", + "publint": "^0.3.12", + "react": "^18.3.1", + "react-colorful": "^5.6.1", + "react-dom": "^18.3.1", + "react-syntax-highlighter": "^15.6.1", + "rimraf": "^6.0.1", + "sass": "^1.86.3", + "storybook": "^8.6.12", + "svelte": "^5.28.1", + "svelte-check": "^4.1.6", + "typescript": "^5.8.3", + "vite": "^6.3.2" + }, + "dependencies": { + "@fortawesome/free-regular-svg-icons": "^6.7.2", + "@fortawesome/free-solid-svg-icons": "^6.7.2", + "@lottiefiles/dotlottie-web": "^0.52.2", + "@reuters-graphics/svelte-markdown": "^0.0.3", + "@sveltejs/kit": "^2.0.0", + "@types/geojson": "^7946.0.16", + "dayjs": "^1.11.13", + "es-toolkit": "^1.35.0", + "journalize": "^2.6.0", + "maplibre-gl": "^5.15.0", + "mp4box": "^0.5.4", + "pmtiles": "^4.3.2", + "proper-url-join": "^2.1.2", + "pym.js": "^1.3.2", + "slugify": "^1.6.6", + "storybook-addon-rtl": "^1.1.0", + "svelte-fa": "^4.0.4", + "svelte-intersection-observer": "^1.0.0", + "ua-parser-js": "^2.0.3", + "vitest": "^3.2.4" + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "svelte": "./dist/index.js", + "default": "./dist/index.js" + }, + "./scss/*": "./dist/scss/*" + }, + "svelte": "./dist/index.js", + "types": "./dist/index.d.ts", + "bugs": { + "url": "https://github.com/reuters-graphics/graphics-components/issues" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..2ca4df7 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,9313 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@fortawesome/free-regular-svg-icons': + specifier: ^6.7.2 + version: 6.7.2 + '@fortawesome/free-solid-svg-icons': + specifier: ^6.7.2 + version: 6.7.2 + '@lottiefiles/dotlottie-web': + specifier: ^0.52.2 + version: 0.52.2 + '@reuters-graphics/svelte-markdown': + specifier: ^0.0.3 + version: 0.0.3(svelte@5.28.1) + '@sveltejs/kit': + specifier: ^2.0.0 + version: 2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + '@types/geojson': + specifier: ^7946.0.16 + version: 7946.0.16 + dayjs: + specifier: ^1.11.13 + version: 1.11.13 + es-toolkit: + specifier: ^1.35.0 + version: 1.35.0 + journalize: + specifier: ^2.6.0 + version: 2.6.0 + maplibre-gl: + specifier: ^5.15.0 + version: 5.15.0 + mp4box: + specifier: ^0.5.4 + version: 0.5.4 + pmtiles: + specifier: ^4.3.2 + version: 4.3.2 + proper-url-join: + specifier: ^2.1.2 + version: 2.1.2 + pym.js: + specifier: ^1.3.2 + version: 1.3.2 + slugify: + specifier: ^1.6.6 + version: 1.6.6 + storybook-addon-rtl: + specifier: ^1.1.0 + version: 1.1.0 + svelte-fa: + specifier: ^4.0.4 + version: 4.0.4(svelte@5.28.1) + svelte-intersection-observer: + specifier: ^1.0.0 + version: 1.0.0 + ua-parser-js: + specifier: ^2.0.3 + version: 2.0.3 + vitest: + specifier: ^3.2.4 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + devDependencies: + '@changesets/cli': + specifier: ^2.29.2 + version: 2.29.2 + '@chromatic-com/storybook': + specifier: ^3.2.6 + version: 3.2.6(react@18.3.1)(storybook@8.6.12(prettier@3.5.3)) + '@reuters-graphics/yaks-eslint': + specifier: ^0.1.1 + version: 0.1.1(@types/eslint@9.6.1)(eslint@9.25.0(jiti@2.4.2))(prettier@3.5.3)(svelte@5.28.1)(typescript@5.8.3) + '@reuters-graphics/yaks-prettier': + specifier: ^0.1.1 + version: 0.1.1(prettier@3.5.3)(svelte@5.28.1)(typescript@5.8.3) + '@storybook/addon-a11y': + specifier: ^8.6.12 + version: 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-essentials': + specifier: ^8.6.12 + version: 8.6.12(@types/react@18.3.20)(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-interactions': + specifier: ^8.6.12 + version: 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-svelte-csf': + specifier: 5.0.0-next.28 + version: 5.0.0-next.28(@storybook/svelte@8.6.12(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1))(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + '@storybook/blocks': + specifier: ^8.6.12 + version: 8.6.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.12(prettier@3.5.3)) + '@storybook/components': + specifier: ^8.6.12 + version: 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/manager-api': + specifier: ^8.6.12 + version: 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/svelte': + specifier: ^8.6.12 + version: 8.6.12(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1) + '@storybook/sveltekit': + specifier: ^8.6.12 + version: 8.6.12(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(postcss-load-config@3.1.4(postcss@8.5.3))(postcss@8.5.3)(sass@1.86.3)(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + '@storybook/test': + specifier: ^8.6.12 + version: 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/theming': + specifier: ^8.6.12 + version: 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@sveltejs/package': + specifier: ^2.3.11 + version: 2.3.11(svelte@5.28.1)(typescript@5.8.3) + '@sveltejs/vite-plugin-svelte': + specifier: ^5.0.3 + version: 5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + '@types/css': + specifier: ^0.0.37 + version: 0.0.37 + '@types/eslint': + specifier: ^9.6.1 + version: 9.6.1 + '@types/fs-extra': + specifier: ^11.0.4 + version: 11.0.4 + '@types/google-publisher-tag': + specifier: ^1.20250210.0 + version: 1.20250210.0 + '@types/gtag.js': + specifier: ^0.0.12 + version: 0.0.12 + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 + '@types/mdx': + specifier: ^2.0.13 + version: 2.0.13 + '@types/node': + specifier: ^22.14.1 + version: 22.14.1 + '@types/prompts': + specifier: ^2.4.9 + version: 2.4.9 + '@types/proper-url-join': + specifier: ^2.1.5 + version: 2.1.5 + '@types/pym.js': + specifier: ^1.3.2 + version: 1.3.2 + '@types/react': + specifier: ^18.3.20 + version: 18.3.20 + '@types/react-syntax-highlighter': + specifier: ^15.5.13 + version: 15.5.13 + chromatic: + specifier: ^11.28.2 + version: 11.28.2 + css: + specifier: ^3.0.0 + version: 3.0.0 + css-color-converter: + specifier: ^2.0.0 + version: 2.0.0 + deep-object-diff: + specifier: ^1.1.9 + version: 1.1.9 + eslint: + specifier: ^9.25.0 + version: 9.25.0(jiti@2.4.2) + eslint-plugin-mdx: + specifier: ^3.4.0 + version: 3.4.0(eslint@9.25.0(jiti@2.4.2)) + eslint-plugin-react: + specifier: ^7.37.5 + version: 7.37.5(eslint@9.25.0(jiti@2.4.2)) + eslint-plugin-storybook: + specifier: ^0.12.0 + version: 0.12.0(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + knip: + specifier: ^5.50.5 + version: 5.50.5(@types/node@22.14.1)(typescript@5.8.3) + mermaid: + specifier: ^10.9.3 + version: 10.9.3 + postcss: + specifier: ^8.5.3 + version: 8.5.3 + prettier: + specifier: ^3.5.3 + version: 3.5.3 + prettier-plugin-svelte: + specifier: ^3.3.3 + version: 3.3.3(prettier@3.5.3)(svelte@5.28.1) + prism-themes: + specifier: ^1.9.0 + version: 1.9.0 + prop-types: + specifier: ^15.8.1 + version: 15.8.1 + publint: + specifier: ^0.3.12 + version: 0.3.12 + react: + specifier: ^18.3.1 + version: 18.3.1 + react-colorful: + specifier: ^5.6.1 + version: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-dom: + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) + react-syntax-highlighter: + specifier: ^15.6.1 + version: 15.6.1(react@18.3.1) + rimraf: + specifier: ^6.0.1 + version: 6.0.1 + sass: + specifier: ^1.86.3 + version: 1.86.3 + storybook: + specifier: ^8.6.12 + version: 8.6.12(prettier@3.5.3) + svelte: + specifier: ^5.28.1 + version: 5.28.1 + svelte-check: + specifier: ^4.1.6 + version: 4.1.6(picomatch@4.0.2)(svelte@5.28.1)(typescript@5.8.3) + typescript: + specifier: ^5.8.3 + version: 5.8.3 + vite: + specifier: ^6.3.2 + version: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + +packages: + + '@adobe/css-tools@4.4.2': + resolution: {integrity: sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.27.0': + resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} + engines: {node: '>=6.9.0'} + + '@braintree/sanitize-url@6.0.4': + resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} + + '@changesets/apply-release-plan@7.0.12': + resolution: {integrity: sha512-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ==} + + '@changesets/assemble-release-plan@6.0.6': + resolution: {integrity: sha512-Frkj8hWJ1FRZiY3kzVCKzS0N5mMwWKwmv9vpam7vt8rZjLL1JMthdh6pSDVSPumHPshTTkKZ0VtNbE0cJHZZUg==} + + '@changesets/changelog-git@0.2.1': + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} + + '@changesets/cli@2.29.2': + resolution: {integrity: sha512-vwDemKjGYMOc0l6WUUTGqyAWH3AmueeyoJa1KmFRtCYiCoY5K3B68ErYpDB6H48T4lLI4czum4IEjh6ildxUeg==} + hasBin: true + + '@changesets/config@3.1.1': + resolution: {integrity: sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==} + + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + + '@changesets/get-dependents-graph@2.1.3': + resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} + + '@changesets/get-release-plan@4.0.10': + resolution: {integrity: sha512-CCJ/f3edYaA3MqoEnWvGGuZm0uMEMzNJ97z9hdUR34AOvajSwySwsIzC/bBu3+kuGDsB+cny4FljG8UBWAa7jg==} + + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + + '@changesets/git@3.0.4': + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} + + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} + + '@changesets/parse@0.4.1': + resolution: {integrity: sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==} + + '@changesets/pre@2.0.2': + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} + + '@changesets/read@0.6.5': + resolution: {integrity: sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==} + + '@changesets/should-skip-package@0.1.2': + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@6.1.0': + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} + + '@changesets/write@0.4.0': + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + + '@chromatic-com/storybook@3.2.6': + resolution: {integrity: sha512-FDmn5Ry2DzQdik+eq2sp/kJMMT36Ewe7ONXUXM2Izd97c7r6R/QyGli8eyh/F0iyqVvbLveNYFyF0dBOJNwLqw==} + engines: {node: '>=16.0.0', yarn: '>=1.22.18'} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@esbuild/aix-ppc64@0.25.2': + resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.2': + resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.2': + resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.2': + resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.2': + resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.2': + resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.2': + resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.2': + resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.2': + resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.2': + resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.2': + resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.2': + resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.2': + resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.2': + resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.2': + resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.2': + resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.2': + resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.2': + resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.2': + resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.2': + resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.2': + resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.2': + resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.2': + resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.2': + resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.2': + resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.6.1': + resolution: {integrity: sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.20.0': + resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.2.1': + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.13.0': + resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@1.4.1': + resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.25.0': + resolution: {integrity: sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.8': + resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@fortawesome/fontawesome-common-types@6.7.2': + resolution: {integrity: sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==} + engines: {node: '>=6'} + + '@fortawesome/free-regular-svg-icons@6.7.2': + resolution: {integrity: sha512-7Z/ur0gvCMW8G93dXIQOkQqHo2M5HLhYrRVC0//fakJXxcF1VmMPsxnG6Ee8qEylA8b8Q3peQXWMNZ62lYF28g==} + engines: {node: '>=6'} + + '@fortawesome/free-solid-svg-icons@6.7.2': + resolution: {integrity: sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==} + engines: {node: '>=6'} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/config-array@0.9.5': + resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} + engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@1.2.1': + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + deprecated: Use @eslint/object-schema instead + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.2': + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} + engines: {node: '>=18.18'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@lottiefiles/dotlottie-web@0.52.2': + resolution: {integrity: sha512-aeXCMUB5RdusHrvZ3Py2KaMgQ0w7SdA8NFbPK+SpwqC1UW1CDFZl5vPLueZHju7vLhB1rpPvpQ5fQ0L/KEZt7w==} + + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@mapbox/geojson-rewind@0.5.2': + resolution: {integrity: sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==} + hasBin: true + + '@mapbox/jsonlint-lines-primitives@2.0.2': + resolution: {integrity: sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==} + engines: {node: '>= 0.6'} + + '@mapbox/point-geometry@1.1.0': + resolution: {integrity: sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==} + + '@mapbox/tiny-sdf@2.0.7': + resolution: {integrity: sha512-25gQLQMcpivjOSA40g3gO6qgiFPDpWRoMfd+G/GoppPIeP6JDaMMkMrEJnMZhKyyS6iKwVt5YKu02vCUyJM3Ug==} + + '@mapbox/unitbezier@0.0.1': + resolution: {integrity: sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==} + + '@mapbox/vector-tile@2.0.4': + resolution: {integrity: sha512-AkOLcbgGTdXScosBWwmmD7cDlvOjkg/DetGva26pIRiZPdeJYjYKarIlb4uxVzi6bwHO6EWH82eZ5Nuv4T5DUg==} + + '@mapbox/whoots-js@3.1.0': + resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==} + engines: {node: '>=6.0.0'} + + '@maplibre/maplibre-gl-style-spec@24.4.1': + resolution: {integrity: sha512-UKhA4qv1h30XT768ccSv5NjNCX+dgfoq2qlLVmKejspPcSQTYD4SrVucgqegmYcKcmwf06wcNAa/kRd0NHWbUg==} + hasBin: true + + '@maplibre/mlt@1.1.2': + resolution: {integrity: sha512-SQKdJ909VGROkA6ovJgtHNs9YXV4YXUPS+VaZ50I2Mt951SLlUm2Cv34x5Xwc1HiFlsd3h2Yrs5cn7xzqBmENw==} + + '@maplibre/vt-pbf@4.2.0': + resolution: {integrity: sha512-bxrk/kQUwWXZgmqYgwOCnZCMONCRi3MJMqJdza4T3E4AeR5i+VyMnaJ8iDWtWxdfEAJRtrzIOeJtxZSy5mFrFA==} + + '@mdx-js/react@3.1.0': + resolution: {integrity: sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==} + peerDependencies: + '@types/react': '>=16' + react: '>=16' + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@npmcli/config@8.3.4': + resolution: {integrity: sha512-01rtHedemDNhUXdicU7s+QYz/3JyV5Naj84cvdXGH4mgCdL+agmSYaLF4LUG4vMCLzhBO8YtS0gPpH1FGvbgAw==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/git@5.0.8': + resolution: {integrity: sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/map-workspaces@3.0.6': + resolution: {integrity: sha512-tkYs0OYnzQm6iIRdfy+LcLBjcKuQCeE5YLb8KnrIlutJfheNaPvPpgoFEyEFgbjzl5PLZ3IA/BWAwRU0eHuQDA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/name-from-folder@2.0.0': + resolution: {integrity: sha512-pwK+BfEBZJbKdNYpHHRTNBwBoqrN/iIMO0AiGvYsp3Hoaq0WbgGSWQR6SCldZovoDpY3yje5lkFUe6gsDgJ2vg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/package-json@5.2.1': + resolution: {integrity: sha512-f7zYC6kQautXHvNbLEWgD/uGu1+xCn9izgqBfgItWSx22U0ZDekxN08A1vM8cTxj/cRVe0Q94Ode+tdoYmIOOQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@npmcli/promise-spawn@7.0.2': + resolution: {integrity: sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==} + engines: {node: ^16.14.0 || >=18.0.0} + + '@parcel/watcher-android-arm64@2.5.1': + resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.1': + resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-win32-arm64@2.5.1': + resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.1': + resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.1': + resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.1': + resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} + engines: {node: '>= 10.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.2.4': + resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@publint/pack@0.1.2': + resolution: {integrity: sha512-S+9ANAvUmjutrshV4jZjaiG8XQyuJIZ8a4utWmN/vW1sgQ9IfBnPndwkmQYw53QmouOIytT874u65HEmu6H5jw==} + engines: {node: '>=18'} + + '@reuters-graphics/svelte-markdown@0.0.3': + resolution: {integrity: sha512-K3DWKjm1XZxnwua+Vz9c7BRFrkFVWpVU+DnMKBPu3eadhCpT09Z0y+1MhJgs/573h4BpraZFuUVCl1h4XUxd1Q==} + peerDependencies: + svelte: ^5.0.0 + + '@reuters-graphics/yaks-eslint@0.1.1': + resolution: {integrity: sha512-cECaoVOAR/nMZPfT7lLY/WvcBjY7rlvSKD59QhpV3Yq2mSmoBwMDHAugjp1ndcQBRt9r/pM7aGL1iZouz4CxVQ==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^9.21.0 + svelte: '>5.2.18' + typescript: '>5.7.0' + + '@reuters-graphics/yaks-prettier@0.1.1': + resolution: {integrity: sha512-uJd3+ze1JpH8syuK37YshoVek7UHjsI9y2XlydKd8LkHmer4wfEehiaaXl1/1K8cE/FF5YJSaB6KQAvoqenXww==} + engines: {node: '>=18'} + peerDependencies: + prettier: ^3.5.2 + typescript: '>5.7.0' + + '@rollup/rollup-android-arm-eabi@4.40.0': + resolution: {integrity: sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.40.0': + resolution: {integrity: sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.40.0': + resolution: {integrity: sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.40.0': + resolution: {integrity: sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.40.0': + resolution: {integrity: sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.40.0': + resolution: {integrity: sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.40.0': + resolution: {integrity: sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.40.0': + resolution: {integrity: sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.40.0': + resolution: {integrity: sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.40.0': + resolution: {integrity: sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.40.0': + resolution: {integrity: sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': + resolution: {integrity: sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.40.0': + resolution: {integrity: sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.40.0': + resolution: {integrity: sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.40.0': + resolution: {integrity: sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.40.0': + resolution: {integrity: sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.40.0': + resolution: {integrity: sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.40.0': + resolution: {integrity: sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.40.0': + resolution: {integrity: sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.40.0': + resolution: {integrity: sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==} + cpu: [x64] + os: [win32] + + '@storybook/addon-a11y@8.6.12': + resolution: {integrity: sha512-H28zHiL8uuv29XsVNf9VjNWsCeht/l66GPYHT7aom1jh+f3fS9+sutrCGEBC/T7cnRpy8ZyuHCtihUqS+RI4pg==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-actions@8.6.12': + resolution: {integrity: sha512-B5kfiRvi35oJ0NIo53CGH66H471A3XTzrfaa6SxXEJsgxxSeKScG5YeXcCvLiZfvANRQ7QDsmzPUgg0o3hdMXw==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-backgrounds@8.6.12': + resolution: {integrity: sha512-lmIAma9BiiCTbJ8YfdZkXjpnAIrOUcgboLkt1f6XJ78vNEMnLNzD9gnh7Tssz1qrqvm34v9daDjIb+ggdiKp3Q==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-controls@8.6.12': + resolution: {integrity: sha512-9VSRPJWQVb9wLp21uvpxDGNctYptyUX0gbvxIWOHMH3R2DslSoq41lsC/oQ4l4zSHVdL+nq8sCTkhBxIsjKqdQ==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-docs@8.6.12': + resolution: {integrity: sha512-kEezQjAf/p3SpDzLABgg4fbT48B6dkT2LiZCKTRmCrJVtuReaAr4R9MMM6Jsph6XjbIj/SvOWf3CMeOPXOs9sg==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-essentials@8.6.12': + resolution: {integrity: sha512-Y/7e8KFlttaNfv7q2zoHMPdX6hPXHdsuQMAjYl5NG9HOAJREu4XBy4KZpbcozRe4ApZ78rYsN/MO1EuA+bNMIA==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-highlight@8.6.12': + resolution: {integrity: sha512-9FITVxdoycZ+eXuAZL9ElWyML/0fPPn9UgnnAkrU7zkMi+Segq/Tx7y+WWanC5zfWZrXAuG6WTOYEXeWQdm//w==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-interactions@8.6.12': + resolution: {integrity: sha512-cTAJlTq6uVZBEbtwdXkXoPQ4jHOAGKQnYSezBT4pfNkdjn/FnEeaQhMBDzf14h2wr5OgBnJa6Lmd8LD9ficz4A==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-measure@8.6.12': + resolution: {integrity: sha512-tACmwqqOvutaQSduw8SMb62wICaT1rWaHtMN3vtWXuxgDPSdJQxLP+wdVyRYMAgpxhLyIO7YRf++Hfha9RHgFg==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-outline@8.6.12': + resolution: {integrity: sha512-1ylwm+n1s40S91No0v9T4tCjZORu3GbnjINlyjYTDLLhQHyBQd3nWR1Y1eewU4xH4cW9SnSLcMQFS/82xHqU6A==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-svelte-csf@5.0.0-next.28': + resolution: {integrity: sha512-Ojj6m8xEd3rlVP7PkNYv/0st4M0NZdSYWwnCowhsw3ItBasmyB8jmP5Ht2WmwH+EIUYq0mMfsRI7Rb6Yl63QbQ==} + peerDependencies: + '@storybook/svelte': ^0.0.0-0 || ^8.2.0 || ^9.0.0-0 + '@sveltejs/vite-plugin-svelte': ^4.0.0 || ^5.0.0 + storybook: ^0.0.0-0 || ^8.2.0 || ^9.0.0-0 + svelte: ^5.0.0 + vite: ^5.0.0 || ^6.0.0 + + '@storybook/addon-toolbars@8.6.12': + resolution: {integrity: sha512-HEcSzo1DyFtIu5/ikVOmh5h85C1IvK9iFKSzBR6ice33zBOaehVJK+Z5f487MOXxPsZ63uvWUytwPyViGInj+g==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/addon-viewport@8.6.12': + resolution: {integrity: sha512-EXK2LArAnABsPP0leJKy78L/lbMWow+EIJfytEP5fHaW4EhMR6h7Hzaqzre6U0IMMr/jVFa1ci+m0PJ0eQc2bw==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/blocks@8.6.12': + resolution: {integrity: sha512-DohlTq6HM1jDbHYiXL4ZvZ00VkhpUp5uftzj/CZDLY1fYHRjqtaTwWm2/OpceivMA8zDitLcq5atEZN+f+siTg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^8.6.12 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + + '@storybook/builder-vite@8.6.12': + resolution: {integrity: sha512-Gju21ud/3Qw4v2vLNaa5SuJECsI9ICNRr2G0UyCCzRvCHg8jpA9lDReu2NqhLDyFIuDG+ZYT38gcaHEUoNQ8KQ==} + peerDependencies: + storybook: ^8.6.12 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + + '@storybook/components@8.6.12': + resolution: {integrity: sha512-FiaE8xvCdvKC2arYusgtlDNZ77b8ysr8njAYQZwwaIHjy27TbR2tEpLDCmUwSbANNmivtc/xGEiDDwcNppMWlQ==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@storybook/core@8.6.12': + resolution: {integrity: sha512-t+ZuDzAlsXKa6tLxNZT81gEAt4GNwsKP/Id2wluhmUWD/lwYW0uum1JiPUuanw8xD6TdakCW/7ULZc7aQUBLCQ==} + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + + '@storybook/csf-plugin@8.6.12': + resolution: {integrity: sha512-6s8CnP1aoKPb3XtC0jRLUp8M5vTA8RhGAwQDKUsFpCC7g89JR9CaKs9FY2ZSzsNbjR15uASi7b3K8BzeYumYQg==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/csf@0.1.12': + resolution: {integrity: sha512-9/exVhabisyIVL0VxTCxo01Tdm8wefIXKXfltAPTSr8cbLn5JAxGQ6QV3mjdecLGEOucfoVhAKtJfVHxEK1iqw==} + + '@storybook/csf@0.1.13': + resolution: {integrity: sha512-7xOOwCLGB3ebM87eemep89MYRFTko+D8qE7EdAAq74lgdqRR5cOUtYWJLjO2dLtP94nqoOdHJo6MdLLKzg412Q==} + + '@storybook/global@5.0.0': + resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} + + '@storybook/icons@1.4.0': + resolution: {integrity: sha512-Td73IeJxOyalzvjQL+JXx72jlIYHgs+REaHiREOqfpo3A2AYYG71AUbcv+lg7mEDIweKVCxsMQ0UKo634c8XeA==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + + '@storybook/instrumenter@8.6.12': + resolution: {integrity: sha512-VK5fYAF8jMwWP/u3YsmSwKGh+FeSY8WZn78flzRUwirp2Eg1WWjsqPRubAk7yTpcqcC/km9YMF3KbqfzRv2s/A==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/manager-api@8.6.12': + resolution: {integrity: sha512-O0SpISeJLNTQvhSBOsWzzkCgs8vCjOq1578rwqHlC6jWWm4QmtfdyXqnv7rR1Hk08kQ+Dzqh0uhwHx0nfwy4nQ==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@storybook/preview-api@8.6.12': + resolution: {integrity: sha512-84FE3Hrs0AYKHqpDZOwx1S/ffOfxBdL65lhCoeI8GoWwCkzwa9zEP3kvXBo/BnEDO7nAfxvMhjASTZXbKRJh5Q==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@storybook/react-dom-shim@8.6.12': + resolution: {integrity: sha512-51QvoimkBzYs8s3rCYnY5h0cFqLz/Mh0vRcughwYaXckWzDBV8l67WBO5Xf5nBsukCbWyqBVPpEQLww8s7mrLA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.6.12 + + '@storybook/svelte-vite@8.6.12': + resolution: {integrity: sha512-E9UNwc+4eAXDBOtR98Am1164L3w+JOielRipgmGNGvFD2xfuWzTmE6feERQimbGGcEnM5ImeYA0t2nLE9dCZ0g==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + storybook: ^8.6.12 + svelte: ^4.0.0 || ^5.0.0 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + + '@storybook/svelte@8.6.12': + resolution: {integrity: sha512-74g07+mUq9Cfm9XStP/jLf1wqOgirPnj4WM0BOHMFolSjUwG58LIsAniB7O5PH7we0tf1+Qvj6Cjws2qUiB9/A==} + engines: {node: '>=18.0.0'} + peerDependencies: + storybook: ^8.6.12 + svelte: ^4.0.0 || ^5.0.0 + + '@storybook/sveltekit@8.6.12': + resolution: {integrity: sha512-QdHDmz3h+CyysvH+/Fmg7mqE5agQWz4pwlzwpuLt/rgOf3lBXCyc3lllPu8osnrG2F4V7z6MIYkoeBkZxIyU7Q==} + engines: {node: '>=18.0.0'} + peerDependencies: + storybook: ^8.6.12 + svelte: ^4.0.0 || ^5.0.0 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + + '@storybook/test@8.6.12': + resolution: {integrity: sha512-0BK1Eg+VD0lNMB1BtxqHE3tP9FdkUmohtvWG7cq6lWvMrbCmAmh3VWai3RMCCDOukPFpjabOr8BBRLVvhNpv2w==} + peerDependencies: + storybook: ^8.6.12 + + '@storybook/theming@8.6.12': + resolution: {integrity: sha512-6VjZg8HJ2Op7+KV7ihJpYrDnFtd9D1jrQnUS8LckcpuBXrIEbaut5+34ObY8ssQnSqkk2GwIZBBBQYQBCVvkOw==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@sveltejs/acorn-typescript@1.0.5': + resolution: {integrity: sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==} + peerDependencies: + acorn: ^8.9.0 + + '@sveltejs/kit@2.20.7': + resolution: {integrity: sha512-dVbLMubpJJSLI4OYB+yWYNHGAhgc2bVevWuBjDj8jFUXIJOAnLwYP3vsmtcgoxNGUXoq0rHS5f7MFCsryb6nzg==} + engines: {node: '>=18.13'} + hasBin: true + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.3 || ^6.0.0 + + '@sveltejs/package@2.3.11': + resolution: {integrity: sha512-DSMt2U0XNAdoQBYksrmgQi5dKy7jUTVDJLiagS/iXF7AShjAmTbGJQKruBuT/FfYAWvNxfQTSjkXU8eAIjVeNg==} + engines: {node: ^16.14 || >=18} + hasBin: true + peerDependencies: + svelte: ^3.44.0 || ^4.0.0 || ^5.0.0-next.1 + + '@sveltejs/vite-plugin-svelte-inspector@4.0.1': + resolution: {integrity: sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^5.0.0 + svelte: ^5.0.0 + vite: ^6.0.0 + + '@sveltejs/vite-plugin-svelte@5.0.3': + resolution: {integrity: sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22} + peerDependencies: + svelte: ^5.0.0 + vite: ^6.0.0 + + '@testing-library/dom@10.4.0': + resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.5.0': + resolution: {integrity: sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/user-event@14.5.2': + resolution: {integrity: sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/chai@5.2.2': + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + + '@types/concat-stream@2.0.3': + resolution: {integrity: sha512-3qe4oQAPNwVNwK4C9c8u+VJqv9kez+2MR4qJpoPFfXtgxxif1QbFusvXzK0/Wra2VX07smostI2VMmJNSpZjuQ==} + + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + + '@types/css@0.0.37': + resolution: {integrity: sha512-IVhWCNH1mw3VRjkOMHsxVAcnANhee9w//TX1fqmALP628Dzf6VMG1LRnOngpptnrilcWCkmcY1tj6QkKGUy0CA==} + + '@types/d3-scale-chromatic@3.1.0': + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} + + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} + + '@types/d3-time@3.0.4': + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + + '@types/geojson-vt@3.2.5': + resolution: {integrity: sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==} + + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + + '@types/google-publisher-tag@1.20250210.0': + resolution: {integrity: sha512-VAGJPSphhIYubiqyZwmZI1bzVDxAveiJJj8EEBo1RDXlOmozsrQg6ZzBRqbzm8HG8pTKQeX42qbu0P84aFhiaQ==} + + '@types/gtag.js@0.0.12': + resolution: {integrity: sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==} + + '@types/hast@2.3.10': + resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/is-empty@1.2.3': + resolution: {integrity: sha512-4J1l5d79hoIvsrKh5VUKVRA1aIdsOb10Hu5j3J2VfP/msDnfTdGPmNp2E1Wg+vs97Bktzo+MZePFFXSGoykYJw==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.16': + resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} + + '@types/mdast@3.0.15': + resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/node-fetch@2.6.12': + resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} + + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + + '@types/node@22.14.1': + resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==} + + '@types/prompts@2.4.9': + resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==} + + '@types/prop-types@15.7.14': + resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} + + '@types/proper-url-join@2.1.5': + resolution: {integrity: sha512-jPPpj0tQFl5mL6BVwlUCqJXXTjel5zig+AQgIYjERwm2rdS04y6cxQsVndmWPaz1Cv+DDGtxtYzvhSLmp/eYEw==} + + '@types/pug@2.0.10': + resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} + + '@types/pym.js@1.3.2': + resolution: {integrity: sha512-VOW0zLYOoBA2XTUN4W7wONN8nVe0Ir7zbJi7UzvHwAX2728tw6ggfM2Cz4D8HnGQLbRHn8Qf0WrGQNsLQxqIKQ==} + + '@types/react-syntax-highlighter@15.5.13': + resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==} + + '@types/react@18.3.20': + resolution: {integrity: sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==} + + '@types/supercluster@7.1.3': + resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==} + + '@types/supports-color@8.1.3': + resolution: {integrity: sha512-Hy6UMpxhE3j1tLpl27exp1XqHD7n8chAiNPzWfz16LPZoMMoSc4dzLl6w9qijkEb/r5O1ozdu1CWGA2L83ZeZg==} + + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/uuid@9.0.8': + resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} + + '@typescript-eslint/eslint-plugin@8.30.1': + resolution: {integrity: sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/parser@8.30.1': + resolution: {integrity: sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/scope-manager@8.30.1': + resolution: {integrity: sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.30.1': + resolution: {integrity: sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/types@8.30.1': + resolution: {integrity: sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.30.1': + resolution: {integrity: sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/utils@8.30.1': + resolution: {integrity: sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/visitor-keys@8.30.1': + resolution: {integrity: sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitest/expect@2.0.5': + resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==} + + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@2.0.5': + resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==} + + '@vitest/pretty-format@2.1.9': + resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==} + + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + + '@vitest/spy@2.0.5': + resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==} + + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + + '@vitest/utils@2.0.5': + resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==} + + '@vitest/utils@2.1.9': + resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + + abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axe-core@4.10.3: + resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} + engines: {node: '>=4'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + better-opn@3.0.2: + resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} + engines: {node: '>=12.0.0'} + + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browser-assert@1.2.1: + resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==} + + buffer-crc32@1.0.0: + resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} + engines: {node: '>=8.0.0'} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} + + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@1.1.4: + resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@1.2.4: + resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + character-reference-invalid@1.1.4: + resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} + + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chromatic@11.28.2: + resolution: {integrity: sha512-aCmUPcZUs4/p9zRZdMreOoO/5JqO2DiJC3md1/vRx8dlMRcmR/YI5ZbgXZcai2absVR+6hsXZ5XiPxV2sboTuQ==} + hasBin: true + peerDependencies: + '@chromatic-com/cypress': ^0.*.* || ^1.0.0 + '@chromatic-com/playwright': ^0.*.* || ^1.0.0 + peerDependenciesMeta: + '@chromatic-com/cypress': + optional: true + '@chromatic-com/playwright': + optional: true + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + ci-info@4.2.0: + resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} + engines: {node: '>=8'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@0.5.3: + resolution: {integrity: sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + comma-separated-tokens@1.0.8: + resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + concat-stream@2.0.0: + resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} + engines: {'0': node >= 6.0} + + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + + cose-base@1.0.3: + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-color-converter@2.0.0: + resolution: {integrity: sha512-oLIG2soZz3wcC3aAl/7Us5RS8Hvvc6I8G8LniF/qfMmrm7fIKQ8RIDDRZeKyGL2SrWfNqYspuLShbnjBMVWm8g==} + + css-unit-converter@1.1.2: + resolution: {integrity: sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==} + + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + + css@3.0.0: + resolution: {integrity: sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + cytoscape-cose-bilkent@4.1.0: + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape@3.31.2: + resolution: {integrity: sha512-/eOXg2uGdMdpGlEes5Sf6zE+jUG+05f3htFNQIxLxduOH/SsaUZiPBfAwP1btVIVzsnhiNOdi+hvDRLYfMZjGw==} + engines: {node: '>=0.10'} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + + d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + + d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + + d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-format@3.1.0: + resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + engines: {node: '>=12'} + + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@1.0.9: + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + + d3-sankey@0.12.3: + resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-shape@1.3.7: + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + + dagre-d3-es@7.0.10: + resolution: {integrity: sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.1.0: + resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==} + + decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + + dedent-js@1.0.1: + resolution: {integrity: sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==} + + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deep-object-diff@1.1.9: + resolution: {integrity: sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delaunator@5.0.1: + resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-europe-js@0.1.2: + resolution: {integrity: sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow==} + + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + devalue@5.1.1: + resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@3.3.0: + resolution: {integrity: sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==} + engines: {node: '>= 4'} + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + dompurify@3.1.6: + resolution: {integrity: sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + earcut@3.0.2: + resolution: {integrity: sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + easy-table@1.2.0: + resolution: {integrity: sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==} + + elkjs@0.9.3: + resolution: {integrity: sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==} + + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + es-abstract@1.23.9: + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.2.1: + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + es-toolkit@1.35.0: + resolution: {integrity: sha512-kVHyrRoC0eLc1hWJ6npG8nNFtOG+nWfcMI+XE0RaFO0gxd6Ions8r0O/U64QyZgY7IeidUnS5oZlRZYUgMGCAg==} + + es6-promise@3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + + esbuild@0.25.2: + resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} + engines: {node: '>=18'} + hasBin: true + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-prettier@10.1.2: + resolution: {integrity: sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-mdx@3.4.0: + resolution: {integrity: sha512-sNffDEvt3fAEkrCntX0Kk/IWhHkfp0fhQ7/n30gQuIRm/FeUjLMkKkgAwlOFqxIMD4XJ03Iidmkf18EC8zTyYw==} + engines: {node: '>=18.0.0'} + peerDependencies: + eslint: '>=8.0.0' + remark-lint-file-extension: '*' + peerDependenciesMeta: + remark-lint-file-extension: + optional: true + + eslint-plugin-mdx@3.4.0: + resolution: {integrity: sha512-f/ot8rSp/telkW1joqe0y9XQigTrE99sQHqyqLYYVgGLtQvl54suDidepbiGsDF7Z5V9uyQPWpmY0Qu/ZMRzmg==} + engines: {node: '>=18.0.0'} + peerDependencies: + eslint: '>=8.0.0' + + eslint-plugin-prettier@5.2.6: + resolution: {integrity: sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-plugin-storybook@0.12.0: + resolution: {integrity: sha512-Lg5I0+npTgiYgZ4KSvGWGDFZi3eOCNJPaWX0c9rTEEXC5wvooOClsP9ZtbI4hhFKyKgYR877KiJxbRTSJq9gWA==} + engines: {node: '>= 18'} + peerDependencies: + eslint: '>=8' + + eslint-plugin-svelte@3.5.1: + resolution: {integrity: sha512-Qn1slddZHfqYiDO6IN8/iN3YL+VuHlgYjm30FT+hh0Jf/TX0jeZMTJXQMajFm5f6f6hURi+XO8P+NPYD+T4jkg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.1 || ^9.0.0 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + svelte: + optional: true + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-utils@3.0.0: + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + + eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@8.4.1: + resolution: {integrity: sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. + hasBin: true + + eslint@9.25.0: + resolution: {integrity: sha512-MsBdObhM4cEwkzCiraDv7A6txFXEqtNXOb877TsSp2FCkBNl8JfVQrmiuDqC1IkejT6JLPzYBXx/xAiYhyzgGA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@9.2.0: + resolution: {integrity: sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrap@1.2.2: + resolution: {integrity: sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==} + + esrap@1.4.6: + resolution: {integrity: sha512-F/D2mADJ9SHY3IwksD4DAXjTt7qt7GWUf3/8RhCNWmC/67tyb55dpimHmy7EplakFaflV0R/PC+fdSPqrRHAQw==} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + expect-type@1.2.2: + resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} + engines: {node: '>=12.0.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fault@1.0.4: + resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==} + + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fdir@6.4.6: + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + filesize@10.1.6: + resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} + engines: {node: '>= 10.4.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + filter-obj@1.1.0: + resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} + engines: {node: '>=0.10.0'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + + format@0.2.2: + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} + engines: {node: '>=0.4.x'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functional-red-black-tree@1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + geojson-vt@4.0.2: + resolution: {integrity: sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + gl-matrix@3.4.4: + resolution: {integrity: sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@11.0.1: + resolution: {integrity: sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==} + engines: {node: 20 || >=22} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.0.0: + resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hast-util-parse-selector@2.2.5: + resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==} + + hastscript@6.0.0: + resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==} + + highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + + highlightjs-vue@1.0.0: + resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==} + + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} + + htmlparser2-svelte@4.1.0: + resolution: {integrity: sha512-+4f4RBFz7Rj2Hp0ZbFbXC+Kzbd6S9PgjiuFtdT76VMNgKogrEZy0pG2UrPycPbrZzVEIM5lAT3lAdkSTCHLPjg==} + + human-id@4.1.1: + resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==} + hasBin: true + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ignore@4.0.6: + resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} + engines: {node: '>= 4'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@6.0.2: + resolution: {integrity: sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==} + engines: {node: '>= 4'} + + immutable@5.1.1: + resolution: {integrity: sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@4.1.3: + resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + + is-alphabetical@1.0.4: + resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} + + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@1.0.4: + resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-decimal@1.0.4: + resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} + + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-empty@1.2.0: + resolution: {integrity: sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-hexadecimal@1.0.4: + resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} + + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-standalone-pwa@0.1.1: + resolution: {integrity: sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g==} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isexe@3.1.1: + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} + + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jackspeak@4.1.0: + resolution: {integrity: sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==} + engines: {node: 20 || >=22} + + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} + hasBin: true + + journalize@2.6.0: + resolution: {integrity: sha512-9Fi36vKj8MRtmqThQf8AK0GnTc1IYKCftyqwJA61dKNnkH82we2qqIPYDl1UX6farfQMCZBEV96OoEkDDQVY8g==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsdoc-type-pratt-parser@4.1.0: + resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} + engines: {node: '>=12.0.0'} + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json-stringify-pretty-compact@4.0.0: + resolution: {integrity: sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + katex@0.16.22: + resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==} + hasBin: true + + kdbush@4.0.2: + resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + khroma@2.1.0: + resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + knip@5.50.5: + resolution: {integrity: sha512-I3mfebuG5x8i/mJJA41xjnmHMbLw75ymbDxlS7HMP+4CjY+jXEDSJyP3A2xmI5JF5/o47Fr8D7Pq3BVT0/nQPw==} + engines: {node: '>=18.18.0'} + hasBin: true + peerDependencies: + '@types/node': '>=18' + typescript: '>=5.0.4' + + known-css-properties@0.35.0: + resolution: {integrity: sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==} + + layout-base@1.0.2: + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lines-and-columns@2.0.4: + resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + load-plugin@6.0.3: + resolution: {integrity: sha512-kc0X2FEUZr145odl68frm+lMJuQ23+rTXYmR6TImqPtbpmXC4vVXbWKDQ9IzndA0HfyQamWfKLhzsqGSTxE63w==} + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + + loupe@3.2.0: + resolution: {integrity: sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lowlight@1.20.0: + resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.1.0: + resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} + engines: {node: 20 || >=22} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + map-or-similar@1.5.0: + resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} + + maplibre-gl@5.15.0: + resolution: {integrity: sha512-pPeu/t4yPDX/+Uf9ibLUdmaKbNMlGxMAX+tBednYukol2qNk2TZXAlhdohWxjVvTO3is8crrUYv3Ok02oAaKzA==} + engines: {node: '>=16.14.0', npm: '>=8.1.0'} + + marked-smartypants@1.1.9: + resolution: {integrity: sha512-VPeuaUr5IWptI7nJdgQ9ugrLWYGv13NdzEXTtKY3cmB4aRWOI2RzhLlf+xQp6Wnob9SAPO2sNVlfSJr+nflk/A==} + peerDependencies: + marked: '>=4 <16' + + marked@15.0.8: + resolution: {integrity: sha512-rli4l2LyZqpQuRve5C0rkn6pj3hT8EWPC+zkAxFTAJLxRbENfTAhEQq9itrmf1Y81QtAX5D/MYlGlIomNgj9lA==} + engines: {node: '>= 18'} + hasBin: true + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdast-util-from-markdown@1.3.1: + resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==} + + mdast-util-from-markdown@2.0.2: + resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} + + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} + + mdast-util-mdx-jsx@3.2.0: + resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} + + mdast-util-mdx@3.0.0: + resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} + + mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@3.2.0: + resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + memoizerific@1.11.3: + resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + mermaid@10.9.3: + resolution: {integrity: sha512-V80X1isSEvAewIL3xhmz/rVmc27CVljcsbWxkxlWJWY/1kQa4XOABqpDl2qQLGKzpKm6WbTfUEKImBlUfFYArw==} + + micromark-core-commonmark@1.1.0: + resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==} + + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + + micromark-extension-mdx-expression@3.0.1: + resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==} + + micromark-extension-mdx-jsx@3.0.2: + resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==} + + micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + + micromark-extension-mdxjs-esm@3.0.0: + resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} + + micromark-extension-mdxjs@3.0.0: + resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} + + micromark-factory-destination@1.1.0: + resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@1.1.0: + resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-mdx-expression@2.0.3: + resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==} + + micromark-factory-space@1.1.0: + resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@1.1.0: + resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@1.1.0: + resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@1.2.0: + resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@1.1.0: + resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@1.1.0: + resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@1.1.0: + resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@1.1.0: + resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@1.1.0: + resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@1.1.0: + resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-events-to-acorn@2.0.3: + resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==} + + micromark-util-html-tag-name@1.2.0: + resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@1.1.0: + resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@1.1.0: + resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@1.2.0: + resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@1.1.0: + resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@1.1.0: + resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@1.1.0: + resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromark@3.2.0: + resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} + + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mp4box@0.5.4: + resolution: {integrity: sha512-GcCH0fySxBurJtvr0dfhz0IxHZjc1RP+F+I8xw+LIwkU1a+7HJx8NCDiww1I5u4Hz6g4eR1JlGADEGJ9r4lSfA==} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + murmurhash-js@1.0.0: + resolution: {integrity: sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + non-layered-tidy-tree-layout@2.0.2: + resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} + + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + normalize-package-data@6.0.2: + resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} + engines: {node: ^16.14.0 || >=18.0.0} + + npm-install-checks@6.3.0: + resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-normalize-package-bin@3.0.1: + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-package-arg@11.0.3: + resolution: {integrity: sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==} + engines: {node: ^16.14.0 || >=18.0.0} + + npm-pick-manifest@9.1.0: + resolution: {integrity: sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==} + engines: {node: ^16.14.0 || >=18.0.0} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-manager-detector@0.2.11: + resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} + + package-manager-detector@1.2.0: + resolution: {integrity: sha512-PutJepsOtsqVfUsxCzgTTpyXmiAgvKptIgY4th5eq5UXXFhj5PxfQ9hnGkypMeovpAvVshFRItoFHYO18TCOqA==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-entities@2.0.0: + resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} + + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + + parse-json@7.1.1: + resolution: {integrity: sha512-SgOTCX/EZXtZxBE5eJ97P4yGM5n37BwRU+YMsH4vNzFqJV/oWFXXCmwFlgWUM4PrakybVOueJJ6pwHqSVhTFDw==} + engines: {node: '>=16'} + + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + + parse5@7.2.1: + resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + pbf@4.0.1: + resolution: {integrity: sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==} + hasBin: true + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pmtiles@4.3.2: + resolution: {integrity: sha512-Ath2F2U2E37QyNXjN1HOF+oLiNIbdrDYrk/K3C9K4Pgw2anwQX10y4WYWEH9O75vPiu0gBbSWIAbSG19svyvZg==} + + polished@4.3.1: + resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} + engines: {node: '>=10'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-load-config@3.1.4: + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-safe-parser@7.0.1: + resolution: {integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==} + engines: {node: '>=18.0'} + peerDependencies: + postcss: ^8.4.31 + + postcss-scss@4.0.9: + resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.29 + + postcss-selector-parser@7.1.0: + resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + engines: {node: '>=4'} + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + + potpack@2.1.0: + resolution: {integrity: sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier-plugin-svelte@3.3.3: + resolution: {integrity: sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==} + peerDependencies: + prettier: ^3.0.0 + svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + pretty-ms@9.2.0: + resolution: {integrity: sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==} + engines: {node: '>=18'} + + prism-themes@1.9.0: + resolution: {integrity: sha512-tX2AYsehKDw1EORwBps+WhBFKc2kxfoFpQAjxBndbZKr4fRmMkv47XN0BghC/K1qwodB1otbe4oF23vUTFDokw==} + + prismjs@1.27.0: + resolution: {integrity: sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==} + engines: {node: '>=6'} + + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + proc-log@4.2.0: + resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + proper-url-join@2.1.2: + resolution: {integrity: sha512-wp0MVpPYbQhwxRFjFkhWwHUoH5PyAA0SCVUpwRxjc9JzSzddPB4GDhu5I+eCYhdpG0S7jvVubsLPEi4pFd77rg==} + + property-information@5.6.0: + resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==} + + protocol-buffers-schema@3.6.0: + resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} + + publint@0.3.12: + resolution: {integrity: sha512-1w3MMtL9iotBjm1mmXtG3Nk06wnq9UhGNRpQ2j6n1Zq7YAD6gnxMMZMIxlRPAydVjVbjSm+n0lhwqsD1m4LD5w==} + engines: {node: '>=18'} + hasBin: true + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pym.js@1.3.2: + resolution: {integrity: sha512-/fFzHFB4BTsJQP5id0wzUdYsDT4VPkfAxk+uENBE9/aP6YbvhAEpcuJHdjxqisqfXOCrcz7duTK1fbtF2rz8RQ==} + + quansync@0.2.10: + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} + + query-string@7.1.3: + resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} + engines: {node: '>=6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quickselect@3.0.0: + resolution: {integrity: sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==} + + react-colorful@5.6.1: + resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + react-confetti@6.4.0: + resolution: {integrity: sha512-5MdGUcqxrTU26I2EU7ltkWPwxvucQTuqMm8dUz72z2YMqTD6s9vMcDUysk7n9jnC+lXuCPeJJ7Knf98VEYE9Rg==} + engines: {node: '>=16'} + peerDependencies: + react: ^16.3.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 + + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react-syntax-highlighter@15.6.1: + resolution: {integrity: sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg==} + peerDependencies: + react: '>= 0.14.0' + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + + read-package-json-fast@3.0.2: + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + refractor@3.6.0: + resolution: {integrity: sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + regexpp@3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + + remark-mdx@3.1.0: + resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-protobuf-schema@2.1.0: + resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} + + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true + + robust-predicates@3.0.2: + resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + + rollup@4.40.0: + resolution: {integrity: sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sander@0.5.1: + resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} + + sass@1.86.3: + resolution: {integrity: sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==} + engines: {node: '>=14.0.0'} + hasBin: true + + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + set-cookie-parser@2.7.1: + resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sirv@3.0.1: + resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} + engines: {node: '>=18'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slugify@1.6.6: + resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==} + engines: {node: '>=8.0.0'} + + smartypants@0.2.2: + resolution: {integrity: sha512-TzobUYoEft/xBtb2voRPryAUIvYguG0V7Tt3de79I1WfXgCwelqVsGuZSnu3GFGRZhXR90AeEYIM+icuB/S06Q==} + hasBin: true + + smol-toml@1.3.3: + resolution: {integrity: sha512-KMVLNWu490KlNfD0lbfDBUktJIEaZRBj1eeK0SMfdpO/rfyARIzlnPVI1Ge4l0vtSJmQUAiGKxMyLGrCT38iyA==} + engines: {node: '>= 18'} + + sorcery@0.11.1: + resolution: {integrity: sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==} + hasBin: true + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-resolve@0.6.0: + resolution: {integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==} + deprecated: See https://github.com/lydell/source-map-resolve#deprecated + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + space-separated-tokens@1.1.5: + resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} + + spark-md5@3.0.2: + resolution: {integrity: sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==} + + spawndamnit@3.0.1: + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.21: + resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} + + split-on-first@1.1.0: + resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} + engines: {node: '>=6'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + + storybook-addon-rtl@1.1.0: + resolution: {integrity: sha512-L8JljF1M+30rcSuM4JjeIi4ZRmg9WZi/1u4T/5/EQvpDKCMOAq7uHeOKj4YS1InC4Zksnz3DrggXmO3mISXKcQ==} + + storybook@8.6.12: + resolution: {integrity: sha512-Z/nWYEHBTLK1ZBtAWdhxC0l5zf7ioJ7G4+zYqtTdYeb67gTnxNj80gehf8o8QY9L2zA2+eyMRGLC2V5fI7Z3Tw==} + hasBin: true + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + + strict-uri-encode@2.0.0: + resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} + engines: {node: '>=4'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@6.1.0: + resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==} + engines: {node: '>=16'} + + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-json-comments@5.0.1: + resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} + engines: {node: '>=14.16'} + + strip-literal@3.0.0: + resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} + + stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + + supercluster@8.0.1: + resolution: {integrity: sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@9.4.0: + resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} + engines: {node: '>=12'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svelte-ast-print@0.4.2: + resolution: {integrity: sha512-hRHHufbJoArFmDYQKCpCvc0xUuIEfwYksvyLYEQyH+1xb5LD5sM/IthfooCdXZQtOIqXz6xm7NmaqdfwG4kh6w==} + engines: {node: '>=18'} + peerDependencies: + svelte: ^5.0.0 + + svelte-check@4.1.6: + resolution: {integrity: sha512-P7w/6tdSfk3zEVvfsgrp3h3DFC75jCdZjTQvgGJtjPORs1n7/v2VMPIoty3PWv7jnfEm3x0G/p9wH4pecTb0Wg==} + engines: {node: '>= 18.0.0'} + hasBin: true + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + typescript: '>=5.0.0' + + svelte-eslint-parser@1.1.2: + resolution: {integrity: sha512-vqFBRamDKo1l70KMfxxXj1/0Cco5TfMDnqaAjgz6D8PyoMhfMcDOLRkAwPg8WkMyZjMtQL3wW66TZ0x59iqO2w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + svelte: + optional: true + + svelte-fa@4.0.4: + resolution: {integrity: sha512-85BomCGkTrH8kPDGvb8JrVwq9CqR9foprbKjxemP4Dtg3zPR7OXj5hD0xVYK0C+UCzFI1zooLoK/ndIX6aYXAw==} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0 + + svelte-intersection-observer@1.0.0: + resolution: {integrity: sha512-AoxSog8fSt9sSN8ajMYM1I48ndq+rmPlaZSkJFCRbZ7I3KO8IPX6pl5mewWxdYL1JDI06hHu/7epn3h5tlJV9w==} + + svelte-preprocess@5.1.4: + resolution: {integrity: sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==} + engines: {node: '>= 16.0.0'} + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 || ^4.0.0 + postcss: ^7 || ^8 + postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + pug: ^3.0.0 + sass: ^1.26.8 + stylus: ^0.55.0 + sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0 + svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 + typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0' + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + + svelte2tsx@0.7.36: + resolution: {integrity: sha512-nBlERuCZRwmpebC8m0vDqZ9oaKsqW8frQS2l3zwFQW1voQIkItYtHxh1F5OTZEmE0meDIH6cxU36eIOQVOxlCw==} + peerDependencies: + svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0 + typescript: ^4.9.4 || ^5.0.0 + + svelte@5.28.1: + resolution: {integrity: sha512-iOa9WmfNG95lSOSJdMhdjJ4Afok7IRAQYXpbnxhd5EINnXseG0GVa9j6WPght4eX78XfFez45Fi+uRglGKPV/Q==} + engines: {node: '>=18'} + + sveltedoc-parser@4.2.1: + resolution: {integrity: sha512-sWJRa4qOfRdSORSVw9GhfDEwsbsYsegnDzBevUCF6k/Eis/QqCu9lJ6I0+d/E2wOWCjOhlcJ3+jl/Iur+5mmCw==} + engines: {node: '>=10.0.0'} + + synckit@0.11.4: + resolution: {integrity: sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==} + engines: {node: ^14.18.0 || >=16.0.0} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} + + tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyqueue@3.0.0: + resolution: {integrity: sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==} + + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.3: + resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} + engines: {node: '>=14.0.0'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tween-functions@1.2.0: + resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + + typescript-eslint@8.30.1: + resolution: {integrity: sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + ua-is-frozen@0.1.2: + resolution: {integrity: sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==} + + ua-parser-js@2.0.3: + resolution: {integrity: sha512-LZyXZdNttONW8LjzEH3Z8+6TE7RfrEiJqDKyh0R11p/kxvrV2o9DrT2FGZO+KVNs3k+drcIQ6C3En6wLnzJGpw==} + hasBin: true + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + unified-engine@11.2.2: + resolution: {integrity: sha512-15g/gWE7qQl9tQ3nAEbMd5h9HV1EACtFs6N9xaRBZICoCwnNGbal1kOs++ICf4aiTdItZxU2s/kYWhW7htlqJg==} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unist-util-inspect@8.1.0: + resolution: {integrity: sha512-mOlg8Mp33pR0eeFpo5d2902ojqFFOKMMG2hF8bmH7ZlhnmjFgh0NI3/ZDwdaBJNbvrS7LZFVrBVtIE9KZ9s7vQ==} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + + unist-util-stringify-position@3.0.3: + resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unplugin@1.16.1: + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + uvu@0.5.6: + resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} + engines: {node: '>=8'} + hasBin: true + + v8-compile-cache@2.4.0: + resolution: {integrity: sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile-reporter@8.1.1: + resolution: {integrity: sha512-qxRZcnFSQt6pWKn3PAk81yLK2rO2i7CDXpy8v8ZquiEOMLSnPw6BMSi9Y1sUCwGGl7a9b3CJT1CKpnRF7pp66g==} + + vfile-sort@4.0.0: + resolution: {integrity: sha512-lffPI1JrbHDTToJwcq0rl6rBmkjQmMuXkAxsZPRS9DXbaJQvc642eCg6EGxcX2i1L+esbuhq+2l9tBll5v8AeQ==} + + vfile-statistics@3.0.0: + resolution: {integrity: sha512-/qlwqwWBWFOmpXujL/20P+Iuydil0rZZNglR+VNm6J0gpLHwuVM5s7g2TfVoswbXjZ4HuIhLMySEyIw5i7/D8w==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.3.2: + resolution: {integrity: sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.0.6: + resolution: {integrity: sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + vite: + optional: true + + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + walk-up-path@3.0.1: + resolution: {integrity: sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + web-worker@1.5.0: + resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.18.1: + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.7.1: + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} + engines: {node: '>= 14'} + hasBin: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zimmerframe@1.1.2: + resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} + + zod-validation-error@3.4.0: + resolution: {integrity: sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.18.0 + + zod@3.24.3: + resolution: {integrity: sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@adobe/css-tools@4.4.2': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/runtime@7.27.0': + dependencies: + regenerator-runtime: 0.14.1 + + '@braintree/sanitize-url@6.0.4': {} + + '@changesets/apply-release-plan@7.0.12': + dependencies: + '@changesets/config': 3.1.1 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.7.1 + + '@changesets/assemble-release-plan@6.0.6': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.7.1 + + '@changesets/changelog-git@0.2.1': + dependencies: + '@changesets/types': 6.1.0 + + '@changesets/cli@2.29.2': + dependencies: + '@changesets/apply-release-plan': 7.0.12 + '@changesets/assemble-release-plan': 6.0.6 + '@changesets/changelog-git': 0.2.1 + '@changesets/config': 3.1.1 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/get-release-plan': 4.0.10 + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.5 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@changesets/write': 0.4.0 + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + ci-info: 3.9.0 + enquirer: 2.4.1 + external-editor: 3.1.0 + fs-extra: 7.0.1 + mri: 1.2.0 + p-limit: 2.3.0 + package-manager-detector: 0.2.11 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.7.1 + spawndamnit: 3.0.1 + term-size: 2.2.1 + + '@changesets/config@3.1.1': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/logger': 0.1.1 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.3': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.7.1 + + '@changesets/get-release-plan@4.0.10': + dependencies: + '@changesets/assemble-release-plan': 6.0.6 + '@changesets/config': 3.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.5 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.4': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 3.0.1 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.1': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 3.14.1 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.5': + dependencies: + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.1 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.1.1 + prettier: 2.8.8 + + '@chromatic-com/storybook@3.2.6(react@18.3.1)(storybook@8.6.12(prettier@3.5.3))': + dependencies: + chromatic: 11.28.2 + filesize: 10.1.6 + jsonfile: 6.1.0 + react-confetti: 6.4.0(react@18.3.1) + storybook: 8.6.12(prettier@3.5.3) + strip-ansi: 7.1.0 + transitivePeerDependencies: + - '@chromatic-com/cypress' + - '@chromatic-com/playwright' + - react + + '@esbuild/aix-ppc64@0.25.2': + optional: true + + '@esbuild/android-arm64@0.25.2': + optional: true + + '@esbuild/android-arm@0.25.2': + optional: true + + '@esbuild/android-x64@0.25.2': + optional: true + + '@esbuild/darwin-arm64@0.25.2': + optional: true + + '@esbuild/darwin-x64@0.25.2': + optional: true + + '@esbuild/freebsd-arm64@0.25.2': + optional: true + + '@esbuild/freebsd-x64@0.25.2': + optional: true + + '@esbuild/linux-arm64@0.25.2': + optional: true + + '@esbuild/linux-arm@0.25.2': + optional: true + + '@esbuild/linux-ia32@0.25.2': + optional: true + + '@esbuild/linux-loong64@0.25.2': + optional: true + + '@esbuild/linux-mips64el@0.25.2': + optional: true + + '@esbuild/linux-ppc64@0.25.2': + optional: true + + '@esbuild/linux-riscv64@0.25.2': + optional: true + + '@esbuild/linux-s390x@0.25.2': + optional: true + + '@esbuild/linux-x64@0.25.2': + optional: true + + '@esbuild/netbsd-arm64@0.25.2': + optional: true + + '@esbuild/netbsd-x64@0.25.2': + optional: true + + '@esbuild/openbsd-arm64@0.25.2': + optional: true + + '@esbuild/openbsd-x64@0.25.2': + optional: true + + '@esbuild/sunos-x64@0.25.2': + optional: true + + '@esbuild/win32-arm64@0.25.2': + optional: true + + '@esbuild/win32-ia32@0.25.2': + optional: true + + '@esbuild/win32-x64@0.25.2': + optional: true + + '@eslint-community/eslint-utils@4.6.1(eslint@9.25.0(jiti@2.4.2))': + dependencies: + eslint: 9.25.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.20.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.2.1': {} + + '@eslint/core@0.13.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@1.4.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.0 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.0 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.25.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.8': + dependencies: + '@eslint/core': 0.13.0 + levn: 0.4.1 + + '@fortawesome/fontawesome-common-types@6.7.2': {} + + '@fortawesome/free-regular-svg-icons@6.7.2': + dependencies: + '@fortawesome/fontawesome-common-types': 6.7.2 + + '@fortawesome/free-solid-svg-icons@6.7.2': + dependencies: + '@fortawesome/fontawesome-common-types': 6.7.2 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/config-array@0.9.5': + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/object-schema@1.2.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.2': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@lottiefiles/dotlottie-web@0.52.2': {} + + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.27.0 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + + '@manypkg/get-packages@1.1.3': + dependencies: + '@babel/runtime': 7.27.0 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + + '@mapbox/geojson-rewind@0.5.2': + dependencies: + get-stream: 6.0.1 + minimist: 1.2.8 + + '@mapbox/jsonlint-lines-primitives@2.0.2': {} + + '@mapbox/point-geometry@1.1.0': {} + + '@mapbox/tiny-sdf@2.0.7': {} + + '@mapbox/unitbezier@0.0.1': {} + + '@mapbox/vector-tile@2.0.4': + dependencies: + '@mapbox/point-geometry': 1.1.0 + '@types/geojson': 7946.0.16 + pbf: 4.0.1 + + '@mapbox/whoots-js@3.1.0': {} + + '@maplibre/maplibre-gl-style-spec@24.4.1': + dependencies: + '@mapbox/jsonlint-lines-primitives': 2.0.2 + '@mapbox/unitbezier': 0.0.1 + json-stringify-pretty-compact: 4.0.0 + minimist: 1.2.8 + quickselect: 3.0.0 + rw: 1.3.3 + tinyqueue: 3.0.0 + + '@maplibre/mlt@1.1.2': + dependencies: + '@mapbox/point-geometry': 1.1.0 + + '@maplibre/vt-pbf@4.2.0': + dependencies: + '@mapbox/point-geometry': 1.1.0 + '@mapbox/vector-tile': 2.0.4 + '@types/geojson-vt': 3.2.5 + '@types/supercluster': 7.1.3 + geojson-vt: 4.0.2 + pbf: 4.0.1 + supercluster: 8.0.1 + + '@mdx-js/react@3.1.0(@types/react@18.3.20)(react@18.3.1)': + dependencies: + '@types/mdx': 2.0.13 + '@types/react': 18.3.20 + react: 18.3.1 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@npmcli/config@8.3.4': + dependencies: + '@npmcli/map-workspaces': 3.0.6 + '@npmcli/package-json': 5.2.1 + ci-info: 4.2.0 + ini: 4.1.3 + nopt: 7.2.1 + proc-log: 4.2.0 + semver: 7.7.1 + walk-up-path: 3.0.1 + transitivePeerDependencies: + - bluebird + + '@npmcli/git@5.0.8': + dependencies: + '@npmcli/promise-spawn': 7.0.2 + ini: 4.1.3 + lru-cache: 10.4.3 + npm-pick-manifest: 9.1.0 + proc-log: 4.2.0 + promise-inflight: 1.0.1 + promise-retry: 2.0.1 + semver: 7.7.1 + which: 4.0.0 + transitivePeerDependencies: + - bluebird + + '@npmcli/map-workspaces@3.0.6': + dependencies: + '@npmcli/name-from-folder': 2.0.0 + glob: 10.4.5 + minimatch: 9.0.5 + read-package-json-fast: 3.0.2 + + '@npmcli/name-from-folder@2.0.0': {} + + '@npmcli/package-json@5.2.1': + dependencies: + '@npmcli/git': 5.0.8 + glob: 10.4.5 + hosted-git-info: 7.0.2 + json-parse-even-better-errors: 3.0.2 + normalize-package-data: 6.0.2 + proc-log: 4.2.0 + semver: 7.7.1 + transitivePeerDependencies: + - bluebird + + '@npmcli/promise-spawn@7.0.2': + dependencies: + which: 4.0.0 + + '@parcel/watcher-android-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-x64@2.5.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.1': + optional: true + + '@parcel/watcher-win32-arm64@2.5.1': + optional: true + + '@parcel/watcher-win32-ia32@2.5.1': + optional: true + + '@parcel/watcher-win32-x64@2.5.1': + optional: true + + '@parcel/watcher@2.5.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.5.1 + '@parcel/watcher-darwin-arm64': 2.5.1 + '@parcel/watcher-darwin-x64': 2.5.1 + '@parcel/watcher-freebsd-x64': 2.5.1 + '@parcel/watcher-linux-arm-glibc': 2.5.1 + '@parcel/watcher-linux-arm-musl': 2.5.1 + '@parcel/watcher-linux-arm64-glibc': 2.5.1 + '@parcel/watcher-linux-arm64-musl': 2.5.1 + '@parcel/watcher-linux-x64-glibc': 2.5.1 + '@parcel/watcher-linux-x64-musl': 2.5.1 + '@parcel/watcher-win32-arm64': 2.5.1 + '@parcel/watcher-win32-ia32': 2.5.1 + '@parcel/watcher-win32-x64': 2.5.1 + optional: true + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.2.4': {} + + '@polka/url@1.0.0-next.29': {} + + '@publint/pack@0.1.2': {} + + '@reuters-graphics/svelte-markdown@0.0.3(svelte@5.28.1)': + dependencies: + es-toolkit: 1.35.0 + marked: 15.0.8 + marked-smartypants: 1.1.9(marked@15.0.8) + parse5: 7.2.1 + spark-md5: 3.0.2 + svelte: 5.28.1 + + '@reuters-graphics/yaks-eslint@0.1.1(@types/eslint@9.6.1)(eslint@9.25.0(jiti@2.4.2))(prettier@3.5.3)(svelte@5.28.1)(typescript@5.8.3)': + dependencies: + '@eslint/js': 9.25.0 + eslint: 9.25.0(jiti@2.4.2) + eslint-config-prettier: 10.1.2(eslint@9.25.0(jiti@2.4.2)) + eslint-plugin-prettier: 5.2.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.2(eslint@9.25.0(jiti@2.4.2)))(eslint@9.25.0(jiti@2.4.2))(prettier@3.5.3) + eslint-plugin-svelte: 3.5.1(eslint@9.25.0(jiti@2.4.2))(svelte@5.28.1) + globals: 16.0.0 + svelte: 5.28.1 + typescript: 5.8.3 + typescript-eslint: 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + transitivePeerDependencies: + - '@types/eslint' + - prettier + - supports-color + - ts-node + + '@reuters-graphics/yaks-prettier@0.1.1(prettier@3.5.3)(svelte@5.28.1)(typescript@5.8.3)': + dependencies: + prettier: 3.5.3 + prettier-plugin-svelte: 3.3.3(prettier@3.5.3)(svelte@5.28.1) + typescript: 5.8.3 + transitivePeerDependencies: + - svelte + + '@rollup/rollup-android-arm-eabi@4.40.0': + optional: true + + '@rollup/rollup-android-arm64@4.40.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.40.0': + optional: true + + '@rollup/rollup-darwin-x64@4.40.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.40.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.40.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.40.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.40.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.40.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.40.0': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.40.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.40.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.40.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.40.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.40.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.40.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.40.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.40.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.40.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.40.0': + optional: true + + '@storybook/addon-a11y@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/addon-highlight': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/global': 5.0.0 + '@storybook/test': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + axe-core: 4.10.3 + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/addon-actions@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/global': 5.0.0 + '@types/uuid': 9.0.8 + dequal: 2.0.3 + polished: 4.3.1 + storybook: 8.6.12(prettier@3.5.3) + uuid: 9.0.1 + + '@storybook/addon-backgrounds@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/global': 5.0.0 + memoizerific: 1.11.3 + storybook: 8.6.12(prettier@3.5.3) + ts-dedent: 2.2.0 + + '@storybook/addon-controls@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/global': 5.0.0 + dequal: 2.0.3 + storybook: 8.6.12(prettier@3.5.3) + ts-dedent: 2.2.0 + + '@storybook/addon-docs@8.6.12(@types/react@18.3.20)(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@mdx-js/react': 3.1.0(@types/react@18.3.20)(react@18.3.1) + '@storybook/blocks': 8.6.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.12(prettier@3.5.3)) + '@storybook/csf-plugin': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/react-dom-shim': 8.6.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.12(prettier@3.5.3)) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + storybook: 8.6.12(prettier@3.5.3) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + + '@storybook/addon-essentials@8.6.12(@types/react@18.3.20)(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/addon-actions': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-backgrounds': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-controls': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-docs': 8.6.12(@types/react@18.3.20)(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-highlight': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-measure': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-outline': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-toolbars': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/addon-viewport': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + storybook: 8.6.12(prettier@3.5.3) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + + '@storybook/addon-highlight@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/addon-interactions@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/test': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + polished: 4.3.1 + storybook: 8.6.12(prettier@3.5.3) + ts-dedent: 2.2.0 + + '@storybook/addon-measure@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.12(prettier@3.5.3) + tiny-invariant: 1.3.3 + + '@storybook/addon-outline@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.12(prettier@3.5.3) + ts-dedent: 2.2.0 + + '@storybook/addon-svelte-csf@5.0.0-next.28(@storybook/svelte@8.6.12(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1))(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))': + dependencies: + '@storybook/csf': 0.1.13 + '@storybook/svelte': 8.6.12(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + dedent: 1.5.3 + es-toolkit: 1.35.0 + esrap: 1.4.6 + magic-string: 0.30.17 + storybook: 8.6.12(prettier@3.5.3) + svelte: 5.28.1 + svelte-ast-print: 0.4.2(svelte@5.28.1) + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + zimmerframe: 1.1.2 + transitivePeerDependencies: + - babel-plugin-macros + + '@storybook/addon-toolbars@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/addon-viewport@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + memoizerific: 1.11.3 + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/blocks@8.6.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/icons': 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + storybook: 8.6.12(prettier@3.5.3) + ts-dedent: 2.2.0 + optionalDependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@storybook/builder-vite@8.6.12(storybook@8.6.12(prettier@3.5.3))(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))': + dependencies: + '@storybook/csf-plugin': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + browser-assert: 1.2.1 + storybook: 8.6.12(prettier@3.5.3) + ts-dedent: 2.2.0 + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + + '@storybook/components@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/core@8.6.12(prettier@3.5.3)(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/theming': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + better-opn: 3.0.2 + browser-assert: 1.2.1 + esbuild: 0.25.2 + esbuild-register: 3.6.0(esbuild@0.25.2) + jsdoc-type-pratt-parser: 4.1.0 + process: 0.11.10 + recast: 0.23.11 + semver: 7.7.1 + util: 0.12.5 + ws: 8.18.1 + optionalDependencies: + prettier: 3.5.3 + transitivePeerDependencies: + - bufferutil + - storybook + - supports-color + - utf-8-validate + + '@storybook/csf-plugin@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + storybook: 8.6.12(prettier@3.5.3) + unplugin: 1.16.1 + + '@storybook/csf@0.1.12': + dependencies: + type-fest: 2.19.0 + + '@storybook/csf@0.1.13': + dependencies: + type-fest: 2.19.0 + + '@storybook/global@5.0.0': {} + + '@storybook/icons@1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@storybook/instrumenter@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/global': 5.0.0 + '@vitest/utils': 2.1.9 + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/manager-api@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/preview-api@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/react-dom-shim@8.6.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.12(prettier@3.5.3))': + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/svelte-vite@8.6.12(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(postcss-load-config@3.1.4(postcss@8.5.3))(postcss@8.5.3)(sass@1.86.3)(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))': + dependencies: + '@storybook/builder-vite': 8.6.12(storybook@8.6.12(prettier@3.5.3))(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + '@storybook/svelte': 8.6.12(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1) + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + magic-string: 0.30.17 + storybook: 8.6.12(prettier@3.5.3) + svelte: 5.28.1 + svelte-preprocess: 5.1.4(postcss-load-config@3.1.4(postcss@8.5.3))(postcss@8.5.3)(sass@1.86.3)(svelte@5.28.1)(typescript@5.8.3) + svelte2tsx: 0.7.36(svelte@5.28.1)(typescript@5.8.3) + sveltedoc-parser: 4.2.1 + ts-dedent: 2.2.0 + typescript: 5.8.3 + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + transitivePeerDependencies: + - '@babel/core' + - coffeescript + - less + - postcss + - postcss-load-config + - pug + - sass + - stylus + - sugarss + - supports-color + + '@storybook/svelte@8.6.12(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1)': + dependencies: + '@storybook/components': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/csf': 0.1.12 + '@storybook/global': 5.0.0 + '@storybook/manager-api': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/preview-api': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/theming': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + storybook: 8.6.12(prettier@3.5.3) + svelte: 5.28.1 + sveltedoc-parser: 4.2.1 + ts-dedent: 2.2.0 + type-fest: 2.19.0 + transitivePeerDependencies: + - supports-color + + '@storybook/sveltekit@8.6.12(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(postcss-load-config@3.1.4(postcss@8.5.3))(postcss@8.5.3)(sass@1.86.3)(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))': + dependencies: + '@storybook/addon-actions': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@storybook/builder-vite': 8.6.12(storybook@8.6.12(prettier@3.5.3))(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + '@storybook/svelte': 8.6.12(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1) + '@storybook/svelte-vite': 8.6.12(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(postcss-load-config@3.1.4(postcss@8.5.3))(postcss@8.5.3)(sass@1.86.3)(storybook@8.6.12(prettier@3.5.3))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + storybook: 8.6.12(prettier@3.5.3) + svelte: 5.28.1 + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + transitivePeerDependencies: + - '@babel/core' + - '@sveltejs/vite-plugin-svelte' + - coffeescript + - less + - postcss + - postcss-load-config + - pug + - sass + - stylus + - sugarss + - supports-color + + '@storybook/test@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.6.12(storybook@8.6.12(prettier@3.5.3)) + '@testing-library/dom': 10.4.0 + '@testing-library/jest-dom': 6.5.0 + '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0) + '@vitest/expect': 2.0.5 + '@vitest/spy': 2.0.5 + storybook: 8.6.12(prettier@3.5.3) + + '@storybook/theming@8.6.12(storybook@8.6.12(prettier@3.5.3))': + dependencies: + storybook: 8.6.12(prettier@3.5.3) + + '@sveltejs/acorn-typescript@1.0.5(acorn@8.14.1)': + dependencies: + acorn: 8.14.1 + + '@sveltejs/kit@2.20.7(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))': + dependencies: + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + '@types/cookie': 0.6.0 + cookie: 0.6.0 + devalue: 5.1.1 + esm-env: 1.2.2 + import-meta-resolve: 4.1.0 + kleur: 4.1.5 + magic-string: 0.30.17 + mrmime: 2.0.1 + sade: 1.8.1 + set-cookie-parser: 2.7.1 + sirv: 3.0.1 + svelte: 5.28.1 + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + + '@sveltejs/package@2.3.11(svelte@5.28.1)(typescript@5.8.3)': + dependencies: + chokidar: 4.0.3 + kleur: 4.1.5 + sade: 1.8.1 + semver: 7.7.1 + svelte: 5.28.1 + svelte2tsx: 0.7.36(svelte@5.28.1)(typescript@5.8.3) + transitivePeerDependencies: + - typescript + + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))': + dependencies: + '@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + debug: 4.4.0 + svelte: 5.28.1 + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)))(svelte@5.28.1)(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + debug: 4.4.0 + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.17 + svelte: 5.28.1 + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + vitefu: 1.0.6(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + transitivePeerDependencies: + - supports-color + + '@testing-library/dom@10.4.0': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/runtime': 7.27.0 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.5.0': + dependencies: + '@adobe/css-tools': 4.4.2 + aria-query: 5.3.2 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + + '@testing-library/user-event@14.5.2(@testing-library/dom@10.4.0)': + dependencies: + '@testing-library/dom': 10.4.0 + + '@types/aria-query@5.0.4': {} + + '@types/chai@5.2.2': + dependencies: + '@types/deep-eql': 4.0.2 + + '@types/concat-stream@2.0.3': + dependencies: + '@types/node': 22.14.1 + + '@types/cookie@0.6.0': {} + + '@types/css@0.0.37': {} + + '@types/d3-scale-chromatic@3.1.0': {} + + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.4 + + '@types/d3-time@3.0.4': {} + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 2.1.0 + + '@types/deep-eql@4.0.2': {} + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.7 + '@types/json-schema': 7.0.15 + + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.7 + + '@types/estree@1.0.7': {} + + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 22.14.1 + + '@types/geojson-vt@3.2.5': + dependencies: + '@types/geojson': 7946.0.16 + + '@types/geojson@7946.0.16': {} + + '@types/google-publisher-tag@1.20250210.0': {} + + '@types/gtag.js@0.0.12': {} + + '@types/hast@2.3.10': + dependencies: + '@types/unist': 2.0.11 + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/is-empty@1.2.3': {} + + '@types/json-schema@7.0.15': {} + + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 22.14.1 + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.16 + + '@types/lodash@4.17.16': {} + + '@types/mdast@3.0.15': + dependencies: + '@types/unist': 2.0.11 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdx@2.0.13': {} + + '@types/ms@2.1.0': {} + + '@types/node-fetch@2.6.12': + dependencies: + '@types/node': 22.14.1 + form-data: 4.0.2 + + '@types/node@12.20.55': {} + + '@types/node@22.14.1': + dependencies: + undici-types: 6.21.0 + + '@types/prompts@2.4.9': + dependencies: + '@types/node': 22.14.1 + kleur: 3.0.3 + + '@types/prop-types@15.7.14': {} + + '@types/proper-url-join@2.1.5': + dependencies: + query-string: 7.1.3 + + '@types/pug@2.0.10': {} + + '@types/pym.js@1.3.2': {} + + '@types/react-syntax-highlighter@15.5.13': + dependencies: + '@types/react': 18.3.20 + + '@types/react@18.3.20': + dependencies: + '@types/prop-types': 15.7.14 + csstype: 3.1.3 + + '@types/supercluster@7.1.3': + dependencies: + '@types/geojson': 7946.0.16 + + '@types/supports-color@8.1.3': {} + + '@types/unist@2.0.11': {} + + '@types/unist@3.0.3': {} + + '@types/uuid@9.0.8': {} + + '@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.30.1 + '@typescript-eslint/type-utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.30.1 + eslint: 9.25.0(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.30.1 + '@typescript-eslint/types': 8.30.1 + '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.30.1 + debug: 4.4.0 + eslint: 9.25.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.30.1': + dependencies: + '@typescript-eslint/types': 8.30.1 + '@typescript-eslint/visitor-keys': 8.30.1 + + '@typescript-eslint/type-utils@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) + '@typescript-eslint/utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + debug: 4.4.0 + eslint: 9.25.0(jiti@2.4.2) + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.30.1': {} + + '@typescript-eslint/typescript-estree@8.30.1(typescript@5.8.3)': + dependencies: + '@typescript-eslint/types': 8.30.1 + '@typescript-eslint/visitor-keys': 8.30.1 + debug: 4.4.0 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 2.1.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.30.1 + '@typescript-eslint/types': 8.30.1 + '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) + eslint: 9.25.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.30.1': + dependencies: + '@typescript-eslint/types': 8.30.1 + eslint-visitor-keys: 4.2.0 + + '@vitest/expect@2.0.5': + dependencies: + '@vitest/spy': 2.0.5 + '@vitest/utils': 2.0.5 + chai: 5.2.0 + tinyrainbow: 1.2.0 + + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.2 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.2.0 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.4(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + + '@vitest/pretty-format@2.0.5': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/pretty-format@2.1.9': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.4': + dependencies: + '@vitest/utils': 3.2.4 + pathe: 2.0.3 + strip-literal: 3.0.0 + + '@vitest/snapshot@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + magic-string: 0.30.17 + pathe: 2.0.3 + + '@vitest/spy@2.0.5': + dependencies: + tinyspy: 3.0.2 + + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.3 + + '@vitest/utils@2.0.5': + dependencies: + '@vitest/pretty-format': 2.0.5 + estree-walker: 3.0.3 + loupe: 3.1.3 + tinyrainbow: 1.2.0 + + '@vitest/utils@2.1.9': + dependencies: + '@vitest/pretty-format': 2.1.9 + loupe: 3.1.3 + tinyrainbow: 1.2.0 + + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.2.0 + tinyrainbow: 2.0.0 + + abbrev@2.0.0: {} + + acorn-jsx@5.3.2(acorn@8.14.1): + dependencies: + acorn: 8.14.1 + + acorn@8.14.1: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-colors@4.1.3: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-includes@3.1.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + + array-union@2.1.0: {} + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + assertion-error@2.0.1: {} + + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + + async-function@1.0.0: {} + + asynckit@0.4.0: {} + + atob@2.1.2: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axe-core@4.10.3: {} + + axobject-query@4.1.0: {} + + bail@2.0.2: {} + + balanced-match@1.0.2: {} + + better-opn@3.0.2: + dependencies: + open: 8.4.2 + + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browser-assert@1.2.1: {} + + buffer-crc32@1.0.0: {} + + buffer-from@1.1.2: {} + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + ccount@2.0.1: {} + + chai@5.2.0: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 + + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + character-entities-html4@2.1.0: {} + + character-entities-legacy@1.1.4: {} + + character-entities-legacy@3.0.0: {} + + character-entities@1.2.4: {} + + character-entities@2.0.2: {} + + character-reference-invalid@1.1.4: {} + + character-reference-invalid@2.0.1: {} + + chardet@0.7.0: {} + + check-error@2.1.1: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chromatic@11.28.2: {} + + ci-info@3.9.0: {} + + ci-info@4.2.0: {} + + clone@1.0.4: + optional: true + + clsx@2.1.1: {} + + color-convert@0.5.3: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + comma-separated-tokens@1.0.8: {} + + commander@7.2.0: {} + + commander@8.3.0: {} + + concat-map@0.0.1: {} + + concat-stream@2.0.0: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.2 + typedarray: 0.0.6 + + cookie@0.6.0: {} + + cose-base@1.0.3: + dependencies: + layout-base: 1.0.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-color-converter@2.0.0: + dependencies: + color-convert: 0.5.3 + color-name: 1.1.4 + css-unit-converter: 1.1.2 + + css-unit-converter@1.1.2: {} + + css.escape@1.5.1: {} + + css@3.0.0: + dependencies: + inherits: 2.0.4 + source-map: 0.6.1 + source-map-resolve: 0.6.0 + + cssesc@3.0.0: {} + + csstype@3.1.3: {} + + cytoscape-cose-bilkent@4.1.0(cytoscape@3.31.2): + dependencies: + cose-base: 1.0.3 + cytoscape: 3.31.2 + + cytoscape@3.31.2: {} + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + + d3-color@3.1.0: {} + + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.0.1 + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.0: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 + + d3-hierarchy@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@1.0.9: {} + + d3-path@3.1.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-sankey@0.12.3: + dependencies: + d3-array: 2.12.1 + d3-shape: 1.3.7 + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.0 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-selection@3.0.0: {} + + d3-shape@1.3.7: + dependencies: + d3-path: 1.0.9 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.0 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + dagre-d3-es@7.0.10: + dependencies: + d3: 7.9.0 + lodash-es: 4.17.21 + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + dayjs@1.11.13: {} + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + debug@4.4.1: + dependencies: + ms: 2.1.3 + + decode-named-character-reference@1.1.0: + dependencies: + character-entities: 2.0.2 + + decode-uri-component@0.2.2: {} + + dedent-js@1.0.1: {} + + dedent@1.5.3: {} + + deep-eql@5.0.2: {} + + deep-is@0.1.4: {} + + deep-object-diff@1.1.9: {} + + deepmerge@4.3.1: {} + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + optional: true + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@2.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + delaunator@5.0.1: + dependencies: + robust-predicates: 3.0.2 + + delayed-stream@1.0.0: {} + + dequal@2.0.3: {} + + detect-europe-js@0.1.2: {} + + detect-indent@6.1.0: {} + + detect-libc@1.0.3: + optional: true + + devalue@5.1.1: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff@5.2.0: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + domelementtype@2.3.0: {} + + domhandler@3.3.0: + dependencies: + domelementtype: 2.3.0 + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + dompurify@3.1.6: {} + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + earcut@3.0.2: {} + + eastasianwidth@0.2.0: {} + + easy-table@1.2.0: + dependencies: + ansi-regex: 5.0.1 + optionalDependencies: + wcwidth: 1.0.1 + + elkjs@0.9.3: {} + + emoji-regex@10.4.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + entities@2.2.0: {} + + entities@4.5.0: {} + + err-code@2.0.3: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + es-abstract@1.23.9: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.19 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-iterator-helpers@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + safe-array-concat: 1.1.3 + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + es-toolkit@1.35.0: {} + + es6-promise@3.3.1: {} + + esbuild-register@3.6.0(esbuild@0.25.2): + dependencies: + debug: 4.4.0 + esbuild: 0.25.2 + transitivePeerDependencies: + - supports-color + + esbuild@0.25.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.2 + '@esbuild/android-arm': 0.25.2 + '@esbuild/android-arm64': 0.25.2 + '@esbuild/android-x64': 0.25.2 + '@esbuild/darwin-arm64': 0.25.2 + '@esbuild/darwin-x64': 0.25.2 + '@esbuild/freebsd-arm64': 0.25.2 + '@esbuild/freebsd-x64': 0.25.2 + '@esbuild/linux-arm': 0.25.2 + '@esbuild/linux-arm64': 0.25.2 + '@esbuild/linux-ia32': 0.25.2 + '@esbuild/linux-loong64': 0.25.2 + '@esbuild/linux-mips64el': 0.25.2 + '@esbuild/linux-ppc64': 0.25.2 + '@esbuild/linux-riscv64': 0.25.2 + '@esbuild/linux-s390x': 0.25.2 + '@esbuild/linux-x64': 0.25.2 + '@esbuild/netbsd-arm64': 0.25.2 + '@esbuild/netbsd-x64': 0.25.2 + '@esbuild/openbsd-arm64': 0.25.2 + '@esbuild/openbsd-x64': 0.25.2 + '@esbuild/sunos-x64': 0.25.2 + '@esbuild/win32-arm64': 0.25.2 + '@esbuild/win32-ia32': 0.25.2 + '@esbuild/win32-x64': 0.25.2 + + escape-string-regexp@4.0.0: {} + + eslint-config-prettier@10.1.2(eslint@9.25.0(jiti@2.4.2)): + dependencies: + eslint: 9.25.0(jiti@2.4.2) + + eslint-mdx@3.4.0(eslint@9.25.0(jiti@2.4.2)): + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint: 9.25.0(jiti@2.4.2) + espree: 10.3.0 + estree-util-visit: 2.0.0 + remark-mdx: 3.1.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + synckit: 0.11.4 + tslib: 2.8.1 + unified: 11.0.5 + unified-engine: 11.2.2 + unist-util-visit: 5.0.0 + uvu: 0.5.6 + vfile: 6.0.3 + transitivePeerDependencies: + - bluebird + - supports-color + + eslint-plugin-mdx@3.4.0(eslint@9.25.0(jiti@2.4.2)): + dependencies: + eslint: 9.25.0(jiti@2.4.2) + eslint-mdx: 3.4.0(eslint@9.25.0(jiti@2.4.2)) + mdast-util-from-markdown: 2.0.2 + mdast-util-mdx: 3.0.0 + micromark-extension-mdxjs: 3.0.0 + remark-mdx: 3.1.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + synckit: 0.11.4 + tslib: 2.8.1 + unified: 11.0.5 + vfile: 6.0.3 + transitivePeerDependencies: + - bluebird + - remark-lint-file-extension + - supports-color + + eslint-plugin-prettier@5.2.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.2(eslint@9.25.0(jiti@2.4.2)))(eslint@9.25.0(jiti@2.4.2))(prettier@3.5.3): + dependencies: + eslint: 9.25.0(jiti@2.4.2) + prettier: 3.5.3 + prettier-linter-helpers: 1.0.0 + synckit: 0.11.4 + optionalDependencies: + '@types/eslint': 9.6.1 + eslint-config-prettier: 10.1.2(eslint@9.25.0(jiti@2.4.2)) + + eslint-plugin-react@7.37.5(eslint@9.25.0(jiti@2.4.2)): + dependencies: + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.25.0(jiti@2.4.2) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + + eslint-plugin-storybook@0.12.0(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3): + dependencies: + '@storybook/csf': 0.1.13 + '@typescript-eslint/utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + eslint: 9.25.0(jiti@2.4.2) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-svelte@3.5.1(eslint@9.25.0(jiti@2.4.2))(svelte@5.28.1): + dependencies: + '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.0(jiti@2.4.2)) + '@jridgewell/sourcemap-codec': 1.5.0 + eslint: 9.25.0(jiti@2.4.2) + esutils: 2.0.3 + known-css-properties: 0.35.0 + postcss: 8.5.3 + postcss-load-config: 3.1.4(postcss@8.5.3) + postcss-safe-parser: 7.0.1(postcss@8.5.3) + semver: 7.7.1 + svelte-eslint-parser: 1.1.2(svelte@5.28.1) + optionalDependencies: + svelte: 5.28.1 + transitivePeerDependencies: + - ts-node + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-scope@8.3.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-utils@3.0.0(eslint@8.4.1): + dependencies: + eslint: 8.4.1 + eslint-visitor-keys: 2.1.0 + + eslint-visitor-keys@2.1.0: {} + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint@8.4.1: + dependencies: + '@eslint/eslintrc': 1.4.1 + '@humanwhocodes/config-array': 0.9.5 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0 + doctrine: 3.0.0 + enquirer: 2.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-utils: 3.0.0(eslint@8.4.1) + eslint-visitor-keys: 3.4.3 + espree: 9.2.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 6.0.2 + globals: 13.24.0 + ignore: 4.0.6 + import-fresh: 3.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + progress: 2.0.3 + regexpp: 3.2.0 + semver: 7.7.1 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + v8-compile-cache: 2.4.0 + transitivePeerDependencies: + - supports-color + + eslint@9.25.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.20.0 + '@eslint/config-helpers': 0.2.1 + '@eslint/core': 0.13.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.25.0 + '@eslint/plugin-kit': 0.2.8 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.2 + '@types/estree': 1.0.7 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0 + escape-string-regexp: 4.0.0 + eslint-scope: 8.3.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + esm-env@1.2.2: {} + + espree@10.3.0: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 4.2.0 + + espree@9.2.0: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 3.4.3 + + espree@9.6.1: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 3.4.3 + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrap@1.2.2: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@types/estree': 1.0.7 + + esrap@1.4.6: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-util-is-identifier-name@3.0.0: {} + + estree-util-visit@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.3 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.7 + + esutils@2.0.3: {} + + expect-type@1.2.2: {} + + extend@3.0.2: {} + + extendable-error@0.1.7: {} + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fault@1.0.4: + dependencies: + format: 0.2.2 + + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + fdir@6.4.6(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + fflate@0.8.2: {} + + file-entry-cache@6.0.1: + dependencies: + flat-cache: 3.2.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + filesize@10.1.6: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + filter-obj@1.1.0: {} + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@3.2.0: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + rimraf: 3.0.2 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + format@0.2.2: {} + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functional-red-black-tree@1.0.1: {} + + functions-have-names@1.2.3: {} + + geojson-vt@4.0.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@6.0.1: {} + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + gl-matrix@3.4.4: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@11.0.1: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.1.0 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globals@14.0.0: {} + + globals@16.0.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hast-util-parse-selector@2.2.5: {} + + hastscript@6.0.0: + dependencies: + '@types/hast': 2.3.10 + comma-separated-tokens: 1.0.8 + hast-util-parse-selector: 2.2.5 + property-information: 5.6.0 + space-separated-tokens: 1.1.5 + + highlight.js@10.7.3: {} + + highlightjs-vue@1.0.0: {} + + hosted-git-info@7.0.2: + dependencies: + lru-cache: 10.4.3 + + htmlparser2-svelte@4.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 3.3.0 + domutils: 2.8.0 + entities: 2.2.0 + + human-id@4.1.1: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ignore@4.0.6: {} + + ignore@5.3.2: {} + + ignore@6.0.2: {} + + immutable@5.1.1: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.1.0: {} + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@4.1.3: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + internmap@1.0.1: {} + + internmap@2.0.3: {} + + is-alphabetical@1.0.4: {} + + is-alphabetical@2.0.1: {} + + is-alphanumerical@1.0.4: + dependencies: + is-alphabetical: 1.0.4 + is-decimal: 1.0.4 + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-decimal@1.0.4: {} + + is-decimal@2.0.1: {} + + is-docker@2.2.1: {} + + is-empty@1.2.0: {} + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-hexadecimal@1.0.4: {} + + is-hexadecimal@2.0.1: {} + + is-map@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-plain-obj@4.1.0: {} + + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.7 + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-standalone-pwa@0.1.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.19 + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isexe@3.1.1: {} + + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jackspeak@4.1.0: + dependencies: + '@isaacs/cliui': 8.0.2 + + jiti@2.4.2: {} + + journalize@2.6.0: {} + + js-tokens@4.0.0: {} + + js-tokens@9.0.1: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsdoc-type-pratt-parser@4.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@3.0.2: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json-stringify-pretty-compact@4.0.0: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + katex@0.16.22: + dependencies: + commander: 8.3.0 + + kdbush@4.0.2: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + khroma@2.1.0: {} + + kleur@3.0.3: {} + + kleur@4.1.5: {} + + knip@5.50.5(@types/node@22.14.1)(typescript@5.8.3): + dependencies: + '@nodelib/fs.walk': 1.2.8 + '@types/node': 22.14.1 + easy-table: 1.2.0 + enhanced-resolve: 5.18.1 + fast-glob: 3.3.3 + jiti: 2.4.2 + js-yaml: 4.1.0 + minimist: 1.2.8 + picocolors: 1.1.1 + picomatch: 4.0.2 + pretty-ms: 9.2.0 + smol-toml: 1.3.3 + strip-json-comments: 5.0.1 + typescript: 5.8.3 + zod: 3.24.3 + zod-validation-error: 3.4.0(zod@3.24.3) + + known-css-properties@0.35.0: {} + + layout-base@1.0.2: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lilconfig@2.1.0: {} + + lines-and-columns@2.0.4: {} + + load-plugin@6.0.3: + dependencies: + '@npmcli/config': 8.3.4 + import-meta-resolve: 4.1.0 + transitivePeerDependencies: + - bluebird + + locate-character@3.0.0: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.17.21: {} + + lodash.merge@4.6.2: {} + + lodash.startcase@4.4.0: {} + + lodash@4.17.21: {} + + longest-streak@3.1.0: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.1.3: {} + + loupe@3.2.0: {} + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + lowlight@1.20.0: + dependencies: + fault: 1.0.4 + highlight.js: 10.7.3 + + lru-cache@10.4.3: {} + + lru-cache@11.1.0: {} + + lz-string@1.5.0: {} + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + map-or-similar@1.5.0: {} + + maplibre-gl@5.15.0: + dependencies: + '@mapbox/geojson-rewind': 0.5.2 + '@mapbox/jsonlint-lines-primitives': 2.0.2 + '@mapbox/point-geometry': 1.1.0 + '@mapbox/tiny-sdf': 2.0.7 + '@mapbox/unitbezier': 0.0.1 + '@mapbox/vector-tile': 2.0.4 + '@mapbox/whoots-js': 3.1.0 + '@maplibre/maplibre-gl-style-spec': 24.4.1 + '@maplibre/mlt': 1.1.2 + '@maplibre/vt-pbf': 4.2.0 + '@types/geojson': 7946.0.16 + '@types/geojson-vt': 3.2.5 + '@types/supercluster': 7.1.3 + earcut: 3.0.2 + geojson-vt: 4.0.2 + gl-matrix: 3.4.4 + kdbush: 4.0.2 + murmurhash-js: 1.0.0 + pbf: 4.0.1 + potpack: 2.1.0 + quickselect: 3.0.0 + supercluster: 8.0.1 + tinyqueue: 3.0.0 + + marked-smartypants@1.1.9(marked@15.0.8): + dependencies: + marked: 15.0.8 + smartypants: 0.2.2 + + marked@15.0.8: {} + + math-intrinsics@1.1.0: {} + + mdast-util-from-markdown@1.3.1: + dependencies: + '@types/mdast': 3.0.15 + '@types/unist': 2.0.11 + decode-named-character-reference: 1.1.0 + mdast-util-to-string: 3.2.0 + micromark: 3.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-decode-string: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + unist-util-stringify-position: 3.0.3 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + + mdast-util-from-markdown@2.0.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.1.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-expression@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-jsx@3.2.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx@3.0.0: + dependencies: + mdast-util-from-markdown: 2.0.2 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdxjs-esm@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.0 + + mdast-util-to-markdown@2.1.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.0.0 + zwitch: 2.0.4 + + mdast-util-to-string@3.2.0: + dependencies: + '@types/mdast': 3.0.15 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + memoizerific@1.11.3: + dependencies: + map-or-similar: 1.5.0 + + merge2@1.4.1: {} + + mermaid@10.9.3: + dependencies: + '@braintree/sanitize-url': 6.0.4 + '@types/d3-scale': 4.0.9 + '@types/d3-scale-chromatic': 3.1.0 + cytoscape: 3.31.2 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.31.2) + d3: 7.9.0 + d3-sankey: 0.12.3 + dagre-d3-es: 7.0.10 + dayjs: 1.11.13 + dompurify: 3.1.6 + elkjs: 0.9.3 + katex: 0.16.22 + khroma: 2.1.0 + lodash-es: 4.17.21 + mdast-util-from-markdown: 1.3.1 + non-layered-tidy-tree-layout: 2.0.2 + stylis: 4.3.6 + ts-dedent: 2.2.0 + uuid: 9.0.1 + web-worker: 1.5.0 + transitivePeerDependencies: + - supports-color + + micromark-core-commonmark@1.1.0: + dependencies: + decode-named-character-reference: 1.1.0 + micromark-factory-destination: 1.1.0 + micromark-factory-label: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-factory-title: 1.1.0 + micromark-factory-whitespace: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-classify-character: 1.1.0 + micromark-util-html-tag-name: 1.2.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-core-commonmark@2.0.3: + dependencies: + decode-named-character-reference: 1.1.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-expression@3.0.1: + dependencies: + '@types/estree': 1.0.7 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-jsx@3.0.2: + dependencies: + '@types/estree': 1.0.7 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.2 + + micromark-extension-mdx-md@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-mdxjs-esm@3.0.0: + dependencies: + '@types/estree': 1.0.7 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 + + micromark-extension-mdxjs@3.0.0: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + micromark-extension-mdx-expression: 3.0.1 + micromark-extension-mdx-jsx: 3.0.2 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs-esm: 3.0.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-destination@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-label@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-mdx-expression@2.0.3: + dependencies: + '@types/estree': 1.0.7 + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 + + micromark-factory-space@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-types: 1.1.0 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 + + micromark-factory-title@1.1.0: + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-whitespace@1.1.0: + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-character@1.2.0: + dependencies: + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-chunked@1.1.0: + dependencies: + micromark-util-symbol: 1.1.0 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-combine-extensions@1.1.0: + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-decode-numeric-character-reference@1.1.0: + dependencies: + micromark-util-symbol: 1.1.0 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@1.1.0: + dependencies: + decode-named-character-reference: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-symbol: 1.1.0 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@1.1.0: {} + + micromark-util-encode@2.0.1: {} + + micromark-util-events-to-acorn@2.0.3: + dependencies: + '@types/estree': 1.0.7 + '@types/unist': 3.0.3 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.2 + + micromark-util-html-tag-name@1.2.0: {} + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@1.1.0: + dependencies: + micromark-util-symbol: 1.1.0 + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@1.1.0: + dependencies: + micromark-util-types: 1.1.0 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.2 + + micromark-util-sanitize-uri@1.2.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-encode: 1.1.0 + micromark-util-symbol: 1.1.0 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@1.1.0: + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-util-subtokenize@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-symbol@1.1.0: {} + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@1.1.0: {} + + micromark-util-types@2.0.2: {} + + micromark@3.2.0: + dependencies: + '@types/debug': 4.1.12 + debug: 4.4.0 + decode-named-character-reference: 1.1.0 + micromark-core-commonmark: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-combine-extensions: 1.1.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-encode: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + + micromark@4.0.2: + dependencies: + '@types/debug': 4.1.12 + debug: 4.4.0 + decode-named-character-reference: 1.1.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + min-indent@1.0.1: {} + + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mp4box@0.5.4: {} + + mri@1.2.0: {} + + mrmime@2.0.1: {} + + ms@2.1.3: {} + + murmurhash-js@1.0.0: {} + + nanoid@3.3.11: {} + + natural-compare@1.4.0: {} + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + node-addon-api@7.1.1: + optional: true + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + non-layered-tidy-tree-layout@2.0.2: {} + + nopt@7.2.1: + dependencies: + abbrev: 2.0.0 + + normalize-package-data@6.0.2: + dependencies: + hosted-git-info: 7.0.2 + semver: 7.7.1 + validate-npm-package-license: 3.0.4 + + npm-install-checks@6.3.0: + dependencies: + semver: 7.7.1 + + npm-normalize-package-bin@3.0.1: {} + + npm-package-arg@11.0.3: + dependencies: + hosted-git-info: 7.0.2 + proc-log: 4.2.0 + semver: 7.7.1 + validate-npm-package-name: 5.0.1 + + npm-pick-manifest@9.1.0: + dependencies: + npm-install-checks: 6.3.0 + npm-normalize-package-bin: 3.0.1 + npm-package-arg: 11.0.3 + semver: 7.7.1 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + os-tmpdir@1.0.2: {} + + outdent@0.5.0: {} + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@2.1.0: {} + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + package-manager-detector@0.2.11: + dependencies: + quansync: 0.2.10 + + package-manager-detector@1.2.0: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-entities@2.0.0: + dependencies: + character-entities: 1.2.4 + character-entities-legacy: 1.1.4 + character-reference-invalid: 1.1.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + is-hexadecimal: 1.0.4 + + parse-entities@4.0.2: + dependencies: + '@types/unist': 2.0.11 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.1.0 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + + parse-json@7.1.1: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 3.0.2 + lines-and-columns: 2.0.4 + type-fest: 3.13.1 + + parse-ms@4.0.0: {} + + parse5@7.2.1: + dependencies: + entities: 4.5.0 + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-scurry@2.0.0: + dependencies: + lru-cache: 11.1.0 + minipass: 7.1.2 + + path-type@4.0.0: {} + + pathe@2.0.3: {} + + pathval@2.0.0: {} + + pbf@4.0.1: + dependencies: + resolve-protobuf-schema: 2.1.0 + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pify@4.0.1: {} + + pmtiles@4.3.2: + dependencies: + fflate: 0.8.2 + + polished@4.3.1: + dependencies: + '@babel/runtime': 7.27.0 + + possible-typed-array-names@1.1.0: {} + + postcss-load-config@3.1.4(postcss@8.5.3): + dependencies: + lilconfig: 2.1.0 + yaml: 1.10.2 + optionalDependencies: + postcss: 8.5.3 + + postcss-safe-parser@7.0.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-scss@4.0.9(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-selector-parser@7.1.0: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss@8.5.3: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + potpack@2.1.0: {} + + prelude-ls@1.2.1: {} + + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.3.0 + + prettier-plugin-svelte@3.3.3(prettier@3.5.3)(svelte@5.28.1): + dependencies: + prettier: 3.5.3 + svelte: 5.28.1 + + prettier@2.8.8: {} + + prettier@3.5.3: {} + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + pretty-ms@9.2.0: + dependencies: + parse-ms: 4.0.0 + + prism-themes@1.9.0: {} + + prismjs@1.27.0: {} + + prismjs@1.30.0: {} + + proc-log@4.2.0: {} + + process@0.11.10: {} + + progress@2.0.3: {} + + promise-inflight@1.0.1: {} + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + proper-url-join@2.1.2: + dependencies: + query-string: 7.1.3 + + property-information@5.6.0: + dependencies: + xtend: 4.0.2 + + protocol-buffers-schema@3.6.0: {} + + publint@0.3.12: + dependencies: + '@publint/pack': 0.1.2 + package-manager-detector: 1.2.0 + picocolors: 1.1.1 + sade: 1.8.1 + + punycode@2.3.1: {} + + pym.js@1.3.2: {} + + quansync@0.2.10: {} + + query-string@7.1.3: + dependencies: + decode-uri-component: 0.2.2 + filter-obj: 1.1.0 + split-on-first: 1.1.0 + strict-uri-encode: 2.0.0 + + queue-microtask@1.2.3: {} + + quickselect@3.0.0: {} + + react-colorful@5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + react-confetti@6.4.0(react@18.3.1): + dependencies: + react: 18.3.1 + tween-functions: 1.2.0 + + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react-is@16.13.1: {} + + react-is@17.0.2: {} + + react-syntax-highlighter@15.6.1(react@18.3.1): + dependencies: + '@babel/runtime': 7.27.0 + highlight.js: 10.7.3 + highlightjs-vue: 1.0.0 + lowlight: 1.20.0 + prismjs: 1.30.0 + react: 18.3.1 + refractor: 3.6.0 + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + read-package-json-fast@3.0.2: + dependencies: + json-parse-even-better-errors: 3.0.2 + npm-normalize-package-bin: 3.0.1 + + read-yaml-file@1.1.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@4.1.2: {} + + recast@0.23.11: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.1 + + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + refractor@3.6.0: + dependencies: + hastscript: 6.0.0 + parse-entities: 2.0.0 + prismjs: 1.27.0 + + regenerator-runtime@0.14.1: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regexpp@3.2.0: {} + + remark-mdx@3.1.0: + dependencies: + mdast-util-mdx: 3.0.0 + micromark-extension-mdxjs: 3.0.0 + transitivePeerDependencies: + - supports-color + + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.2 + micromark-util-types: 2.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-stringify@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.2 + unified: 11.0.5 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-protobuf-schema@2.1.0: + dependencies: + protocol-buffers-schema: 3.6.0 + + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retry@0.12.0: {} + + reusify@1.1.0: {} + + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rimraf@6.0.1: + dependencies: + glob: 11.0.1 + package-json-from-dist: 1.0.1 + + robust-predicates@3.0.2: {} + + rollup@4.40.0: + dependencies: + '@types/estree': 1.0.7 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.40.0 + '@rollup/rollup-android-arm64': 4.40.0 + '@rollup/rollup-darwin-arm64': 4.40.0 + '@rollup/rollup-darwin-x64': 4.40.0 + '@rollup/rollup-freebsd-arm64': 4.40.0 + '@rollup/rollup-freebsd-x64': 4.40.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.40.0 + '@rollup/rollup-linux-arm-musleabihf': 4.40.0 + '@rollup/rollup-linux-arm64-gnu': 4.40.0 + '@rollup/rollup-linux-arm64-musl': 4.40.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.40.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.40.0 + '@rollup/rollup-linux-riscv64-gnu': 4.40.0 + '@rollup/rollup-linux-riscv64-musl': 4.40.0 + '@rollup/rollup-linux-s390x-gnu': 4.40.0 + '@rollup/rollup-linux-x64-gnu': 4.40.0 + '@rollup/rollup-linux-x64-musl': 4.40.0 + '@rollup/rollup-win32-arm64-msvc': 4.40.0 + '@rollup/rollup-win32-ia32-msvc': 4.40.0 + '@rollup/rollup-win32-x64-msvc': 4.40.0 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rw@1.3.3: {} + + sade@1.8.1: + dependencies: + mri: 1.2.0 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safer-buffer@2.1.2: {} + + sander@0.5.1: + dependencies: + es6-promise: 3.3.1 + graceful-fs: 4.2.11 + mkdirp: 0.5.6 + rimraf: 2.7.1 + + sass@1.86.3: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.1 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + + semver@6.3.1: {} + + semver@7.7.1: {} + + set-cookie-parser@2.7.1: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + sirv@3.0.1: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + + slash@3.0.0: {} + + slugify@1.6.6: {} + + smartypants@0.2.2: {} + + smol-toml@1.3.3: {} + + sorcery@0.11.1: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + buffer-crc32: 1.0.0 + minimist: 1.2.8 + sander: 0.5.1 + + source-map-js@1.2.1: {} + + source-map-resolve@0.6.0: + dependencies: + atob: 2.1.2 + decode-uri-component: 0.2.2 + + source-map@0.6.1: {} + + space-separated-tokens@1.1.5: {} + + spark-md5@3.0.2: {} + + spawndamnit@3.0.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.21 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.21 + + spdx-license-ids@3.0.21: {} + + split-on-first@1.1.0: {} + + sprintf-js@1.0.3: {} + + stackback@0.0.2: {} + + std-env@3.9.0: {} + + storybook-addon-rtl@1.1.0: {} + + storybook@8.6.12(prettier@3.5.3): + dependencies: + '@storybook/core': 8.6.12(prettier@3.5.3)(storybook@8.6.12(prettier@3.5.3)) + optionalDependencies: + prettier: 3.5.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + strict-uri-encode@2.0.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@6.1.0: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 10.4.0 + strip-ansi: 7.1.0 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.9 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom@3.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + + strip-json-comments@5.0.1: {} + + strip-literal@3.0.0: + dependencies: + js-tokens: 9.0.1 + + stylis@4.3.6: {} + + supercluster@8.0.1: + dependencies: + kdbush: 4.0.2 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@9.4.0: {} + + supports-preserve-symlinks-flag@1.0.0: {} + + svelte-ast-print@0.4.2(svelte@5.28.1): + dependencies: + esrap: 1.2.2 + svelte: 5.28.1 + zimmerframe: 1.1.2 + + svelte-check@4.1.6(picomatch@4.0.2)(svelte@5.28.1)(typescript@5.8.3): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + chokidar: 4.0.3 + fdir: 6.4.3(picomatch@4.0.2) + picocolors: 1.1.1 + sade: 1.8.1 + svelte: 5.28.1 + typescript: 5.8.3 + transitivePeerDependencies: + - picomatch + + svelte-eslint-parser@1.1.2(svelte@5.28.1): + dependencies: + eslint-scope: 8.3.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + postcss: 8.5.3 + postcss-scss: 4.0.9(postcss@8.5.3) + postcss-selector-parser: 7.1.0 + optionalDependencies: + svelte: 5.28.1 + + svelte-fa@4.0.4(svelte@5.28.1): + dependencies: + svelte: 5.28.1 + + svelte-intersection-observer@1.0.0: {} + + svelte-preprocess@5.1.4(postcss-load-config@3.1.4(postcss@8.5.3))(postcss@8.5.3)(sass@1.86.3)(svelte@5.28.1)(typescript@5.8.3): + dependencies: + '@types/pug': 2.0.10 + detect-indent: 6.1.0 + magic-string: 0.30.17 + sorcery: 0.11.1 + strip-indent: 3.0.0 + svelte: 5.28.1 + optionalDependencies: + postcss: 8.5.3 + postcss-load-config: 3.1.4(postcss@8.5.3) + sass: 1.86.3 + typescript: 5.8.3 + + svelte2tsx@0.7.36(svelte@5.28.1)(typescript@5.8.3): + dependencies: + dedent-js: 1.0.1 + pascal-case: 3.1.2 + svelte: 5.28.1 + typescript: 5.8.3 + + svelte@5.28.1: + dependencies: + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.5.0 + '@sveltejs/acorn-typescript': 1.0.5(acorn@8.14.1) + '@types/estree': 1.0.7 + acorn: 8.14.1 + aria-query: 5.3.2 + axobject-query: 4.1.0 + clsx: 2.1.1 + esm-env: 1.2.2 + esrap: 1.4.6 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.17 + zimmerframe: 1.1.2 + + sveltedoc-parser@4.2.1: + dependencies: + eslint: 8.4.1 + espree: 9.2.0 + htmlparser2-svelte: 4.1.0 + transitivePeerDependencies: + - supports-color + + synckit@0.11.4: + dependencies: + '@pkgr/core': 0.2.4 + tslib: 2.8.1 + + tapable@2.2.1: {} + + term-size@2.2.1: {} + + text-table@0.2.0: {} + + tiny-invariant@1.3.3: {} + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyglobby@0.2.12: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + + tinyglobby@0.2.14: + dependencies: + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + + tinypool@1.1.1: {} + + tinyqueue@3.0.0: {} + + tinyrainbow@1.2.0: {} + + tinyrainbow@2.0.0: {} + + tinyspy@3.0.2: {} + + tinyspy@4.0.3: {} + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + totalist@3.0.1: {} + + tr46@0.0.3: {} + + trough@2.2.0: {} + + ts-api-utils@2.1.0(typescript@5.8.3): + dependencies: + typescript: 5.8.3 + + ts-dedent@2.2.0: {} + + tslib@2.8.1: {} + + tween-functions@1.2.0: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + type-fest@2.19.0: {} + + type-fest@3.13.1: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typedarray@0.0.6: {} + + typescript-eslint@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/parser': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + '@typescript-eslint/utils': 8.30.1(eslint@9.25.0(jiti@2.4.2))(typescript@5.8.3) + eslint: 9.25.0(jiti@2.4.2) + typescript: 5.8.3 + transitivePeerDependencies: + - supports-color + + typescript@5.8.3: {} + + ua-is-frozen@0.1.2: {} + + ua-parser-js@2.0.3: + dependencies: + '@types/node-fetch': 2.6.12 + detect-europe-js: 0.1.2 + is-standalone-pwa: 0.1.1 + node-fetch: 2.7.0 + ua-is-frozen: 0.1.2 + transitivePeerDependencies: + - encoding + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + undici-types@6.21.0: {} + + unified-engine@11.2.2: + dependencies: + '@types/concat-stream': 2.0.3 + '@types/debug': 4.1.12 + '@types/is-empty': 1.2.3 + '@types/node': 22.14.1 + '@types/unist': 3.0.3 + concat-stream: 2.0.0 + debug: 4.4.0 + extend: 3.0.2 + glob: 10.4.5 + ignore: 6.0.2 + is-empty: 1.2.0 + is-plain-obj: 4.1.0 + load-plugin: 6.0.3 + parse-json: 7.1.1 + trough: 2.2.0 + unist-util-inspect: 8.1.0 + vfile: 6.0.3 + vfile-message: 4.0.2 + vfile-reporter: 8.1.1 + vfile-statistics: 3.0.0 + yaml: 2.7.1 + transitivePeerDependencies: + - bluebird + - supports-color + + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unist-util-inspect@8.1.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position-from-estree@2.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@3.0.3: + dependencies: + '@types/unist': 2.0.11 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + unplugin@1.16.1: + dependencies: + acorn: 8.14.1 + webpack-virtual-modules: 0.6.2 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.0 + is-typed-array: 1.1.15 + which-typed-array: 1.1.19 + + uuid@9.0.1: {} + + uvu@0.5.6: + dependencies: + dequal: 2.0.3 + diff: 5.2.0 + kleur: 4.1.5 + sade: 1.8.1 + + v8-compile-cache@2.4.0: {} + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + validate-npm-package-name@5.0.1: {} + + vfile-message@4.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile-reporter@8.1.1: + dependencies: + '@types/supports-color': 8.1.3 + string-width: 6.1.0 + supports-color: 9.4.0 + unist-util-stringify-position: 4.0.0 + vfile: 6.0.3 + vfile-message: 4.0.2 + vfile-sort: 4.0.0 + vfile-statistics: 3.0.0 + + vfile-sort@4.0.0: + dependencies: + vfile: 6.0.3 + vfile-message: 4.0.2 + + vfile-statistics@3.0.0: + dependencies: + vfile: 6.0.3 + vfile-message: 4.0.2 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.2 + + vite-node@3.2.4(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1): + dependencies: + cac: 6.7.14 + debug: 4.4.1 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1): + dependencies: + esbuild: 0.25.2 + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + postcss: 8.5.3 + rollup: 4.40.0 + tinyglobby: 0.2.12 + optionalDependencies: + '@types/node': 22.14.1 + fsevents: 2.3.3 + jiti: 2.4.2 + sass: 1.86.3 + yaml: 2.7.1 + + vitefu@1.0.6(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)): + optionalDependencies: + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + + vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.2.0 + debug: 4.4.1 + expect-type: 1.2.2 + magic-string: 0.30.17 + pathe: 2.0.3 + picomatch: 4.0.2 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.14 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 6.3.2(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + vite-node: 3.2.4(@types/node@22.14.1)(jiti@2.4.2)(sass@1.86.3)(yaml@2.7.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 + '@types/node': 22.14.1 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + walk-up-path@3.0.1: {} + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + optional: true + + web-worker@1.5.0: {} + + webidl-conversions@3.0.1: {} + + webpack-virtual-modules@0.6.2: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.0 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.19: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@4.0.0: + dependencies: + isexe: 3.1.1 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + ws@8.18.1: {} + + xtend@4.0.2: {} + + yaml@1.10.2: {} + + yaml@2.7.1: {} + + yocto-queue@0.1.0: {} + + zimmerframe@1.1.2: {} + + zod-validation-error@3.4.0(zod@3.24.3): + dependencies: + zod: 3.24.3 + + zod@3.24.3: {} + + zwitch@2.0.4: {} diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 0000000..516fe50 --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/actions/cssVariables/cssVariables.mdx b/src/actions/cssVariables/cssVariables.mdx new file mode 100644 index 0000000..c67b635 --- /dev/null +++ b/src/actions/cssVariables/cssVariables.mdx @@ -0,0 +1,39 @@ +import { Meta } from '@storybook/blocks'; +import { parameters } from '../../docs/utils/docsPage.js'; + + + +# `cssVariables` + +An action you can use to easily set [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) on HTML elements. Useful for passing JavaScript values to your component SCSS like this: + +```svelte + + + +
+

My text...

+
+ + +``` diff --git a/src/actions/cssVariables/index.ts b/src/actions/cssVariables/index.ts new file mode 100644 index 0000000..47b2326 --- /dev/null +++ b/src/actions/cssVariables/index.ts @@ -0,0 +1,20 @@ +// Shamelessly stolen from: https://github.com/kaisermann/svelte-css-vars +export default (node: HTMLElement, props: Record) => { + Object.entries(props).forEach(([key, value]) => { + node.style.setProperty(`--${key}`, value); + }); + + return { + update(newProps: Record) { + Object.entries(newProps).forEach(([key, value]) => { + node.style.setProperty(`--${key}`, value); + delete props[key]; + }); + + Object.keys(props).forEach((name) => { + node.style.removeProperty(`--${name}`); + }); + props = newProps; + }, + }; +}; diff --git a/src/actions/resizeObserver/index.ts b/src/actions/resizeObserver/index.ts new file mode 100644 index 0000000..10cf699 --- /dev/null +++ b/src/actions/resizeObserver/index.ts @@ -0,0 +1,25 @@ +// Shamelessly stolen from https://github.com/sveltejs/svelte/issues/7583#issue-1260717165 +let observer: ResizeObserver; +let callbacks: WeakMap unknown>; + +export default (element: HTMLElement, onResize: (el: Element) => unknown) => { + if (!observer) { + callbacks = new WeakMap(); + observer = new ResizeObserver((entries) => { + for (const entry of entries) { + const onResize = callbacks.get(entry.target); + if (onResize) onResize(entry.target); + } + }); + } + + callbacks.set(element, onResize); + observer.observe(element); + + return { + destroy: () => { + callbacks.delete(element); + observer.unobserve(element); + }, + }; +}; diff --git a/src/actions/resizeObserver/resizeObserver.mdx b/src/actions/resizeObserver/resizeObserver.mdx new file mode 100644 index 0000000..b56549a --- /dev/null +++ b/src/actions/resizeObserver/resizeObserver.mdx @@ -0,0 +1,20 @@ +import { Meta } from '@storybook/blocks'; +import { parameters } from '../../docs/utils/docsPage.js'; + + + +# `resizeObserver` + +An action you can use to easily to check when a DOM element's dimensions change using the [Resize Observer API](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver). Use it like this: + +```svelte + + +
(elementWidth = element.clientWidth)}> + My width is: {elementWidth} +
+``` diff --git a/src/app.html b/src/app.html new file mode 100644 index 0000000..6151681 --- /dev/null +++ b/src/app.html @@ -0,0 +1,11 @@ + + + + + + %sveltekit.head% + + + %sveltekit.body% + + diff --git a/src/components/@types/global.ts b/src/components/@types/global.ts new file mode 100644 index 0000000..9aaee2e --- /dev/null +++ b/src/components/@types/global.ts @@ -0,0 +1,128 @@ +import type { Component } from 'svelte'; +import type { TransitionOptions } from '../ScrollerVideo/ts/ScrollerVideo.js'; +import type { ScrollerVideoState } from '../ScrollerVideo/ts/state.svelte.js'; +/** + * Used for the list of + {/each} + + + + diff --git a/src/components/Framer/Framer.mdx b/src/components/Framer/Framer.mdx new file mode 100644 index 0000000..2d0b8a2 --- /dev/null +++ b/src/components/Framer/Framer.mdx @@ -0,0 +1,19 @@ +import { Meta } from '@storybook/blocks'; + +import * as FramerStories from './Framer.stories.svelte'; + + + +# FeaturePhoto + +An embed tool for development in the graphics kit. + +```svelte + + + +``` diff --git a/src/components/Framer/Framer.stories.svelte b/src/components/Framer/Framer.stories.svelte new file mode 100644 index 0000000..fa0a68d --- /dev/null +++ b/src/components/Framer/Framer.stories.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/components/Framer/Framer.svelte b/src/components/Framer/Framer.svelte new file mode 100644 index 0000000..4c7937e --- /dev/null +++ b/src/components/Framer/Framer.svelte @@ -0,0 +1,225 @@ + + +
+
+ +
+ + {#if embeds.length === 0} +
+

No embeds to show.

+
+ {:else} + {#if searchType === 'typeahead'} +
+ + embedTitles[d.index]} + data={embeds.map((embed, index) => ({ index, embed }))} + showDropdownOnFocus={true} + onselect={(detail) => { + if (typeof window !== 'undefined') { + window.localStorage.setItem( + 'framer-active-embed', + detail.original.embed + ); + } + activeEmbed = detail.original.embed; + // activeEmbedIndex = detail.original.index; + }} + /> +
+ {:else} + + {/if} + +
+

Preview

+
+
+ {/if} +
+ + + +{#if embeds.length > 0} + +{/if} + + diff --git a/src/components/Framer/Resizer/index.svelte b/src/components/Framer/Resizer/index.svelte new file mode 100644 index 0000000..e406ed9 --- /dev/null +++ b/src/components/Framer/Resizer/index.svelte @@ -0,0 +1,243 @@ + + + + +
+
+
+ {pixelLabel || $width}px +
+ +
+
+
+
+ +
+
+ + diff --git a/src/components/Framer/Typeahead/Search.svelte b/src/components/Framer/Typeahead/Search.svelte new file mode 100644 index 0000000..9e8566f --- /dev/null +++ b/src/components/Framer/Typeahead/Search.svelte @@ -0,0 +1,101 @@ + + +
{ + e.preventDefault(); + }} +> + + +
diff --git a/src/components/Framer/Typeahead/fuzzy.ts b/src/components/Framer/Typeahead/fuzzy.ts new file mode 100644 index 0000000..d04abfa --- /dev/null +++ b/src/components/Framer/Typeahead/fuzzy.ts @@ -0,0 +1,108 @@ +interface MatchOptions { + pre?: string; + post?: string; + caseSensitive?: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + extract?: (arg: any) => string; +} + +interface MatchResult { + rendered: string; + score: number; +} + +interface FilterResult { + string: string; + score: number; + index: number; + original: T; +} + +const fuzzy = { + simpleFilter(pattern: string, array: string[]): string[] { + return array.filter((str) => this.test(pattern, str)); + }, + + test(pattern: string, str: string): boolean { + return this.match(pattern, str) !== null; + }, + + match( + pattern: string, + str: string, + opts: MatchOptions = {} + ): MatchResult | null { + let patternIdx = 0; + const result: string[] = []; + const len = str.length; + let totalScore = 0; + let currScore = 0; + const pre = opts.pre || ''; + const post = opts.post || ''; + const compareString = opts.caseSensitive ? str : str.toLowerCase(); + pattern = opts.caseSensitive ? pattern : pattern.toLowerCase(); + + for (let idx = 0; idx < len; idx++) { + let ch = str[idx]; + if (compareString[idx] === pattern[patternIdx]) { + ch = pre + ch + post; + patternIdx += 1; + currScore += 1 + currScore; + } else { + currScore = 0; + } + totalScore += currScore; + result[result.length] = ch; + } + + if (patternIdx === pattern.length) { + totalScore = compareString === pattern ? Infinity : totalScore; + return { rendered: result.join(''), score: totalScore }; + } + + return null; + }, + + filter( + pattern: string, + arr: T[], + opts: MatchOptions = {} + ): FilterResult[] { + if (!arr || arr.length === 0) { + return []; + } + if (typeof pattern !== 'string') { + return arr.map((element, index) => ({ + string: element as unknown as string, + score: 0, + index, + original: element, + })); + } + + return arr + .reduce[]>((prev, element, idx) => { + let str = element as unknown as string; + if (opts.extract) { + str = opts.extract(element); + } + const rendered = this.match(pattern, str, opts); + if (rendered != null) { + prev.push({ + string: rendered.rendered, + score: rendered.score, + index: idx, + original: element, + }); + } + return prev; + }, []) + .sort((a, b) => { + const compare = b.score - a.score; + if (compare) return compare; + return a.index - b.index; + }); + }, +}; + +export default fuzzy; diff --git a/src/components/Framer/Typeahead/index.svelte b/src/components/Framer/Typeahead/index.svelte new file mode 100644 index 0000000..798f219 --- /dev/null +++ b/src/components/Framer/Typeahead/index.svelte @@ -0,0 +1,375 @@ + + + { + if (!hideDropdown && !comboboxRef?.contains(target as Node)) { + close(); + } + }} +/> + +
0} + aria-controls="{id}-listbox" + aria-expanded={showResults || + (isFocused && value.length > 0 && results.length === 0)} + id="{id}-typeahead" +> + = 0 && !hideDropdown && results.length > 0 + ) ? + `${id}-result-${selectedIndex}` + : null} + onfocus={() => { + open(); + if (showDropdownOnFocus) { + showResults = true; + isFocused = true; + } + }} + onclear={open} + onkeydown={(e: KeyboardEvent) => { + if (results.length === 0) return; + + switch (e.key) { + case 'Enter': + select(); + break; + case 'ArrowDown': + e.preventDefault(); + change(1); + break; + case 'ArrowUp': + e.preventDefault(); + change(-1); + break; + case 'Escape': + e.preventDefault(); + value = ''; + searchRef?.focus(); + close(); + break; + } + }} + {...restProps} + /> +
    + {#if showResults && !hideDropdown} + {#each results as result, index} +
  • { + if (result.disabled) return; + selectedIndex = index; + select(); + }} + onkeyup={(e) => { + if (e.key !== 'Enter') return; + if (result.disabled) return; + selectedIndex = index; + select(); + }} + onmouseenter={() => { + if (result.disabled) return; + selectedIndex = index; + }} + > + {@html result.string} +
  • + {/each} + {/if} + {#if value.length > 0 && results.length === 0} +
  • No embeds found...
  • + {/if} +
+
+ + diff --git a/src/components/Framer/stores.ts b/src/components/Framer/stores.ts new file mode 100644 index 0000000..69e7100 --- /dev/null +++ b/src/components/Framer/stores.ts @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store'; + +export const width = writable(660); diff --git a/src/components/Framer/uniqNames.ts b/src/components/Framer/uniqNames.ts new file mode 100644 index 0000000..010ab3d --- /dev/null +++ b/src/components/Framer/uniqNames.ts @@ -0,0 +1,54 @@ +export default (embeds: string[]) => { + const nakedEmbeds = embeds + .map((e) => e.replace(/\?.+$/, '')) + .map((e) => e.replace(/index\.html$/, '')) + .map((e) => e.replace(/^http[s]*:\/\/[\w.]+\.com/, '')); + + // If just one, get the last path part + if (nakedEmbeds.length === 1) { + return [ + nakedEmbeds[0] + .split('/') + .filter((d) => d) + .slice(-1)[0], + ]; + } + + // If many, test each path part for unique-ness + const test = nakedEmbeds[0]; + let replacementForward = 0; + for (const i in test.split('/')) { + const pathPart = test.split('/')[i]; + const notUniq = nakedEmbeds.every((e) => e.split('/')[i] === pathPart); + if (notUniq) { + replacementForward += 1; + } else { + break; + } + } + + if (replacementForward === test.split('/').length) return nakedEmbeds; + + let replacementBackward = 0; + for (const i in test.split('/').reverse()) { + const pathPart = test.split('/').reverse()[i]; + const notUniq = nakedEmbeds.every( + (e) => e.split('/').reverse()[i] === pathPart + ); + if (notUniq) { + replacementBackward += 1; + } else { + break; + } + } + + return nakedEmbeds.map((e) => { + if (replacementBackward > 0) { + return e + .split('/') + .slice(replacementForward, replacementBackward * -1) + .join('/'); + } + return e.split('/').slice(replacementForward).join('/'); + }); +}; diff --git a/src/components/Functions/Utils.mdx b/src/components/Functions/Utils.mdx new file mode 100644 index 0000000..f4e1b54 --- /dev/null +++ b/src/components/Functions/Utils.mdx @@ -0,0 +1,23 @@ +import { Meta } from '@storybook/blocks'; + +import * as UtilFunctionStories from './Utils.stories.svelte'; + + + +# Util functions + +This library provides utility functions that can be used across various components and applications. + +## Prettify date in the Reuters format + +The function `prettifyDate` formats the input string, which is expected to be in English, to format the month and time designator (AM/PM) according to the Reuters style guide. The function is case agnostic and will format both full month names and their 3-letter abbreviations (i.e. `Mar` or `Jun`) correctly. + +```javascript +import { prettifyDate } from '@reuters-graphics/graphics-components'; + +// Example usage +prettifyDate('January 1, 2023, 10:00 AM'); // returns 'Jan. 1, 2023, 10:00 a.m.' +prettifyDate('Jan 1, 2023, 10:00 PM'); // returns 'Jan. 1, 2023, 10:00 p.m.' +prettifyDate('MAR. 2025'); // returns 'March 2025' +prettifyDate('sep. 1, 2023, 10:00PM'); // returns 'Sept. 1, 2023, 10:00 p.m.' +``` diff --git a/src/components/Functions/Utils.stories.svelte b/src/components/Functions/Utils.stories.svelte new file mode 100644 index 0000000..fe7b28a --- /dev/null +++ b/src/components/Functions/Utils.stories.svelte @@ -0,0 +1,9 @@ + + + diff --git a/src/components/GraphicBlock/GraphicBlock.mdx b/src/components/GraphicBlock/GraphicBlock.mdx new file mode 100644 index 0000000..e5ff886 --- /dev/null +++ b/src/components/GraphicBlock/GraphicBlock.mdx @@ -0,0 +1,215 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as GraphicBlockStories from './GraphicBlock.stories.svelte'; + + + +# GraphicBlock + +The `GraphicBlock` component is a special derivative of the [Block](?path=/docs/components-page-layout-block--docs) component that wraps around your graphic. It also adds a title, description, notes and other text elements. + +Many other Reuters Graphics components use `GraphicBlock` to wrap graphics with styled text. + +```svelte + + + + +
+ +``` + + + +## Using with ai2svelte and ArchieML docs + +The `GraphicBlock` component is built to handle [ai2svelte](https://github.com/reuters-graphics/ai2svelte) graphics in graphics kit. + +You'll likely get your text value from an ArchieML doc... + +```yaml +# ArchieML doc +[blocks] +type: ai-graphic +width: normal +chart: AiMap # IMPORTANT: This must match the name of the ai2svelte chart you import in App.svelte +title: Earthquake in Haiti +description: The 7.2-magnitude earthquake struck at 8:29 a.m. EST, Aug. 14, 2021. +notes: \Note: A shakemap represents the ground shaking produced by an earthquake. + +\Source: USGIS +:end +altText: A map that shows the shake intensity of the earthquake, which was worst in central Haiti. +:end +[] +``` + +... which you'll parse out of a ArchieML block object before passing to the `GraphicBlock` component. + +To pass your ai2svelte graphic into `GraphicBlock` component, import your ai2svelte graphic at the top of `App.svelte` and add it to the `aiCharts` object. + +> **Importantโ—:** Make sure that the value for `chart` in the ArchieML doc matches the name of the ai2svelte file imported in `App.svelte`. + +```svelte + + + + +{#each content.blocks as block} + {#if block.type === 'ai-graphic'} + {#if !aiCharts[block.chart]} + + + {:else} + + {@const AiChart = aiCharts[block.chart]} + + + + + {/if} + {/if} +{/each} +``` + + + +## Custom text + +You can override the default styles for title and notes by making your own custom elements and passing them as `title` and `notes` [snippets](https://svelte.dev/docs/svelte/snippet) instead of as strings: + +```svelte + + + {#snippet title()} +
My smaller title
+ {/snippet} + + +
+ + + {#snippet notes()} + + {/snippet} +
+``` + + + +## ARIA descriptions + +If the text in your chart isn't easily read by screen readers โ€” for example, a map with annotations that wouldn't make sense without the visual โ€” add an `ariaDescription` that describes the chart. + +The `ariaDescription` string will be processed as markdown, so you can add multiple paragraphs, links, headers, etc. in markdown. + +> **Note:** When you set an `ariaDescription`, your graphic will be automatically wrapped in a div with [aria-hidden="true"](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-hidden), which tells screen readers to read the hidden ARIA description and skip the text in the graphic. + +```svelte + + + + +``` + + + +## Custom ARIA descriptions + +Sometimes, instead of a simple sentence, we want to provide a data table or something more complex as an ARIA description. To do this, pass the custom elements as an `ariaDescription` [snippet](https://svelte.dev/docs/svelte/snippet) instead of as a string, as in the [example above](?path=/docs/components-graphics-graphicblock--docs#aria-descriptions). + +[Read this](https://accessibility.psu.edu/images/charts/) for more information on using screen reader data tables for charts. + +> **Note:** The `customAria` snippet will override the `ariaDescription` and will also hide the text in your graphic from screen readers. + +```svelte + + + + + + {#snippet ariaDescription()} +

+ A shakemap shows the intensity of the 7.2-magnitude earthquake that struck + Haiti at 8:29 a.m. EST, Aug. 14, 2021. +

+ + + + + + + + + + + + + + + +
CityFelt shake strength
Les CayesVery strong
JeremieStrong
+ {/snippet} +
+ + + +``` + + diff --git a/src/components/GraphicBlock/GraphicBlock.stories.svelte b/src/components/GraphicBlock/GraphicBlock.stories.svelte new file mode 100644 index 0000000..f19268e --- /dev/null +++ b/src/components/GraphicBlock/GraphicBlock.stories.svelte @@ -0,0 +1,134 @@ + + + + + + +
+ placeholder +
+
+
+ + + + + + + + + +
+ placeholder +
+ + {#snippet title()} +
My smaller title
+ {/snippet} + + {#snippet notes()} + + {/snippet} +
+
+ + + + + + + + + + + {#snippet ariaDescription()} +

+ A shakemap shows the intensity of the 7.2-magnitude earthquake that + struck Haiti at 8:29 a.m. EST, Aug. 14, 2021. +

+ + + + + + + + + + + + + + + +
CityFelt shake strength
Les CayesVery strong
JeremieStrong
+ {/snippet} +
+
+ + diff --git a/src/components/GraphicBlock/GraphicBlock.svelte b/src/components/GraphicBlock/GraphicBlock.svelte new file mode 100644 index 0000000..a9deaff --- /dev/null +++ b/src/components/GraphicBlock/GraphicBlock.svelte @@ -0,0 +1,148 @@ + + + +
+ + + {#if typeof title === 'string'} + + +

{title}

+ {#if description} + + {/if} +
+
+ {:else if title} + + + + {@render title()} + + + {/if} + + {#if ariaDescription} +
+ {#if typeof ariaDescription === 'string'} + + {:else} + + {@render ariaDescription()} + {/if} +
+ {/if} + {#if typeof notes === 'string'} + + + + + + {:else if notes} + + + + {@render notes()} + + + {/if} +
+
+ + diff --git a/src/components/GraphicBlock/components/AriaHidden.svelte b/src/components/GraphicBlock/components/AriaHidden.svelte new file mode 100644 index 0000000..6186b2e --- /dev/null +++ b/src/components/GraphicBlock/components/AriaHidden.svelte @@ -0,0 +1,22 @@ + + +{#if hidden} + +{:else} + {@render children()} +{/if} diff --git a/src/components/GraphicBlock/components/TextBlock.svelte b/src/components/GraphicBlock/components/TextBlock.svelte new file mode 100644 index 0000000..c7413fd --- /dev/null +++ b/src/components/GraphicBlock/components/TextBlock.svelte @@ -0,0 +1,23 @@ + + +{#if width} + + {@render children()} + +{:else} + {@render children()} +{/if} diff --git a/src/components/GraphicBlock/demo/ai2svelte/ai-chart.svelte b/src/components/GraphicBlock/demo/ai2svelte/ai-chart.svelte new file mode 100644 index 0000000..704b6ea --- /dev/null +++ b/src/components/GraphicBlock/demo/ai2svelte/ai-chart.svelte @@ -0,0 +1,630 @@ + + + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

Shake intensity

+
+
+

Light

+
+
+

Moderate

+
+
+

Cap-Haitien

+
+
+

Strong

+
+
+

Very strong

+
+
+

Gonaรฏves

+
+
+

Caribbean

+

Sea

+
+
+

HAITI

+
+
+

Jeremie

+
+
+

Port-au-Prince

+
+
+

Epicenter

+
+
+

Jacmel

+
+
+

Les Cayes

+
+
+

50 mi

+
+
+

Dominican

+

Republic

+
+
+

50 km

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

Shake intensity

+
+
+

Light

+
+
+

Moderate

+
+
+

Cap-Haitien

+
+
+

Strong

+
+
+

Very strong

+
+
+

Gonaรฏves

+
+
+

Caribbean

+

Sea

+
+
+

HAITI

+
+
+

Jeremie

+
+
+

Port-au-Prince

+
+
+

Epicenter

+
+
+

Dominican

+

Republic

+
+
+

Jacmel

+
+
+

Les Cayes

+
+
+

50 mi

+
+
+

50 km

+
+
+ {/if} + + {#if width && width >= 660} +
+
+
+
+

Shake intensity

+
+
+

Light

+
+
+

Moderate

+
+
+

Cap-Haitien

+
+
+

Strong

+
+
+

Very strong

+
+
+

Gonaรฏves

+
+
+

Caribbean

+

Sea

+
+
+

HAITI

+
+
+

Dominican

+

Republic

+
+
+

Jeremie

+
+
+

Epicenter

+
+
+

Port-au-Prince

+
+
+

Jacmel

+
+
+

Les Cayes

+
+
+

50 mi

+
+
+

50 km

+
+
+ {/if} +
+ + + + + diff --git a/src/components/GraphicBlock/demo/imgs/ai-chart-md.png b/src/components/GraphicBlock/demo/imgs/ai-chart-md.png new file mode 100644 index 0000000..7f62d44 Binary files /dev/null and b/src/components/GraphicBlock/demo/imgs/ai-chart-md.png differ diff --git a/src/components/GraphicBlock/demo/imgs/ai-chart-sm.png b/src/components/GraphicBlock/demo/imgs/ai-chart-sm.png new file mode 100644 index 0000000..49c06f6 Binary files /dev/null and b/src/components/GraphicBlock/demo/imgs/ai-chart-sm.png differ diff --git a/src/components/GraphicBlock/demo/imgs/ai-chart-xs.png b/src/components/GraphicBlock/demo/imgs/ai-chart-xs.png new file mode 100644 index 0000000..15d640d Binary files /dev/null and b/src/components/GraphicBlock/demo/imgs/ai-chart-xs.png differ diff --git a/src/components/GraphicBlock/demo/placeholder.png b/src/components/GraphicBlock/demo/placeholder.png new file mode 100644 index 0000000..ca52164 Binary files /dev/null and b/src/components/GraphicBlock/demo/placeholder.png differ diff --git a/src/components/Headline/Headline.mdx b/src/components/Headline/Headline.mdx new file mode 100644 index 0000000..320ed4a --- /dev/null +++ b/src/components/Headline/Headline.mdx @@ -0,0 +1,150 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as HeadlineStories from './Headline.stories.svelte'; + + + +# Headline + +The `Headline` component creates headlines in the legacy Reuters Graphics style, with the text centred on the page. + +```svelte + + + +``` + + + +## With bylines and dateline + +Optionally, you can add authors and a publish time to the headline, which the `Headline` component internally renders with the [Byline](./?path=/docs/components-text-elements-byline--docs) component. + +> **Note**: Since `Headline` uses `Byline`, you can customise the author page hyperlink and bylines with the `getAuthorPage`, `byline`, `published` and `updated` props. + +```svelte + + + `mailto:${author.replace(' ', '')}@example.com`} +/> +``` + + + +## Custom hed and dek + +Use the `hed` and/or `dek` [snippets](https://svelte.dev/docs/svelte/snippet) to override those elements with custom elements. + +```svelte + + + + + {#snippet hed()} +

+ The secret to + โ€œThe Nutcracker'sโ€ + success +

+ {/snippet} + + + {#snippet dek()} +

+ How โ€œThe Nutcrackerโ€ ballet became anAmerican holday stapleand a financial pillar of ballet companies across the country +

+ {/snippet} +
+ + + +``` + + + +## With crown image + +To add a crown image, use the `crown` [snippet](https://svelte.dev/docs/svelte/snippet). + +```svelte + + + + + {#snippet crown()} + Illustration of Europe + {/snippet} + +``` + + + +## With crown graphic + +Add a full graphic or any other component in the crown. + +```svelte + + + + + {#snippet crown()} + + + {/snippet} + +``` + + diff --git a/src/components/Headline/Headline.stories.svelte b/src/components/Headline/Headline.stories.svelte new file mode 100644 index 0000000..0b48df7 --- /dev/null +++ b/src/components/Headline/Headline.stories.svelte @@ -0,0 +1,111 @@ + + + + + + + + { + return `mailto:${author.replace(' ', '')}@example.com`; + }} + /> + + + + + {#snippet hed()} +

+ The secret to + โ€œThe Nutcracker'sโ€ + success +

+ {/snippet} + {#snippet dek()} +

+ How โ€œThe Nutcrackerโ€ ballet became anAmerican holday stapleand a financial pillar of ballet companies across the country +

+ {/snippet} +
+
+ + + + + {#snippet crown()} + Illustration of Europe + {/snippet} + + + + + + + {#snippet crown()} + + {/snippet} + + + + diff --git a/src/components/Headline/Headline.svelte b/src/components/Headline/Headline.svelte new file mode 100644 index 0000000..447f5b7 --- /dev/null +++ b/src/components/Headline/Headline.svelte @@ -0,0 +1,161 @@ + + + +
+ +
+ {#if crown} +
+ + {@render crown()} +
+ {/if} +
+ {#if section} +

+ {section} +

+ {/if} + {#if typeof hed === 'string'} +

+ +

+ {:else if hed} + + {@render hed()} + {/if} + {#if typeof dek === 'string'} +
+ +
+ {:else if dek} + +
+ {@render dek()} +
+ {/if} +
+ {#if authors.length > 0 || publishTime} + + {:else if byline} + + {@render byline()} + {/if} +
+
+
+ + diff --git a/src/components/Headline/demo/crown.png b/src/components/Headline/demo/crown.png new file mode 100644 index 0000000..c6bec93 Binary files /dev/null and b/src/components/Headline/demo/crown.png differ diff --git a/src/components/Headline/demo/graphic-lg.png b/src/components/Headline/demo/graphic-lg.png new file mode 100644 index 0000000..cc07e74 Binary files /dev/null and b/src/components/Headline/demo/graphic-lg.png differ diff --git a/src/components/Headline/demo/graphic-md.png b/src/components/Headline/demo/graphic-md.png new file mode 100644 index 0000000..88e3ca1 Binary files /dev/null and b/src/components/Headline/demo/graphic-md.png differ diff --git a/src/components/Headline/demo/graphic-sm.png b/src/components/Headline/demo/graphic-sm.png new file mode 100644 index 0000000..89e54ad Binary files /dev/null and b/src/components/Headline/demo/graphic-sm.png differ diff --git a/src/components/Headline/demo/graphic-xl.png b/src/components/Headline/demo/graphic-xl.png new file mode 100644 index 0000000..bc6488f Binary files /dev/null and b/src/components/Headline/demo/graphic-xl.png differ diff --git a/src/components/Headline/demo/graphic-xs.png b/src/components/Headline/demo/graphic-xs.png new file mode 100644 index 0000000..60ab82c Binary files /dev/null and b/src/components/Headline/demo/graphic-xs.png differ diff --git a/src/components/Headline/demo/graphic.svelte b/src/components/Headline/demo/graphic.svelte new file mode 100644 index 0000000..41afe75 --- /dev/null +++ b/src/components/Headline/demo/graphic.svelte @@ -0,0 +1,962 @@ + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

GREENLAND

+
+
+

UKRAINE

+
+
+

RUSSIA

+
+
+

Moscow

+
+
+

CANADA

+
+
+

U.S.

+
+
+

BELARUS

+
+
+

SPAIN

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

GREENLAND

+
+
+

FINLAND

+
+
+

RUSSIA

+
+
+

NORWAY

+
+
+

Moscow

+
+
+

BELARUS

+
+
+

ICELAND

+
+
+

UNITED

+

STATES

+
+
+

UK

+
+
+

UKRAINE

+
+
+

CANADA

+
+
+

IRELAND

+
+
+

IRAN

+
+
+

FRANCE

+
+
+

ITALY

+
+
+

SPAIN

+
+
+ {/if} + + {#if width && width >= 660 && width < 930} +
+
+
+ +
+

GREENLAND

+
+
+

FINLAND

+
+
+

RUSSIA

+
+
+

NORWAY

+
+
+

Moscow

+
+
+

BELARUS

+
+
+

ICELAND

+
+
+

CANADA

+
+
+

UNITED

+

STATES

+
+
+

UK

+
+
+

UKRAINE

+
+
+

IRELAND

+
+
+

IRAN

+
+
+

FRANCE

+
+
+

SAUDI

+

ARABIA

+
+
+

ITALY

+
+
+

SPAIN

+
+
+ {/if} + + {#if width && width >= 930 && width < 1200} +
+
+
+
+

FINLAND

+
+
+

RUSSIA

+
+
+

GREENLAND

+
+
+

KAZAKHSTAN

+
+
+

NORWAY

+
+
+

Moscow

+
+
+

BELARUS

+
+
+

ICELAND

+
+
+

CANADA

+
+
+

UNITED

+

STATES

+
+
+

UK

+
+
+

UKRAINE

+
+
+

IRELAND

+
+
+

IRAN

+
+
+

FRANCE

+
+
+

SPAIN

+
+
+

SAUDI

+

ARABIA

+
+
+

ITALY

+
+
+ {/if} + + {#if width && width >= 1200} +
+
+
+
+

FINLAND

+
+
+

RUSSIA

+
+
+

GREENLAND

+
+
+

KAZAKHSTAN

+
+
+

NORWAY

+
+
+

Moscow

+
+
+

BELARUS

+
+
+

ICELAND

+
+
+

CANADA

+
+
+

UKRAINE

+
+
+

UK

+
+
+

UNITED

+

STATES

+
+
+

POLAND

+
+
+

GERMANY

+
+
+

IRELAND

+
+
+

ROMANIA

+
+
+

IRAN

+
+
+

FRANCE

+
+
+

ITALY

+
+
+

SAUDI

+

ARABIA

+
+
+

SPAIN

+
+
+

GREECE

+
+
+ {/if} +
+ + + + + + + + diff --git a/src/components/Headpile/Headpile.mdx b/src/components/Headpile/Headpile.mdx new file mode 100644 index 0000000..dcdc28e --- /dev/null +++ b/src/components/Headpile/Headpile.mdx @@ -0,0 +1,37 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as HeadpileStories from './Headpile.stories.svelte'; + + + +# Headpile + +The `Headpile` component is a headshot-bulleted list of people, identifying them with their names, roles and a short description of their significance to a story. + +It's designed to be used with headshots that have had their background removed, which can be done in the [Preview app](https://support.apple.com/en-gb/guide/preview/prvw15636/mac?#apd320b3b1b750a4) on macOS. + +```svelte + + + +``` + + diff --git a/src/components/Headpile/Headpile.stories.svelte b/src/components/Headpile/Headpile.stories.svelte new file mode 100644 index 0000000..576bd89 --- /dev/null +++ b/src/components/Headpile/Headpile.stories.svelte @@ -0,0 +1,37 @@ + + + diff --git a/src/components/Headpile/Headpile.svelte b/src/components/Headpile/Headpile.svelte new file mode 100644 index 0000000..564f49d --- /dev/null +++ b/src/components/Headpile/Headpile.svelte @@ -0,0 +1,81 @@ + + + +
+ {#each figures as figure} + + {/each} +
+
+ + diff --git a/src/components/Headpile/Headshot.svelte b/src/components/Headpile/Headshot.svelte new file mode 100644 index 0000000..dd2afff --- /dev/null +++ b/src/components/Headpile/Headshot.svelte @@ -0,0 +1,41 @@ + + +
+
+
+
+ + diff --git a/src/components/Headpile/KeyFigure.svelte b/src/components/Headpile/KeyFigure.svelte new file mode 100644 index 0000000..14e6266 --- /dev/null +++ b/src/components/Headpile/KeyFigure.svelte @@ -0,0 +1,108 @@ + + +
+
+
+ +
+
+
{name}
+
+ {role || ''} +
+ {#if !mobile.current} +
+ +
+ {/if} +
+
+ + {#if mobile.current} +
+ +
+ {/if} +
+ + diff --git a/src/components/Headpile/images/abdel.png b/src/components/Headpile/images/abdel.png new file mode 100644 index 0000000..dcaef5c Binary files /dev/null and b/src/components/Headpile/images/abdel.png differ diff --git a/src/components/Headpile/images/hemedti.png b/src/components/Headpile/images/hemedti.png new file mode 100644 index 0000000..c432113 Binary files /dev/null and b/src/components/Headpile/images/hemedti.png differ diff --git a/src/components/HeroHeadline/HeroHeadline.mdx b/src/components/HeroHeadline/HeroHeadline.mdx new file mode 100644 index 0000000..1091015 --- /dev/null +++ b/src/components/HeroHeadline/HeroHeadline.mdx @@ -0,0 +1,329 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as HeroHeadlineStories from './HeroHeadline.stories.svelte'; + + + +# HeroHeadline + +The `HeroHeadline` component creates a Reuters Graphics headline with a hero media, which can be a graphic, photo, video or other media. + +By default, the hero is in the background, i.e., the headline and dek are stacked on top of the hero. You can unstack and insert the hero media inline -- i.e., before or after the headline -- by setting `stacked: false`. [Read more.](?/iframe.html?viewMode=docs&id=components-text-elements-heroheadline--docs&globals=&args=#inline-hero) + +## Photo hero + +To use a photo as the hero, simply pass the image source to the `img` prop. + +```svelte + + + + +``` + + + +## Transparent site header + +In the graphics kit, set styles in `global.scss` to make the Reuters site header transparent and make the hero go all the way to the top of the page: + +```scss +// global.scss +.nav-container { + background-color: transparent !important; +} +.nav-container .inner { + background-color: transparent !important; + border: none !important; +} +.hero-wrapper { + margin-block-start: -64px; +} +``` + + + +## Ai2svelte hero + +To use an ai2svelte graphic as the hero, wrap your ai2svelte component in a `GraphicBlock` component and insert it inside `HeroHeadline`. + +To customise styles, use CSS to target the class passed to `HeroHeadline`. + +> **Note:** Pass `notes` and `ariaDescription` to the `GraphicBlock` component to provide additional information about the ai2svelte graphic. + +```svelte + + + + + + + + + +``` + +Add styles in `global.scss`: + +```scss +// global.scss +// Customise styles using the class (e.g. `custom-hero` here) passed to `HeroHeadline` +.hero-wrapper { + .custom-hero.headline { + // Adjust vertical positioning + align-items: flex-end !important; + + @media (max-width: 1100px) { + // Adjust line length of title + max-width: var(--normal-column-width) !important; + } + } + + // Make hero shorter than 100vh + --heroHeight: 85svh; + + @media (max-width: 960px) { + --heroHeight: 65svh; + } + + // For small height + @media (max-height: 850px) { + --heroHeight: 100svh; + } + + // Custom hero sizing for landscape mobile + @media (max-width: 960px) and (orientation: landscape) { + --heroHeight: 200svh; + } +} + +// Override default fixed height for hero layout in embeds +.hero-wrapper.embedded { + --heroHeight: 1000px; +} +``` + + + +## Video hero + +To add a video as the hero, use the [Video](?path=/docs/components-multimedia-video--docs) component. To customise styles, use CSS to target the class passed to `HeroHeadline`. + +> **Note:** Pass `notes` and `ariaDescription` to the `GraphicBlock` component to provide additional information about the video. + +```svelte + + + + +``` + +Add styles in `global.scss`: + +```scss +// global.scss +// Customise styles using the class (e.g. `video-hero` here) passed to `HeroHeadline` +.hero-wrapper { + --heroHeight: calc(100svh - 60px); + .video-hero.headline { + header { + // Adjust vertical position as offset from default center + top: calc(50svh - 250px); + } + + h1 { + color: #ffd430; + text-shadow: 3px 4px 7px rgba(81, 67, 21, 0.8); + } + } +} +``` + + + +## Inline hero + +To use a photo, graphic, video, etc. as an inline hero -- i.e., to make the hero appear _after_ the headline and dek, instead of stacked underneath -- set `stacked` to `false`. Otherwise, add your hero media in the same way as documented above. + +```svelte + + + + + + + + + + +``` + + + +## Custom hed, dek and byline + +The `HeroHeadline` component internally uses the [Headline](?path=/docs/components-text-elements-headline--docs) component to render the headline and dek, which lets you to customise the headline and dek by passing [snippets](https://svelte.dev/docs/svelte/snippet) into the `hed` and `dek` props. + +Since `Headline` internally uses the [Byline](?path=/docs/components-text-elements-headline--docs) component, you can also customise the author page hyperlink and bylines with the `getAuthorPage`, `byline`, `published` and `updated` props. + +```svelte + + { + return `mailto:${author.replace(' ', '')}@example.com`; + }} +> + + {#snippet hed()} +

+
A visual guide to
+
EUROVISION
+

+ {/snippet} + + + {#snippet dek()} +
+

+ Performers from 37 countries are coming together May 9-13 in Liverpool, + England, for the 67th annual Eurovision Song Contest. The winner gets + the trophy and their country gets the right to host next yearโ€™s event, + produced by the European Broadcasting Union (EBU). +

+
+ {/snippet} +
+``` + +Add styles in `global.scss`: + +```scss +// global.scss +.custom-hed { + h1 { + .body-note { + color: #ffffff; + } + .title { + color: #ffffff; + text-shadow: 1px 1px 8px #ff7c88; + filter: drop-shadow(0px 0px 12px #ff7c88); + } + } + + .dek { + margin-block-start: 1rem; + p { + color: #ffffff; + text-shadow: 1px 1px 8px #ff7c88; + filter: drop-shadow(0px 0px 12px #ff7c88); + } + } +} +``` + + diff --git a/src/components/HeroHeadline/HeroHeadline.stories.svelte b/src/components/HeroHeadline/HeroHeadline.stories.svelte new file mode 100644 index 0000000..5e4000e --- /dev/null +++ b/src/components/HeroHeadline/HeroHeadline.stories.svelte @@ -0,0 +1,287 @@ + + + + + + + + + + + + +
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + return `mailto:${author.replace(' ', '')}@example.com`; + }} + > + {#snippet hed()} +

+
A visual guide to
+
EUROVISION
+

+ {/snippet} + + {#snippet dek()} +
+

+ Performers from 37 countries are coming together May 9-13 in + Liverpool, England, for the 67th annual Eurovision Song Contest. The + winner gets the trophy and their country gets the right to host next + yearโ€™s event, produced by the European Broadcasting Union (EBU). +

+
+ {/snippet} +
+ + +
+ + diff --git a/src/components/HeroHeadline/HeroHeadline.svelte b/src/components/HeroHeadline/HeroHeadline.svelte new file mode 100644 index 0000000..bf38f92 --- /dev/null +++ b/src/components/HeroHeadline/HeroHeadline.svelte @@ -0,0 +1,276 @@ + + + +
+
+ + {#if stacked} + + + + +
+ + {#if children} + {@render children()} + + + {:else if img} + +
+
+ {/if} +
+
+ {/if} + + + {#if stacked === false} + + + + +
+ + {#if children} + {@render children()} + + + {:else if img} + + {/if} +
+
+ {/if} +
+ + +
+ + diff --git a/src/components/HeroHeadline/demo/eurovis.jpeg b/src/components/HeroHeadline/demo/eurovis.jpeg new file mode 100644 index 0000000..ad298a8 Binary files /dev/null and b/src/components/HeroHeadline/demo/eurovis.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/CRASH_1-lg.jpeg b/src/components/HeroHeadline/demo/graphics/CRASH_1-lg.jpeg new file mode 100644 index 0000000..60e6304 Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/CRASH_1-lg.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/CRASH_1-md.jpeg b/src/components/HeroHeadline/demo/graphics/CRASH_1-md.jpeg new file mode 100644 index 0000000..abe9b17 Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/CRASH_1-md.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/CRASH_1-sm.jpeg b/src/components/HeroHeadline/demo/graphics/CRASH_1-sm.jpeg new file mode 100644 index 0000000..ca46080 Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/CRASH_1-sm.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/CRASH_1-xl.jpeg b/src/components/HeroHeadline/demo/graphics/CRASH_1-xl.jpeg new file mode 100644 index 0000000..0619957 Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/CRASH_1-xl.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/CRASH_1-xl_copy.jpeg b/src/components/HeroHeadline/demo/graphics/CRASH_1-xl_copy.jpeg new file mode 100644 index 0000000..e150f58 Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/CRASH_1-xl_copy.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/CRASH_1-xs.jpeg b/src/components/HeroHeadline/demo/graphics/CRASH_1-xs.jpeg new file mode 100644 index 0000000..4a8245f Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/CRASH_1-xs.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/crash.svelte b/src/components/HeroHeadline/demo/graphics/crash.svelte new file mode 100644 index 0000000..9f2ac0f --- /dev/null +++ b/src/components/HeroHeadline/demo/graphics/crash.svelte @@ -0,0 +1,650 @@ + + + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

Cruising at

+

29,100 feet

+
+
+

2.21 pm

+

Steep drop from

+

27,025 feet

+
+
+

Typical path to

+

Guangzhou

+
+
+

Last known

+

location

+
+
+

Crash

+

site

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

Cruising at

+

29,100 feet

+
+
+

2.21 pm

+

Steep drop from

+

27,025 feet

+
+
+

Typical path to

+

Guangzhou

+
+
+

Last known

+

location

+
+
+

Crash

+

site

+
+
+ {/if} + + {#if width && width >= 660 && width < 930} +
+
+
+
+

Cruising at

+

29,100 feet

+
+
+

2.20 pm

+

Slight descent

+
+
+

2.21 pm

+

Steep drop from

+

27,025 feet

+
+
+

Typical path to

+

Guangzhou

+
+
+

Last known

+

location

+
+
+

Approximate

+

crash site

+
+
+ {/if} + + {#if width && width >= 930 && width < 1200} +
+
+
+
+

Cruising at

+

29,100 feet

+
+
+

2.20 pm

+

Slight descent

+
+
+

2.21 pm

+

Steep drop from

+

27,025 feet

+
+
+

Typical path to

+

Guangzhou

+
+
+

Last known

+

location

+
+
+

Approximate

+

crash site

+
+
+ {/if} + + {#if width && width >= 1200 && width < 1350} +
+
+
+
+

Cruising at

+

29,100 feet

+
+
+

2.20 pm

+

Slight descent

+
+
+

2.21 pm

+

Steep drop from

+

27,025 feet

+
+
+

Typical path to

+

Guangzhou

+
+
+

Last known

+

location

+
+
+

Approximate

+

crash site

+
+
+ {/if} + + {#if width && width >= 1350} +
+
+
+
+

Cruising at

+

29,100 feet

+
+
+

2.20 pm

+

Slight descent

+
+
+

2.21 pm

+

Steep drop from

+

27,025 feet

+
+
+

Typical path to

+

Guangzhou

+
+
+

Last known

+

location

+
+
+

Approximate

+

crash site

+
+
+ {/if} +
+ + + + + diff --git a/src/components/HeroHeadline/demo/graphics/quake-map-top-lg.jpeg b/src/components/HeroHeadline/demo/graphics/quake-map-top-lg.jpeg new file mode 100644 index 0000000..67096d6 Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/quake-map-top-lg.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/quake-map-top-md.jpeg b/src/components/HeroHeadline/demo/graphics/quake-map-top-md.jpeg new file mode 100644 index 0000000..157b8b3 Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/quake-map-top-md.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/quake-map-top-sm.jpeg b/src/components/HeroHeadline/demo/graphics/quake-map-top-sm.jpeg new file mode 100644 index 0000000..f93377a Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/quake-map-top-sm.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/quake-map-top-xl.jpeg b/src/components/HeroHeadline/demo/graphics/quake-map-top-xl.jpeg new file mode 100644 index 0000000..a150f58 Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/quake-map-top-xl.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/quake-map-top-xs.jpeg b/src/components/HeroHeadline/demo/graphics/quake-map-top-xs.jpeg new file mode 100644 index 0000000..34601bd Binary files /dev/null and b/src/components/HeroHeadline/demo/graphics/quake-map-top-xs.jpeg differ diff --git a/src/components/HeroHeadline/demo/graphics/quakemap.svelte b/src/components/HeroHeadline/demo/graphics/quakemap.svelte new file mode 100644 index 0000000..30fba5c --- /dev/null +++ b/src/components/HeroHeadline/demo/graphics/quakemap.svelte @@ -0,0 +1,863 @@ + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

Kabul

+
+
+

Shaking

+
+
+

Very strong

+
+
+

Weak

+
+
+

AFGHANISTAN

+
+
+

Gardez

+
+
+

Khost

+
+
+

Epicentre

+
+
+

Bannu

+
+
+

PAKISTAN

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

Shaking

+
+
+

Very strong

+
+
+

AFGHANISTAN

+
+
+

Weak

+
+
+

Gardez

+
+
+

Ghazni

+
+
+

Khost

+
+
+

Epicentre

+
+
+

Bannu

+
+
+

PAKISTAN

+
+
+ {/if} + + {#if width && width >= 660 && width < 1200} +
+
+
+
+

Shaking

+
+
+

Very strong

+
+
+

Afghanistan

+
+
+

Weak

+
+
+

AFGHANISTAN

+
+
+

Gardez

+
+
+

Ghazni

+
+
+

Khost

+
+
+

Epicentre

+
+
+

Bannu

+
+
+

PAKISTAN

+
+
+ {/if} + + {#if width && width >= 1200 && width < 1300} +
+
+
+
+

Shaking

+
+
+

Very strong

+
+
+

Afghanistan

+
+
+

AFGHANISTAN

+
+
+

Weak

+
+
+

Gardez

+
+
+

Ghazni

+
+
+

PAKISTAN

+
+
+

Khost

+
+
+

Epicentre

+
+
+

Bannu

+
+
+ {/if} + + {#if width && width >= 1300} +
+
+
+
+

Shaking

+
+
+

Afghanistan

+
+
+

Very strong

+
+
+

AFGHANISTAN

+
+
+

Weak

+
+
+

Gardez

+
+
+

Ghazni

+
+
+

PAKISTAN

+
+
+

Khost

+
+
+

Epicentre

+
+
+

Bannu

+
+
+ {/if} +
+ + + + + + + diff --git a/src/components/HeroHeadline/demo/polar.jpg b/src/components/HeroHeadline/demo/polar.jpg new file mode 100644 index 0000000..fe7cac6 Binary files /dev/null and b/src/components/HeroHeadline/demo/polar.jpg differ diff --git a/src/components/HorizontalScroller/Debug.svelte b/src/components/HorizontalScroller/Debug.svelte new file mode 100644 index 0000000..f3da8a3 --- /dev/null +++ b/src/components/HorizontalScroller/Debug.svelte @@ -0,0 +1,355 @@ + + + + +{#snippet triggerPoints()} + {#if componentState.triggerStops.length > 0} + {#if componentState.scrubbed} + {@const totalStops = componentState.triggerStops.length} + {#each Array(totalStops) as _, index} + | + {/each} + {:else} + {@const stops = componentState.triggerStops.map((x: number) => + mappedStop(x) + )} + {#each stops as stop, index} + {#if index < stops.length - 1} + | + {/if} + {/each} + {/if} + {/if} +{/snippet} + +
+
+ + CONSOLE + +
+ +

Progress:

+
+

+ {componentState.progress} +

+
+ +

Mapped progress:

+
+

+ {@render triggerPoints()} + {fmt.format(componentState.mappedProgress)} +   +

+
+
+
+
+ +

Eased Progress:

+
+

+ {#if componentState.stops.length > 0} + {#each componentState.stops as stop} + {stop} + {/each} + {/if} + {fmt.format(componentState.easedProgress)} +   +

+
+
+
+
+ +

Direction:

+
+

+ {componentState.direction} +

+
+ + {#if componentState.stops.length > 0} +

Stops:

+
+

+ {#each componentState.stops as stop} + {stop} + {/each} +

+
+ {/if} + +

Handle scroll:

+
+

+ {componentState.handleScroll} +

+
+ +

Scrubbed:

+
+

+ {componentState.scrubbed} +

+
+ +

Easing:

+
+

+ {componentState.easing} +

+
+ +

+ Duration: + {#if componentState.scrubbed} + NA + {/if} +

+
+

+ {componentState.duration} +

+
+ +
+
+
+ + diff --git a/src/components/HorizontalScroller/HorizontalScroller.mdx b/src/components/HorizontalScroller/HorizontalScroller.mdx new file mode 100644 index 0000000..1fae940 --- /dev/null +++ b/src/components/HorizontalScroller/HorizontalScroller.mdx @@ -0,0 +1,447 @@ +import { Meta } from '@storybook/blocks'; + +import * as HorizontalScrollerStories from './HorizontalScroller.stories.svelte'; + +import IllustratorScreenshot from './assets/illustrator.png'; + + + +# HorizontalScroller + +The `HorizontalScroller` component creates a horizontal scrolling section that scrolls through any child content wider than `100vw`. + +To use `HorizontalScroller`, wrap it around the content that you want to horizontally scroll through. The scroll length is controlled by the height of the `HorizontalScroller` container, which is set by the prop `height`. `height` defaults to `200lvh`, but you can adjust this to any valid CSS height value such as `1200px` or `400lvh`. + +The child content inside the `HorizontalScroller` must be wider than `100vw` so that there is overflow to horizontal scroll through. By default, only the top `100lvh` of the child content is visible. You can use CSS `transform: translate()` on the child content to adjust its vertical positioning within the visible area. + +> ๐Ÿ’กTIP: Use `lvh` or `svh` units instead of `vh` unit for the height, as [these units](https://www.w3.org/TR/css-values-4/#large-viewport-size) are more reliable on mobile or other devices where elements such as the address bar toggle between being shown and hidden. + +> ๐Ÿ’กTIP: Set the `showDebugInfo` prop to `true` to visualise the scroll progress and other useful information. + +See the full list of available props under the `Controls` tab in the [demo](?path=/story/components-graphics-horizontalscroller--demo). + +```svelte + + + + + + + +
+ alt text +
+
+
+``` + +## Controlling scroll behaviour with stops and easing + +The `HorizontalScroller` allows you to control the horizontal scroll behaviour and pacing with various props. + +**`stops`:** + +`stops` is an optional prop that accepts an array of numbers between `0` and `1`. At these points, which corresponds to the scroll `progress` values, the scrolling stops or slows down. This is useful for adding custom pauses based on progress. + +For example, as shown in the demo below, if you define `stops` as `[0.2, 0.5, 0.9]`, the scrolling will pause or slow down at these `progress` values as the user scrolls through the `HorizontalScroller` section. + +**`scrubbed`:** + +The `scrubbed` prop controls whether the scrolling is tied exactly to the scroll position (`scrubbed: true`) or is smoothed out (`scrubbed: false`). This prop defaults to `true`. + +If `scrubbed` is set to `false` and `stops` are defined, the scrolling transitions smoothly between the stop values. + +**`easing`** and **`duration`**: + +`easing` accepts any easing function from `svelte/easing` or a custom easing function, while `duration` sets the time, in milliseconds, for each transition between stops. + +So, if the stops are at irregular intervals โ€” for example, `[0.2, 0.9]` โ€” the scroll to the first stop will be much quicker than the scroll to the second stop since the distance to travel is different but the duration of the transition is the same. + +By default, `duration` is set to `400` milliseconds. + +[Demo](?path=/story/components-graphics-horizontalscroller--with-stops) + +```svelte + + + + + + +
+ alt text +
+
+
+``` + +## Extended boundaries + +`HorizontalScroller` has `mappedStart` and `mappedEnd` props, which extend the horizontal scroll boundaries beyond the default 0 to 1 range. This is useful when you want to create an overscroll effect or have more control over the horizontal scroll range. By default, these values are set to 0 and 1 respectively. + +If using custom `mappedStart` and `mappedEnd` values, you must also set `stops` values that are within the mapped range. + +> ๐Ÿ’กTIP: In the debugging info box, `Progress` indicates the raw scroll progress value between `0` and `1`. `Mapped Progress` indicates the vertical progress mapped to `mappedStart` and `mappedEnd`. If they are not set, `Mapped Progress` is bound between 0 and 1 and matches `Progress`. `Eased Progress` indicates the scroll progress with any stops and easing applied. `Eased Progress` is what reflects the actual transition of the horizontal scroll position. + +[Demo](?path=/story/components-graphics-horizontalscroller--extended-boundaries) + +```svelte + + + + + + +
+ alt text +
+
+
+``` + +## With ai2svelte components + +With [ai2svelte](https://reuters-graphics.github.io/ai2svelte/) v1.0.3 onwards, you can export your ai2svelte graphic with a wider-than-viewport layout and use it directly inside `HorizontalScroller` to create horizontally scrolling graphics. + +To do that, follow these steps: + +1. In Illustrator, rename your artboard with the breakpoint at which you want that artboard to be visible on the page. For example, to make the XL artboard visible on viewports wider than 1200px, rename it to `xl:1200`. You can have multiple artboards with different breakpoints. +2. Add these properties to the ai2svelte settings and run the script to export the component. + +```yaml +include_resizer_css: false +respect_height: true +allow_overflow: true +``` + +Screenshot showing Illustrator document with artboard panel + +[Demo](?path=/story/components-graphics-horizontalscroller--scrollable-ai-2-svelte) + +```svelte + + + + + + + + +``` + +## With ai2svelte components: advanced + +You can use the bound prop `progress` to create advanced interactivity with an ai2svelte graphic. + +The demo below has 2 advanced interactions: fade in/out of caption boxes based on scroll position and parallax movement of a `png` layer. + +### Captions fading in/out + +Caption boxes are exported as `htext` [tagged layers](https://reuters-graphics.github.io/ai2svelte/users/tagged-layers/) in ai2svelte. In this example, we use the `handleScroll()` function to check the position of each caption box relative to the viewport width and set its opacity to `1` (visible) or `0` (hidden) based on whether the caption box is within the `threshold` of the viewport. In Adobe Illustrator, set `override_text: true` in the ai2svelte export settings to allow custom HTML content in tagged text layers. + +### Parallax effect with png layer + +This demo has a tagged `png` [layer](https://reuters-graphics.github.io/ai2svelte/users/tagged-layers/), which contains the foreground overlay image. The `handleScroll()` function uses the bound `progress` value to calculate a horizontal translation for the `png` layer, creating a parallax effect as the user scrolls through the `HorizontalScroller`. + +[Demo](?path=/story/components-graphics-horizontalscroller--scrollable-ai-2-svelte-advanced) + +```svelte + + + + + + Caption 1!
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
', + caption2: + '
Caption 2!
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
', + caption3: + '
Caption 3!
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
', + caption4: + '
Caption 4!
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
', + }, + }, + }} + /> + + + + +``` + +## With custom child components + +You can create a custom horizontal layout with any component and pass it as a child to the `HorizontalScroller`. Here's an example with `DatawrapperChart`, `Headline` and ai2svelte components laid out in a horizontal scroll. + +[Demo](?path=/story/components-graphics-horizontalscroller--custom-children) + +```svelte + + + + + +
+
+ +
+
+ +
+
+ + + +
+
+
+
+ + +``` + +## With ScrollerBase + +You can also integrate HorizontalScroller with `ScrollerBase` for a horizontal scroll with vertical captions. + +When using `HorizontalScroller` with `ScrollerBase` or other scrollers, you must: + +- Create a `progress` state variable and bind it to both `ScrollerBase` and `HorizontalScroller` +- Set `HorizontalScroller`'s `height` to `100lvh` +- Set `handleScroll` to `false` + +> **โš ๏ธ Warning:** It is not recommended to use HorizontalScroller with vertical ScrollerBase. This example is only to serve the purpose of demonstrating how to control the HorizontalScroller with an external progress value (ScrollerBase's progress in this case). + +[Demo](?path=/story/components-graphics-horizontalscroller--with-scroller-base) + +```svelte + + + + {#snippet backgroundSnippet()} + + + + + + + {/snippet} + {#snippet foregroundSnippet()} + +

Step 1

+

Step 2

+

Step 3

+

Step 4

+

Step 5

+ {/snippet} +
+ + +``` diff --git a/src/components/HorizontalScroller/HorizontalScroller.stories.svelte b/src/components/HorizontalScroller/HorizontalScroller.stories.svelte new file mode 100644 index 0000000..c17dfbf --- /dev/null +++ b/src/components/HorizontalScroller/HorizontalScroller.stories.svelte @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/HorizontalScroller/HorizontalScroller.svelte b/src/components/HorizontalScroller/HorizontalScroller.svelte new file mode 100644 index 0000000..7a66e6d --- /dev/null +++ b/src/components/HorizontalScroller/HorizontalScroller.svelte @@ -0,0 +1,254 @@ + + + + +
+
+ {#if children} + {@render children()} + {/if} + {#if showDebugInfo} +
+ +
+ {/if} +
+
+ + diff --git a/src/components/HorizontalScroller/assets/illustrator.png b/src/components/HorizontalScroller/assets/illustrator.png new file mode 100644 index 0000000..7de9355 Binary files /dev/null and b/src/components/HorizontalScroller/assets/illustrator.png differ diff --git a/src/components/HorizontalScroller/demo/AdvancedScrollableGraphic.svelte b/src/components/HorizontalScroller/demo/AdvancedScrollableGraphic.svelte new file mode 100644 index 0000000..c3f51e4 --- /dev/null +++ b/src/components/HorizontalScroller/demo/AdvancedScrollableGraphic.svelte @@ -0,0 +1,103 @@ + + + + + + + + + Caption 1!
Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + caption2: + '
Caption 2!
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
', + caption3: + '
Caption 3!
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
', + caption4: + '
Caption 4!
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
', + }, + }, + }} + /> +
+
+ + + + diff --git a/src/components/HorizontalScroller/demo/CustomChildrenSnippet.svelte b/src/components/HorizontalScroller/demo/CustomChildrenSnippet.svelte new file mode 100644 index 0000000..fb2749c --- /dev/null +++ b/src/components/HorizontalScroller/demo/CustomChildrenSnippet.svelte @@ -0,0 +1,44 @@ + + +
+
+ +
+
+ +
+
+ + + +
+
+ + diff --git a/src/components/HorizontalScroller/demo/Demo.svelte b/src/components/HorizontalScroller/demo/Demo.svelte new file mode 100644 index 0000000..c0fbb8d --- /dev/null +++ b/src/components/HorizontalScroller/demo/Demo.svelte @@ -0,0 +1,42 @@ + + + + +{#if args.toggleScrub} + + + +{/if} + + + + + + + + diff --git a/src/components/HorizontalScroller/demo/DemoSnippet.svelte b/src/components/HorizontalScroller/demo/DemoSnippet.svelte new file mode 100644 index 0000000..cda252d --- /dev/null +++ b/src/components/HorizontalScroller/demo/DemoSnippet.svelte @@ -0,0 +1,7 @@ +
+ An ultra wide scenic view of cityscape +
diff --git a/src/components/HorizontalScroller/demo/ScrollableGraphic.svelte b/src/components/HorizontalScroller/demo/ScrollableGraphic.svelte new file mode 100644 index 0000000..7b03f26 --- /dev/null +++ b/src/components/HorizontalScroller/demo/ScrollableGraphic.svelte @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/src/components/HorizontalScroller/demo/graphic/ai2svelte/ai-chart.svelte b/src/components/HorizontalScroller/demo/graphic/ai2svelte/ai-chart.svelte new file mode 100644 index 0000000..704b6ea --- /dev/null +++ b/src/components/HorizontalScroller/demo/graphic/ai2svelte/ai-chart.svelte @@ -0,0 +1,630 @@ + + + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

Shake intensity

+
+
+

Light

+
+
+

Moderate

+
+
+

Cap-Haitien

+
+
+

Strong

+
+
+

Very strong

+
+
+

Gonaรฏves

+
+
+

Caribbean

+

Sea

+
+
+

HAITI

+
+
+

Jeremie

+
+
+

Port-au-Prince

+
+
+

Epicenter

+
+
+

Jacmel

+
+
+

Les Cayes

+
+
+

50 mi

+
+
+

Dominican

+

Republic

+
+
+

50 km

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

Shake intensity

+
+
+

Light

+
+
+

Moderate

+
+
+

Cap-Haitien

+
+
+

Strong

+
+
+

Very strong

+
+
+

Gonaรฏves

+
+
+

Caribbean

+

Sea

+
+
+

HAITI

+
+
+

Jeremie

+
+
+

Port-au-Prince

+
+
+

Epicenter

+
+
+

Dominican

+

Republic

+
+
+

Jacmel

+
+
+

Les Cayes

+
+
+

50 mi

+
+
+

50 km

+
+
+ {/if} + + {#if width && width >= 660} +
+
+
+
+

Shake intensity

+
+
+

Light

+
+
+

Moderate

+
+
+

Cap-Haitien

+
+
+

Strong

+
+
+

Very strong

+
+
+

Gonaรฏves

+
+
+

Caribbean

+

Sea

+
+
+

HAITI

+
+
+

Dominican

+

Republic

+
+
+

Jeremie

+
+
+

Epicenter

+
+
+

Port-au-Prince

+
+
+

Jacmel

+
+
+

Les Cayes

+
+
+

50 mi

+
+
+

50 km

+
+
+ {/if} +
+ + + + + diff --git a/src/components/HorizontalScroller/demo/graphic/ai2svelte/demo.svelte b/src/components/HorizontalScroller/demo/graphic/ai2svelte/demo.svelte new file mode 100644 index 0000000..de14038 --- /dev/null +++ b/src/components/HorizontalScroller/demo/graphic/ai2svelte/demo.svelte @@ -0,0 +1,280 @@ + + + + +
+ + {#if aiBoxWidth && aiBoxWidth >= 0 && aiBoxWidth < 1200} +
+
+
+
+ {/if} + + {#if aiBoxWidth && aiBoxWidth >= 1200} +
+
+
+
+

+ {@html taggedText?.htext?.captions?.caption2 || ''} +

+
+
+

+ {@html taggedText?.htext?.captions?.caption3 || ''} +

+
+
+

+ {@html taggedText?.htext?.captions?.caption4 || ''} +

+
+
+

+ {@html taggedText?.htext?.captions?.caption1 || ''} +

+
+
+ {/if} +
+ + + + + + + diff --git a/src/components/HorizontalScroller/demo/graphic/imgs/ai-chart-md.png b/src/components/HorizontalScroller/demo/graphic/imgs/ai-chart-md.png new file mode 100644 index 0000000..7f62d44 Binary files /dev/null and b/src/components/HorizontalScroller/demo/graphic/imgs/ai-chart-md.png differ diff --git a/src/components/HorizontalScroller/demo/graphic/imgs/ai-chart-sm.png b/src/components/HorizontalScroller/demo/graphic/imgs/ai-chart-sm.png new file mode 100644 index 0000000..49c06f6 Binary files /dev/null and b/src/components/HorizontalScroller/demo/graphic/imgs/ai-chart-sm.png differ diff --git a/src/components/HorizontalScroller/demo/graphic/imgs/ai-chart-xs.png b/src/components/HorizontalScroller/demo/graphic/imgs/ai-chart-xs.png new file mode 100644 index 0000000..15d640d Binary files /dev/null and b/src/components/HorizontalScroller/demo/graphic/imgs/ai-chart-xs.png differ diff --git a/src/components/HorizontalScroller/demo/graphic/imgs/demo-lg.jpg b/src/components/HorizontalScroller/demo/graphic/imgs/demo-lg.jpg new file mode 100644 index 0000000..7a22ffb Binary files /dev/null and b/src/components/HorizontalScroller/demo/graphic/imgs/demo-lg.jpg differ diff --git a/src/components/HorizontalScroller/demo/graphic/imgs/demo-xl.jpg b/src/components/HorizontalScroller/demo/graphic/imgs/demo-xl.jpg new file mode 100644 index 0000000..342cf78 Binary files /dev/null and b/src/components/HorizontalScroller/demo/graphic/imgs/demo-xl.jpg differ diff --git a/src/components/HorizontalScroller/demo/graphic/imgs/layer-overlay-lg.png b/src/components/HorizontalScroller/demo/graphic/imgs/layer-overlay-lg.png new file mode 100644 index 0000000..93b1bb0 Binary files /dev/null and b/src/components/HorizontalScroller/demo/graphic/imgs/layer-overlay-lg.png differ diff --git a/src/components/HorizontalScroller/demo/graphic/imgs/layer-overlay-xl.png b/src/components/HorizontalScroller/demo/graphic/imgs/layer-overlay-xl.png new file mode 100644 index 0000000..2a601fb Binary files /dev/null and b/src/components/HorizontalScroller/demo/graphic/imgs/layer-overlay-xl.png differ diff --git a/src/components/HorizontalScroller/demo/graphic/placeholder.png b/src/components/HorizontalScroller/demo/graphic/placeholder.png new file mode 100644 index 0000000..ca52164 Binary files /dev/null and b/src/components/HorizontalScroller/demo/graphic/placeholder.png differ diff --git a/src/components/HorizontalScroller/demo/withScrollerBase.svelte b/src/components/HorizontalScroller/demo/withScrollerBase.svelte new file mode 100644 index 0000000..fe3a267 --- /dev/null +++ b/src/components/HorizontalScroller/demo/withScrollerBase.svelte @@ -0,0 +1,63 @@ + + + + + + {#snippet backgroundSnippet()} + + + + + + {/snippet} + {#snippet foregroundSnippet()} + +

Step 1

+

Step 2

+

Step 3

+

Step 4

+

Step 5

+ {/snippet} +
+ + diff --git a/src/components/HorizontalScroller/utils/index.ts b/src/components/HorizontalScroller/utils/index.ts new file mode 100644 index 0000000..06807f9 --- /dev/null +++ b/src/components/HorizontalScroller/utils/index.ts @@ -0,0 +1,40 @@ +/** + * Clamp a number `n` to the inclusive range [low, high]. + */ +export function clamp(n: number, low: number, high: number): number { + // Ensure low <= high even if caller swaps them + const min = Math.min(low, high); + const max = Math.max(low, high); + return Math.max(min, Math.min(n, max)); +} + +/** + * Linearly maps a value `n` from range [inStart, inEnd] to [outStart, outEnd]. + * + * @param {number} n - The input value to map. + * @param {number} inStart - Input range start. + * @param {number} inEnd - Input range end. + * @param {number} outStart - Output range start. + * @param {number} outEnd - Output range end. + * @param {boolean} withinBounds - If true, clamp the mapped value to [outStart, outEnd]. + * @returns {number} - Mapped (and optionally clamped) value. + */ +export function map( + n: number, + inStart: number, + inEnd: number, + outStart: number, + outEnd: number, + withinBounds: boolean = true +): number { + // Avoid division by zero: when input range is degenerate, return outStart + const inSpan = inEnd - inStart; + if (inSpan === 0) { + return withinBounds ? clamp(outStart, outStart, outEnd) : outStart; + } + + const t = (n - inStart) / inSpan; // normalized 0..1 in input space (or beyond) + const out = t * (outEnd - outStart) + outStart; + + return withinBounds ? clamp(out, outStart, outEnd) : out; +} diff --git a/src/components/InfoBox/InfoBox.mdx b/src/components/InfoBox/InfoBox.mdx new file mode 100644 index 0000000..1704e58 --- /dev/null +++ b/src/components/InfoBox/InfoBox.mdx @@ -0,0 +1,122 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as InfoBoxStories from './InfoBox.stories.svelte'; + + + +# InfoBox + +The `InfoBox` component creates a stylised text box that provides additional information that needs to be visually separate from the main content flow, such as methodology, detailed notes about data and extra context. + +```svelte + + + +``` + + + +## Using with ArchieML docs + +With the graphics kit, you'll likely get your text value from an ArchieML doc... + +```yaml +# Archie ML doc +[blocks] + +type: info-box +title: What you need to know about the war +text: Reuters is collecting daily COVID-19 infections and deaths data for 240 countries and territories around the world, updated regularly throughout each day. + +Every country reports those figures a little differently and, inevitably, misses undiagnosed infections and deaths. With this project we are focusing on the trends within countries as they try to contain the virusโ€™ spread, whether they are approaching or past peak infection rates, or if they are seeing a resurgence of infections or deaths. +:end +notes: [Read more about our methodology](https://www.reuters.com/world-coronavirus-tracker-and-maps/en/methodology/) +[] +``` + +... which you'll parse out of a ArchieML block object before passing to the `InfoBox` component. + +```svelte + + + +# Graphics kit +{#each content.blocks as block} + {#if block.type === 'info-box'} + + + {/if} +{/each} +``` + + + +## Lists + +Use markdown to add lists to `InfoBox`. + +```svelte + + + +``` + + +## Customisation + +Use [snippets](https://svelte.dev/docs/svelte/snippet) to customise the `InfoBox`, such as adding tables, icons and thumbnail images. + +```svelte + + + {#snippet header()} +

Global video game market

+ {/snippet} + + {#snippet body()} + + + + + + + + + + + + + + + + + + + + + +
YearMarket size ($bln)
2024274.63
2023281.77
2022249.55
+ {/snippet} + + {#snippet updated()} +
Source: Precedence Research
+ {/snippet} +
+``` + + diff --git a/src/components/InfoBox/InfoBox.stories.svelte b/src/components/InfoBox/InfoBox.stories.svelte new file mode 100644 index 0000000..f07fc99 --- /dev/null +++ b/src/components/InfoBox/InfoBox.stories.svelte @@ -0,0 +1,98 @@ + + + + + + + + + + + {#snippet header()} +

Global video game market

+ {/snippet} + {#snippet body()} + + + + + + + + + + + + + + + + + + + + + +
YearMarket size ($bln)
2024274.63
2023281.77
2022249.55
+ {/snippet} + {#snippet footer()} +
Source: Precedence Research
+ {/snippet} +
+
+ + diff --git a/src/components/InfoBox/InfoBox.svelte b/src/components/InfoBox/InfoBox.svelte new file mode 100644 index 0000000..d347963 --- /dev/null +++ b/src/components/InfoBox/InfoBox.svelte @@ -0,0 +1,160 @@ + + + + + + diff --git a/src/components/Lottie/Debug.svelte b/src/components/Lottie/Debug.svelte new file mode 100644 index 0000000..8fc6faf --- /dev/null +++ b/src/components/Lottie/Debug.svelte @@ -0,0 +1,269 @@ + + + + +
+
+ + CONSOLE + +
+ +

Progress:

+
+

{componentState.progress}

+
+
+
+
+ +

Duration:

+

+ {componentState.duration}s +

+ + {#if componentState.segment} +

Segment:

+

+ {componentState.segment[0]} -- {componentState.segment[1]} +

+ {/if} + +

Current frame:

+

+ {componentState.currentFrame}/{componentState.totalFrames} +

+ +

Speed:

+

+ {componentState.speed} +

+ +

Autoplay:

+

+ {componentState.autoplay} +

+ +

Loop:

+

+ {componentState.loop} + {componentState.loop ? `(Loop count: ${componentState.loopCount})` : ''} +

+ +

Mode:

+

+ {componentState.mode} +

+ +

Layout:

+

+ {JSON.stringify(componentState.layout)} +

+ + {#if Object.keys(componentState.allMarkers).length} +

All markers:

+

+ {componentState.allMarkers} +

+ {/if} + + {#if componentState.marker} +

Active marker:

+

+ {componentState.marker} +

+ {/if} + + {#if componentState.allThemes.length} +

All themes:

+

+ {componentState.allThemes.join(', ')} +

+ {/if} + {#if componentState.activeThemeId} +

Active theme ID:

+

+ {componentState.activeThemeId} +

+ {/if} + +

isPaused:

+

+ {componentState.isPaused} +

+ +

isPlaying:

+

+ {componentState.isPlaying} +

+ +

isStopped:

+

+ {componentState.isStopped} +

+ +

isLoaded:

+

+ {componentState.isLoaded} +

+ +

isFrozen:

+

+ {componentState.isFrozen} +

+
+
+
+ + diff --git a/src/components/Lottie/Lottie.mdx b/src/components/Lottie/Lottie.mdx new file mode 100644 index 0000000..6c0029b --- /dev/null +++ b/src/components/Lottie/Lottie.mdx @@ -0,0 +1,386 @@ +import { Meta } from '@storybook/blocks'; + +import * as LottieStories from './Lottie.stories.svelte'; +import CompositionMarkerImage from './assets/marker.jpg?url'; + + + +# Lottie + +The `Lottie` component uses the [dotLottie-web](https://developers.lottiefiles.com/docs/dotlottie-player/dotlottie-web/) library to render Lottie animations. + +## How to prepare Lottie files + +[LottieFiles](https://lottiefiles.com/) is the official platform for creating and editing Lottie animations. The free version of LottieFiles has limited features, so [Bodymovin](https://exchange.adobe.com/apps/cc/12557/bodymovin) remains a popular, free way to export Lottie animations as JSON files. + +[dotLottie](https://dotlottie.io/) is another common format for Lottie files. This format bundles the Lottie JSON file and any associated assets, such as images and fonts, into a single compressed file with the extension `.lottie`. + +This `Lottie` component is flexible and supports both `dotLottie` and JSON Lottie files. For best performance it is recommended that you convert your Lottie JSON file into a `.zip` file by following these steps: + +1. Export your Lottie animation as a JSON file using [Bodymovin](https://exchange.adobe.com/apps/cc/12557/bodymovin) or another Lottie exporter. +2. Use the [LottieFiles converter](https://lottiefiles.com/tools/lottie-to-dotlottie) to convert the JSON file into a `.lottie` file. +3. Change the file extension to `.zip` from `.lottie`. This ensures full compatibility with the Reuters graphics publisher while maintaining the benefits of dotLottie format's compression and optimisation. + +## When not to use Lottie + +Lottie animations are great for lightweight, scalable animations. However, they may not be suitable for all use cases. Consider the following before using Lottie: + +- **Huge raster images**: Lottie is best suited for simple to moderately complex animations. Animations with large raster images may not render well or could lead to performance issues. In such cases, consider using a [Video](?path=/docs/components-multimedia-video--docs) component or a [ScrollerVideo](?path=/docs/components-graphics-scrollervideo--docs) component instead. + +- **Complex effects**: Some advanced effects and features available in After Effects may not be fully supported in Lottie, which could lead to discrepancies between the original design and the rendered animation. Check the [Lottie documentation](https://lottiefiles.com/supported-features) for a list of supported features. + +- **Text rendering**: Lottie renders text as vector shapes. If you need DOM text for accessibility or CSS manipulation, consider using HTML/CSS animations instead. + +- **SVG DOM manipulation**: Lottie renders animations on a canvas. If you need to manipulate individual elements of the animation using JavaScript or CSS, consider using SVG animations instead. + +## Basic demo + +To use the `Lottie` component, import it and provide the Lottie animation source. The height of the container defaults to `100lvh`, but you can adjust this to any valid CSS height value such as `1200px` or `200lvh` with the `height` prop. + +**Use `lvh` or `svh` units instead of `vh`** as [these units](https://www.w3.org/TR/css-values-4/#large-viewport-size) are more reliable on mobile and other devices where elements such as the address bar appear and disappear and affect the height. + +The component also provides a `width` prop to set the width of the Lottie container. While the `width` prop defaults to `fluid`, it allows any `ContainerWidth` value such as `narrower`, `narrow`, `normal`, `wide`, `wider`, `widest`, `fluid`, or a custom CSS width value like `600px` or `80vw`. + +If importing the Lottie file directly into a Svelte component, make sure to append **?url** to the import statement (see example below). This ensures that the file is treated as a URL. + +> ๐Ÿ’กTIP: Set `showDebugInfo` prop to `true` to display information about the component state. + +[Demo](?path=/story/components-graphics-scrollerlottie--demo) + +```svelte + + + +``` + +## Using with ArchieML + +If you are using `Lottie` with ArchieML, store your Lottie zip file in the `src/statics/lottie/` folder. + +With the graphics kit, you'll likely get your text and prop values from an ArchieML doc... + +```yaml +# ArchieML doc +[blocks] + type: lottie + + # Lottie file stored in `src/statics/lottie/` folder + src: lottie/LottieFile.zip + autoplay: true + loop: true + showDebugInfo: true +[] +``` + +... which you'll parse out of a ArchieML block object before passing to the `Lottie` component. + +```svelte + + +{#each content.blocks as block} + + {#if block.type == 'lottie'} + + {/if} +{/each} +``` + +## Playing a segment + +The `Lottie` component can play a specific segment of the Lottie animation using the `segment` prop. The `segment` prop expects an array of two numbers representing the start and end frames of the segment. + +[Demo](?path=/story/components-graphics-scrollerlottie--segment) + +With the graphics kit, you'll likely get your text and prop values from an ArchieML doc... + +```yaml +# ArchieML doc +[blocks] + type: lottie + showDebugInfo: true + loop: true + + # Optionally, set playback speed + speed: 0.5 + + # Lottie file stored in `src/statics/lottie/` folder + src: lottie/LottieFile.zip + [.segment] + start: 0 + end: 20 + [] +[] +``` + +... which you'll parse out of a ArchieML block object before passing to the `Lottie` component. + +```svelte + + +{#each content.blocks as block} + + {#if block.type == 'lottie'} + + {/if} +{/each} +``` + +## Markers + +The `Lottie` component can also play a specific portion of the Lottie animation using markers set in [AfterEffects](https://helpx.adobe.com/in/after-effects/using/layer-markers-composition-markers.html). + +The list of available markers, which can be passed into the `marker` prop, can be found in the debug info box that appears when `showDebugInfo` is set to `true`. + +When setting markers in AfterEffects, ensure that the **Comment** section of the Composition Marker contains only the name of your marker: + +Composition Marker Dialog + +[Demo](?path=/story/components-graphics-scrollerlottie--marker) + +```svelte + + + +``` + +## Switching themes + +[Lottie Creator](https://lottiefiles.com/theming) allows you to define multiple colour themes for your animation. You can switch between these themes using the `theme` prop. + +Available themes can be found in the debug info when the `showDebugInfo` prop is set to `true`. + +You can set multiple themes and switch between them dynamically -- for example, based on the `progress` of the animation. + +[Demo](?path=/story/components-graphics-scrollerlottie--themes) + +```svelte + + + +``` + +## Using with `ScrollerBase` + +The `Lottie` component can be used with the `ScrollerBase` component to create a more complex scrolling experience. `ScrollerBase` provides a scrollable container sets the `Lottie` component as a background. + +```svelte + + + + {#snippet backgroundSnippet()} + + + {/snippet} + {#snippet foregroundSnippet()} +
+

Step 1

+
+
+

Step 2

+
+
+

Step 3

+
+ {/snippet} +
+ + +``` + +## With foregrounds + +The `Lottie` component can also be used with the `LottieForeground` component to display foreground elements at specific times in the animation. + +[Demo](?path=/story/components-graphics-scrollerlottie--with-foregrounds). + +```svelte + + + + + +
+ + + +
+
+ + + +
+``` + +### Using with ArchieML + +With the graphics kit, you'll likely get your text and prop values from an ArchieML doc... + +```yaml +# ArchieML doc +[blocks] + type: lottie + + # Lottie file stored in `src/statics/lottie/` folder + src: lottie/LottieFile.zip + + # Array of foregrounds + [.foregrounds] + + # Foreground 1: Headline component + startFrame: 0 # When in the animation to start showing the foreground + endFrame: 50 # When to stop showing the foreground + + # Set foreground type + type: component + + # Set props to pass into `LottieForeground` + {.foregroundProps} + componentName: Headline + hed: Headline + dek: Some deck text + [.authors] + * Jane Doe + * John Smith + [] + {} + + # Foreground 2: Text only + startFrame: 50 + endFrame: 100 + + # Set foreground type + type: text + + # If the foreground type is `text`, set text prop here + {.foregroundProps} + text: Some text for the foreground + {} + +[] +``` + +... which you'll parse out of a ArchieML block object before passing to the `Lottie` component. + +```svelte + + +{#each content.blocks as block} + + {#if block.type == 'lottie'} + + {#each block.foregrounds as foreground} + {#if foreground.type == 'text'} + + {:else if foreground.type == 'component'} + {@const Component = + Components[foreground.foregroundProps.componentName]} + + + + {/if} + {/each} + + {/if} +{/each} +``` diff --git a/src/components/Lottie/Lottie.stories.svelte b/src/components/Lottie/Lottie.stories.svelte new file mode 100644 index 0000000..8ecc7da --- /dev/null +++ b/src/components/Lottie/Lottie.stories.svelte @@ -0,0 +1,150 @@ + + + + {#snippet children(args)} + + {/snippet} + + + + {#snippet children(args)} + + {/snippet} + + + + {#snippet children(args)} + + {/snippet} + + + + {#snippet children(args)} + + {/snippet} + + + + + + + + + +
+ + + +
+
+ + +
+
+ + diff --git a/src/components/Lottie/Lottie.svelte b/src/components/Lottie/Lottie.svelte new file mode 100644 index 0000000..d7a64ec --- /dev/null +++ b/src/components/Lottie/Lottie.svelte @@ -0,0 +1,443 @@ + + +
+ {#if showDebugInfo && lottiePlayer} + + {/if} + +
+ +
+ + {#if children} + {@render children()} + {/if} +
+ + diff --git a/src/components/Lottie/LottieForeground.svelte b/src/components/Lottie/LottieForeground.svelte new file mode 100644 index 0000000..ed74a21 --- /dev/null +++ b/src/components/Lottie/LottieForeground.svelte @@ -0,0 +1,145 @@ + + +
+ {#if componentState?.currentFrame && componentState.currentFrame >= startFrame && componentState.currentFrame <= endFrame} +
+ + {#if text} + +
+ +
+
+ + {:else if children} + {@render children()} + {/if} +
+ {/if} +
+ + diff --git a/src/components/Lottie/assets/marker.jpg b/src/components/Lottie/assets/marker.jpg new file mode 100644 index 0000000..37f729e Binary files /dev/null and b/src/components/Lottie/assets/marker.jpg differ diff --git a/src/components/Lottie/demo/withScrollerBase.svelte b/src/components/Lottie/demo/withScrollerBase.svelte new file mode 100644 index 0000000..483626d --- /dev/null +++ b/src/components/Lottie/demo/withScrollerBase.svelte @@ -0,0 +1,64 @@ + + + + + + {#snippet backgroundSnippet()} + + {/snippet} + {#snippet foregroundSnippet()} +

Step 1

+

Step 2

+

Step 3

+

Step 4

+

Step 5

+ {/snippet} +
+ + + + diff --git a/src/components/Lottie/lottie/demo.zip b/src/components/Lottie/lottie/demo.zip new file mode 100644 index 0000000..2739af5 Binary files /dev/null and b/src/components/Lottie/lottie/demo.zip differ diff --git a/src/components/Lottie/lottie/foregroundSample.zip b/src/components/Lottie/lottie/foregroundSample.zip new file mode 100644 index 0000000..2b9e0b5 Binary files /dev/null and b/src/components/Lottie/lottie/foregroundSample.zip differ diff --git a/src/components/Lottie/lottie/markerSample.zip b/src/components/Lottie/lottie/markerSample.zip new file mode 100644 index 0000000..8064b2e Binary files /dev/null and b/src/components/Lottie/lottie/markerSample.zip differ diff --git a/src/components/Lottie/lottie/themesLottie.zip b/src/components/Lottie/lottie/themesLottie.zip new file mode 100644 index 0000000..eed4feb Binary files /dev/null and b/src/components/Lottie/lottie/themesLottie.zip differ diff --git a/src/components/Lottie/ts/lottieState.svelte.ts b/src/components/Lottie/ts/lottieState.svelte.ts new file mode 100644 index 0000000..2b8e971 --- /dev/null +++ b/src/components/Lottie/ts/lottieState.svelte.ts @@ -0,0 +1,61 @@ +import type { Layout } from '@lottiefiles/dotlottie-web'; + +export interface LottieState { + [key: string]: + | number + | boolean + | string + | null + | Array + | Array + | [number, number] + | Layout + | undefined; + progress: number; + currentFrame: number; + totalFrames: number; + duration: number; + loop: boolean; + speed: number; + loopCount: number; + mode: string; + isPaused: boolean; + isPlaying: boolean; + isStopped: boolean; + isLoaded: boolean; + isFrozen: boolean; + segment: null | [number, number]; + autoplay: boolean; + layout: null | Layout; + allMarkers: Array; + marker: undefined | string; + allThemes: Array; + activeThemeId: null | string; +} + +export function createLottieState(): LottieState { + const lottieState = $state({ + progress: 0, + currentFrame: 0, + totalFrames: 0, + duration: 0, + loop: false, + speed: 1, + loopCount: 0, + mode: '', + isPaused: false, + isPlaying: false, + isStopped: false, + isLoaded: false, + isFrozen: false, + segment: null, + autoplay: false, + layout: null, + allMarkers: [], + marker: undefined, + allThemes: [], + activeThemeId: null, + }); + + return lottieState; +} diff --git a/src/components/Lottie/ts/types.ts b/src/components/Lottie/ts/types.ts new file mode 100644 index 0000000..f4b088f --- /dev/null +++ b/src/components/Lottie/ts/types.ts @@ -0,0 +1,45 @@ +// Types +import type { Snippet } from 'svelte'; +import { + type Config, + type DotLottie as DotLottieType, +} from '@lottiefiles/dotlottie-web'; +import { type LottieState } from './lottieState.svelte'; +import type { ContainerWidth } from '../../@types/global'; + +type DotlottieProps = { + autoplay?: Config['autoplay']; + backgroundColor?: Config['backgroundColor']; + data?: Config['data']; + loop?: Config['loop']; + mode?: Config['mode']; + renderConfig?: Config['renderConfig']; + segment?: Config['segment']; + speed?: Config['speed']; + src: Config['src']; + useFrameInterpolation?: Config['useFrameInterpolation']; + marker?: Config['marker'] | undefined; + layout?: Config['layout']; + animationId?: Config['animationId']; + themeId?: Config['themeId']; + playOnHover?: boolean; + themeData?: string; + dotLottieRefCallback?: (dotLottie: DotLottieType) => void; + onLoad?: () => void; + onRender?: () => void; + onComplete?: () => void; +}; + +export type Props = DotlottieProps & { + // Additional properties can be added here if needed + lottiePlayer?: DotLottieType | undefined; + showDebugInfo?: boolean; + width?: string | ContainerWidth; + height?: string; + lottieState?: LottieState; + progress?: number; + tweenDuration?: number; + easing?: (t: number) => number; + /** Children render function */ + children?: Snippet; +}; diff --git a/src/components/Lottie/ts/utils.ts b/src/components/Lottie/ts/utils.ts new file mode 100644 index 0000000..dec2c2a --- /dev/null +++ b/src/components/Lottie/ts/utils.ts @@ -0,0 +1,127 @@ +import type { DotLottie } from '@lottiefiles/dotlottie-web'; +import type { LottieState } from './lottieState.svelte'; +import type { ContainerWidth } from '$lib/components/@types/global'; + +function constrain(n: number, low: number, high: number) { + return Math.max(Math.min(n, high), low); +} + +export function map( + n: number, + start1: number, + stop1: number, + start2: number, + stop2: number, + withinBounds: boolean = true +) { + const newval = ((n - start1) / (stop1 - start1)) * (stop2 - start2) + start2; + if (!withinBounds) { + return newval; + } + if (start2 < stop2) { + return constrain(newval, start2, stop2); + } else { + return constrain(newval, stop2, start2); + } +} + +/** + * Syncs the lottie player state with the component's lottie state + */ +export function syncLottieState( + lottiePlayer: DotLottie, + lottieState: LottieState +) { + lottieState.currentFrame = lottiePlayer.currentFrame; + lottieState.totalFrames = lottiePlayer.totalFrames; + lottieState.duration = lottiePlayer.duration; + lottieState.loop = lottiePlayer.loop; + lottieState.speed = lottiePlayer.speed; + lottieState.loopCount = lottiePlayer.loopCount; + lottieState.mode = lottiePlayer.mode; + lottieState.isPaused = lottiePlayer.isPaused; + lottieState.isPlaying = lottiePlayer.isPlaying; + lottieState.isStopped = lottiePlayer.isStopped; + lottieState.isLoaded = lottiePlayer.isLoaded; + lottieState.isFrozen = lottiePlayer.isFrozen; + lottieState.segment = lottiePlayer.segment ?? null; + lottieState.autoplay = lottiePlayer.autoplay ?? false; + lottieState.layout = lottiePlayer.layout ?? null; + lottieState.activeThemeId = lottiePlayer.activeThemeId ?? null; + lottieState.marker = lottiePlayer.marker ?? undefined; +} + +/** + * Gets marker info by name + */ +export function getMarkerByName(lottiePlayer: DotLottie, markerName: string) { + return lottiePlayer.markers().find((m) => m.name === markerName); +} + +/** + * Gets the start and end frames for a marker + */ +export function getMarkerRange( + lottiePlayer: DotLottie, + markerName: string +): [number, number] { + const marker = getMarkerByName(lottiePlayer, markerName); + const start = marker?.time ?? 0; + const end = start + (marker?.duration ?? 0); + return [start, end]; +} + +/** + * Calculates target frame based on progress and mode + */ +export function calculateTargetFrame( + progress: number, + mode: string, + start: number, + end: number +): number { + const adjustedProgress = + mode === 'reverse' || mode === 'reverse-bounce' ? 1 - progress : progress; + return map(adjustedProgress, 0, 1, start, end); +} + +/** + * Determines if mode is reverse + */ +export function isReverseMode(mode: string): boolean { + return mode === 'reverse' || mode === 'reverse-bounce'; +} + +/** + * Creates render config with optimized defaults + */ +export function createRenderConfig() { + return { + autoResize: true, + devicePixelRatio: + window.devicePixelRatio > 1 ? window.devicePixelRatio * 0.75 : 1, + freezeOnOffscreen: true, + }; +} + +/** + * Checks if a value is null or undefined (empty marker check) + */ +export function isNullish(value: unknown): boolean { + return value === null || value === undefined || value === ''; +} + +/** + * Checks if a value is of type ContainerWidth + */ +export function isContainerWidth(string: string): string is ContainerWidth { + return ( + string === 'narrower' || + string === 'narrow' || + string === 'normal' || + string === 'wide' || + string === 'wider' || + string === 'widest' || + string === 'fluid' + ); +} diff --git a/src/components/PaddingReset/PaddingReset.mdx b/src/components/PaddingReset/PaddingReset.mdx new file mode 100644 index 0000000..95feb03 --- /dev/null +++ b/src/components/PaddingReset/PaddingReset.mdx @@ -0,0 +1,53 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as PaddingResetStories from './PaddingReset.stories.svelte'; + + + +# PaddingReset + +Sometimes you want a visual element to be fluid, i.e., edge-to-edge, but keep padding on adjacent text such as notes or captions. The `PaddingReset` component resets our normal well padding inside a `fluid` container. + +```svelte + + + + + Alt text + + + +
+ A caption for the image that is padded when Block is fluid. +
+
+
+``` + + + +## Conditional padding + +You can add the padding conditionally by setting the `containerIsFluid` prop to `true` when the `Block` width is `fluid`, which is what many other components in this library do. + +```svelte + + + + + Alt text + + + +
+ A caption for the image that is padded when Block is fluid. +
+
+
+``` diff --git a/src/components/PaddingReset/PaddingReset.stories.svelte b/src/components/PaddingReset/PaddingReset.stories.svelte new file mode 100644 index 0000000..041690f --- /dev/null +++ b/src/components/PaddingReset/PaddingReset.stories.svelte @@ -0,0 +1,49 @@ + + + + + + + + shark + +
+ A caption for the image that is padded when its containing Block is fluid. +
+
+
+
+ + diff --git a/src/components/PaddingReset/PaddingReset.svelte b/src/components/PaddingReset/PaddingReset.svelte new file mode 100644 index 0000000..cfc012b --- /dev/null +++ b/src/components/PaddingReset/PaddingReset.svelte @@ -0,0 +1,34 @@ + + + +{#if containerIsFluid} +
+ + {@render children()} +
+{:else} + + {@render children()} +{/if} + + diff --git a/src/components/PaddingReset/shark.jpg b/src/components/PaddingReset/shark.jpg new file mode 100644 index 0000000..5b54e9f Binary files /dev/null and b/src/components/PaddingReset/shark.jpg differ diff --git a/src/components/PhotoPack/PhotoPack.mdx b/src/components/PhotoPack/PhotoPack.mdx new file mode 100644 index 0000000..e5988a1 --- /dev/null +++ b/src/components/PhotoPack/PhotoPack.mdx @@ -0,0 +1,177 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as PhotoPackStories from './PhotoPack.stories.svelte'; + + + +# PhotoPack + +The `PhotoPack` component makes simple photo grids with custom layouts at various breakpoints. + +`images` are defined with their src, alt text, captions and an optional `maxHeight`, which ensures that an image is no taller than that height in any layout. + +```javascript +const images = [ + { + src: 'https://...', + altText: 'Alt text', + caption: 'Lorem ipsum. REUTERS/Photog', + // Optional max-height of images across all layouts + maxHeight: 800, + }, + // ... +]; +``` + +`layouts` optionally define how images are laid out at different breakpoints. You can customise the layouts and group images into `rows` above a certain `breakpoint` by specifying the number of images that should go in that row. For example: + +```javascript +const layouts = [ + { + breakpoint: 450, + rows: [1, 2, 1], + }, +]; +``` + +... tells the component that when the `PhotoPack` container is 450 pixels or wider, it should group the 4 images in 3 rows: 1 in the first, 2 in the second and 1 in the last. + +If you don't specify any layouts, the component will use a default responsive layout based on the number of images in your pack. + +You can define as many layouts for as many images as you like. + +```svelte + + + +``` + + + +## Using with ArchieML docs + +With the graphics kit, you'll likely get your text value from an ArchieML doc... + +```yaml +# ArchieML doc +[blocks] +type: photo-pack +id: my-photo-pack # Optional +class: mb-2 # Optional +width: wide # Optional +textWidth: normal # Optional +gap: 10 # Optional; must be a number. + +# Array of image metadata + [.images] + src: images/my-img-1.jpg + altText: Alt text + caption: Lorem ipsum. REUTERS/Photog + + src: images/my-img-2.jpg + altText: Alt text + caption: Lorem ipsum. REUTERS/Photog + + ... + [] + +[] +``` + +... which you'll parse out of a ArchieML block object before passing to the `PhotoPack` component. + +> **Important โ—**: The prop `gap` must be a number. ArchieML renders all values -- including numbers -- as strings, so convert the `prop` value to a number before passing it to `PhotoPack`. + +```svelte + + + +{#each content.blocks as block} + {#if block.type === 'photo-pack'} + + ({ + ...img, + src: `${assets}/${img.src}`, + }))} + layouts={[ + { breakpoint: 750, rows: [2, 3] }, + { breakpoint: 450, rows: [1, 2, 2] }, + ]} + /> + {/if} +{/each} +``` + + + +## Smart default layouts + +If you don't specify the `layouts` prop, `PhotoPack` will automatically generate responsive layouts based on the number of images and the container width. + +**How it works:** + +- **Desktop** (1024px+): Number of images per row depends on container width: + - `normal`: max 2 per row + - `wide` / `wider`: max 3 per row + - `widest` / `fluid`: max 4 per row +- **Tablet** (768px+): Always max 2 per row +- **Mobile** (below 768px): 1 per row + +The smart defaults use a **bottom-heavy distribution**, meaning earlier rows have fewer images (making them larger and more prominent), while later rows have more images. + +**Examples:** + +- 5 images, `wide` container, desktop: `[2, 3]` (2 in first row, 3 in second) +- 7 images, `widest` container, desktop: `[3, 4]` (3 in first row, 4 in second) +- 4 images, any container, desktop: `[2, 2]` (evenly distributed) + +```svelte + + + + +``` diff --git a/src/components/PhotoPack/PhotoPack.stories.svelte b/src/components/PhotoPack/PhotoPack.stories.svelte new file mode 100644 index 0000000..1eb8522 --- /dev/null +++ b/src/components/PhotoPack/PhotoPack.stories.svelte @@ -0,0 +1,140 @@ + + + + + + + + + {#snippet children(args)} + {@const { imageCount, ...photoPackProps } = args as SmartDefaultsArgs} + + {/snippet} + diff --git a/src/components/PhotoPack/PhotoPack.svelte b/src/components/PhotoPack/PhotoPack.svelte new file mode 100644 index 0000000..971b29a --- /dev/null +++ b/src/components/PhotoPack/PhotoPack.svelte @@ -0,0 +1,151 @@ + + + + +
+ {#each rows as row, ri} +
+ {#each row as img, i} +
+ {img.altText} + {#if !img.altText} +
altText
+ {/if} +
+ {/each} +
+ {/each} +
+ +
+ + {#each rows as row, ri} + {#each row as img, i} + {#if img.caption} +
+ +
+ {/if} + {/each} + {/each} +
+
+
+
+ + diff --git a/src/components/PhotoPack/utils.ts b/src/components/PhotoPack/utils.ts new file mode 100644 index 0000000..ed022ff --- /dev/null +++ b/src/components/PhotoPack/utils.ts @@ -0,0 +1,94 @@ +import type { Image, Layout } from './PhotoPack.svelte'; + +// Breakpoint constants for smart default layouts +export const DESKTOP_BREAKPOINT = 1024; +export const TABLET_BREAKPOINT = 768; + +/** + * Generates a smart layout for a given number of images with bottom-heavy distribution. + * Avoids single-image rows by redistributing when necessary. + * + * @param imageCount - Total number of images + * @param maxPerRow - Maximum images per row + * @param breakpoint - Breakpoint threshold for this layout + * @returns Layout object with rows array + */ +export const generateSmartLayout = ( + imageCount: number, + maxPerRow: number, + breakpoint: number +): Layout => { + // Handle edge cases + if (imageCount === 0) return { breakpoint, rows: [] }; + if (imageCount === 1) return { breakpoint, rows: [1] }; + + const fullRows = Math.floor(imageCount / maxPerRow); + const remainder = imageCount % maxPerRow; + + let rows: number[] = []; + + if (remainder === 0) { + // Perfect division: all rows have maxPerRow + rows = Array(fullRows).fill(maxPerRow); + } else { + // Bottom-heavy: smaller row at top, larger rows below + // This makes early images larger (fewer per row = bigger display size) + rows = [remainder, ...Array(fullRows).fill(maxPerRow)]; + } + + return { + breakpoint, + rows, + }; +}; + +type ContainerWidth = 'normal' | 'wide' | 'wider' | 'widest' | 'fluid'; + +/** + * Generates smart default layouts for desktop and tablet breakpoints. + * Mobile (below TABLET_BREAKPOINT) automatically shows 1 image per row. + * + * Max images per row by container width: + * - normal: 2 + * - wide/wider: 3 + * - widest/fluid: 4 + * + * @param imageCount - Total number of images + * @param width - Container width setting + * @returns Array of 2 layouts [desktop, tablet] + */ +export const generateDefaultLayouts = ( + imageCount: number, + width: ContainerWidth +): Layout[] => { + // Map container width to max images per row for desktop + const desktopMaxPerRow = + width === 'normal' ? 2 + : width === 'widest' || width === 'fluid' ? 4 + : 3; + + // Tablet always uses max 2 per row + const tabletMaxPerRow = 2; + + return [ + generateSmartLayout(imageCount, desktopMaxPerRow, DESKTOP_BREAKPOINT), + generateSmartLayout(imageCount, tabletMaxPerRow, TABLET_BREAKPOINT), + ]; +}; + +export const groupRows = (images: Image[], layout?: Layout) => { + // Default layout, one img per row + if (!layout) return images.map((img) => [img]); + // Otherwise, chunk into rows according to layout scheme + let i = 0; + const rows = []; + for (const rowLength of layout.rows) { + const row = []; + for (const imgI of [...Array(rowLength).keys()]) { + row.push(images[imgI + i]); + } + rows.push(row); + i += rowLength; + } + return rows; +}; diff --git a/src/components/PymChild/PymChild.mdx b/src/components/PymChild/PymChild.mdx new file mode 100644 index 0000000..00d995d --- /dev/null +++ b/src/components/PymChild/PymChild.mdx @@ -0,0 +1,33 @@ +import { Meta } from '@storybook/blocks'; + +import * as PymChildStories from './PymChild.stories.svelte'; + + + +# PymChild + +The `PymChild` component creates a [Pym.js](https://blog.apps.npr.org/pym.js/) child instance for embeddables. + +```svelte + + + +``` + +You can access the Pym.js child via `pym` in other components to send custom height updates to parent frames: + +```svelte + + + + + +``` diff --git a/src/components/PymChild/PymChild.stories.svelte b/src/components/PymChild/PymChild.stories.svelte new file mode 100644 index 0000000..36c1f1f --- /dev/null +++ b/src/components/PymChild/PymChild.stories.svelte @@ -0,0 +1,11 @@ + + + diff --git a/src/components/PymChild/PymChild.svelte b/src/components/PymChild/PymChild.svelte new file mode 100644 index 0000000..c7c5a55 --- /dev/null +++ b/src/components/PymChild/PymChild.svelte @@ -0,0 +1,18 @@ + + diff --git a/src/components/PymChild/state.svelte.ts b/src/components/PymChild/state.svelte.ts new file mode 100644 index 0000000..71c43a6 --- /dev/null +++ b/src/components/PymChild/state.svelte.ts @@ -0,0 +1,5 @@ +import type p from 'pym.js'; + +type PymChild = { child: p.Child | null }; + +export const pym = $state({ child: null }); diff --git a/src/components/ReferralBlock/ReferralBlock.mdx b/src/components/ReferralBlock/ReferralBlock.mdx new file mode 100644 index 0000000..0cffe82 --- /dev/null +++ b/src/components/ReferralBlock/ReferralBlock.mdx @@ -0,0 +1,44 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as ReferralBlockStories from './ReferralBlock.stories.svelte'; + + + +# ReferralBlock + +The `ReferralBlock` component creates a set of referral links from recent Reuters.com stories using the [recent stories by section API](https://www.reuters.com/pf/api/v3/content/fetch/recent-stories-by-sections-v1?query=%7B%22section_ids%22%3A%22%2Fworld%2F%22%2C%22size%22%3A20%2C%22website%22%3A%22reuters%22%7D). + +> Note: The `section` or `collection` prop determines which section or collection stories are from. +> +> You can get the section ID from the URL for the Reuters.com section pages. For example, the section ID for [World - Europe](https://www.reuters.com/world/europe/) stories at `www.reuters.com/world/europe/` would be `/world/europe/`. (The leading and trailing slashes are required!) +> +> You should get the collection alias from the dotcom team. + +```svelte + + + +``` + + + +## Collections + +TK - Check if this is still relevant. + +```svelte + + + +``` + + +``` diff --git a/src/components/ReferralBlock/ReferralBlock.stories.svelte b/src/components/ReferralBlock/ReferralBlock.stories.svelte new file mode 100644 index 0000000..966575f --- /dev/null +++ b/src/components/ReferralBlock/ReferralBlock.stories.svelte @@ -0,0 +1,51 @@ + + + + + diff --git a/src/components/ReferralBlock/ReferralBlock.svelte b/src/components/ReferralBlock/ReferralBlock.svelte new file mode 100644 index 0000000..fe26c88 --- /dev/null +++ b/src/components/ReferralBlock/ReferralBlock.svelte @@ -0,0 +1,258 @@ + + + +{#if referrals.length === number} + + + +{/if} + + diff --git a/src/components/ReferralBlock/filterCurrentPage.ts b/src/components/ReferralBlock/filterCurrentPage.ts new file mode 100644 index 0000000..2536555 --- /dev/null +++ b/src/components/ReferralBlock/filterCurrentPage.ts @@ -0,0 +1,35 @@ +import type { Article } from './types'; + +const getUrlFromPath = (path: string) => { + const base = 'https://www.reuters.com'; + + try { + return new URL(path); + } catch { + try { + return new URL(path, base); + } catch { + return null; + } + } +}; + +const isCurrentPage = (urlPath: string) => { + if (typeof window === 'undefined' || typeof window.location === 'undefined') { + return false; + } + const url = getUrlFromPath(urlPath); + if (!url) return false; + return ( + window.location.origin === url.origin && + window.location.pathname === url.pathname + ); +}; + +export const articleIsNotCurrentPage = (article: Article) => { + const { redirect_url: redirectUrl, canonical_url: canonicalUrl } = article; + + if (redirectUrl) return !isCurrentPage(redirectUrl); + if (canonicalUrl) return !isCurrentPage(canonicalUrl); + return true; +}; diff --git a/src/components/ReferralBlock/types.ts b/src/components/ReferralBlock/types.ts new file mode 100644 index 0000000..b087500 --- /dev/null +++ b/src/components/ReferralBlock/types.ts @@ -0,0 +1,109 @@ +export interface Referrals { + statusCode: number; + message: string; + result: Result; +} + +interface Result { + date_modified: Date; + pagination: Pagination; + fetch_type: string; + title: string; + articles: Article[]; +} + +export interface Article { + id: string; + canonical_url: string; + basic_headline: string; + title: string; + lead_art: LeadArt; + description: string; + web: string; + content_code: string; + updated_time: Date; + published_time: Date; + display_time: Date; + thumbnail: LeadArt; + primary_media_type: string; + source: Source; + redirect_url: string; + distributor: string; + authors: Author[]; + kicker: Kicker; + content_elements: unknown[]; + headline_category?: unknown; + content?: { + third_party?: unknown; + }; +} + +interface Author { + topic_url: string; + thumbnail: Thumbnail; + id: string; + name: string; + first_name: string; + last_name: string; + company: string; + social_links: SocialLink[]; + byline: string; +} + +interface SocialLink { + url: string; + site: string; +} + +interface Thumbnail { + url: string; + resizer_url: string; + renditions: Renditions; +} + +interface Renditions { + square: Landscape; + landscape: Landscape; + portrait: Landscape; + original: Landscape; +} + +interface Landscape { + '60w': string; + '120w': string; + '240w': string; + '480w': string; + '960w': string; + '1080w': string; + '1200w': string; + '1920w': string; +} + +interface Kicker { + name: string; + path: string; + names: string[]; +} + +interface LeadArt { + type: string; + url: string; + resizer_url: string; + renditions: Renditions; + id: string; + caption?: string; + alt_text: string; + width: number; + height: number; + subtitle: string; + updated_at: Date; +} + +interface Source { + name: string; +} + +interface Pagination { + size: number; + expected_size: number; +} diff --git a/src/components/ReutersGraphicsLogo/ReutersGraphicsLogo.mdx b/src/components/ReutersGraphicsLogo/ReutersGraphicsLogo.mdx new file mode 100644 index 0000000..6e7c817 --- /dev/null +++ b/src/components/ReutersGraphicsLogo/ReutersGraphicsLogo.mdx @@ -0,0 +1,21 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as ReutersGraphicsLogoStories from './ReutersGraphicsLogo.stories.svelte'; + + + +# ReutersGraphicsLogo + +The `ReutersGraphicsLogo` component contains the Reuters Graphics team logo. + +> Generally, used only for internal tools. For public pages, use the [ReutersLogo](./?path=/docs/components-logos-reuterslogo--docs) component. + +```svelte + + + +``` + + diff --git a/src/components/ReutersGraphicsLogo/ReutersGraphicsLogo.stories.svelte b/src/components/ReutersGraphicsLogo/ReutersGraphicsLogo.stories.svelte new file mode 100644 index 0000000..3409313 --- /dev/null +++ b/src/components/ReutersGraphicsLogo/ReutersGraphicsLogo.stories.svelte @@ -0,0 +1,14 @@ + + + diff --git a/src/components/ReutersGraphicsLogo/ReutersGraphicsLogo.svelte b/src/components/ReutersGraphicsLogo/ReutersGraphicsLogo.svelte new file mode 100644 index 0000000..cb6e31b --- /dev/null +++ b/src/components/ReutersGraphicsLogo/ReutersGraphicsLogo.svelte @@ -0,0 +1,215 @@ + + + + + + diff --git a/src/components/ReutersLogo/ReutersLogo.mdx b/src/components/ReutersLogo/ReutersLogo.mdx new file mode 100644 index 0000000..e4d3b63 --- /dev/null +++ b/src/components/ReutersLogo/ReutersLogo.mdx @@ -0,0 +1,19 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as ReutersLogoStories from './ReutersLogo.stories.svelte'; + + + +# ReutersLogo + +The `ReutersLogo` component contains the official Reuters logo. + +```svelte + + + +``` + + diff --git a/src/components/ReutersLogo/ReutersLogo.stories.svelte b/src/components/ReutersLogo/ReutersLogo.stories.svelte new file mode 100644 index 0000000..5ab6725 --- /dev/null +++ b/src/components/ReutersLogo/ReutersLogo.stories.svelte @@ -0,0 +1,15 @@ + + + diff --git a/src/components/ReutersLogo/ReutersLogo.svelte b/src/components/ReutersLogo/ReutersLogo.svelte new file mode 100644 index 0000000..aadffae --- /dev/null +++ b/src/components/ReutersLogo/ReutersLogo.svelte @@ -0,0 +1,188 @@ + + + + + + diff --git a/src/components/SEO/SEO.mdx b/src/components/SEO/SEO.mdx new file mode 100644 index 0000000..e56e7ca --- /dev/null +++ b/src/components/SEO/SEO.mdx @@ -0,0 +1,80 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as SEOStories from './SEO.stories.svelte'; + + + +# SEO + +The `SEO` component adds essential metadata to pages. + +```svelte + + + +``` + +## Using with ArchieML docs + +With the graphics kit, you'll likely get many of your text values from an ArchieML doc... + +```yaml +# ArchieML doc +slug: ROOT-SLUG/WILD +seoTitle: Page title for search +seoDescription: Page description for search +shareTitle: Page title for social media +shareDescription: Page description for social media +shareImgPath: images/reuters-graphics.jpg +shareImgAlt: Alt text for share image. +``` + +... which you'll pass to the `SEO` component. + +```svelte + + + +``` + +> **Note:** For _reasons_, we can't document the value of `VITE_BASE_URL` below. It's `import` + `.meta.env.BASE_URL` (concatenate all that) in the graphics kit and other Vite-based rigs. + + +``` diff --git a/src/components/SEO/SEO.stories.svelte b/src/components/SEO/SEO.stories.svelte new file mode 100644 index 0000000..dc35435 --- /dev/null +++ b/src/components/SEO/SEO.stories.svelte @@ -0,0 +1,23 @@ + + +
View page source to see the SEO metadata.
+ diff --git a/src/components/SEO/SEO.svelte b/src/components/SEO/SEO.svelte new file mode 100644 index 0000000..19bc694 --- /dev/null +++ b/src/components/SEO/SEO.svelte @@ -0,0 +1,197 @@ + + + + + {#key canonicalUrl} + {seoTitle} + + + + + + + + + + + + + + + + + + + + + + {#if shareImgAlt} + + {/if} + + + + + + + + {@html `<${'script'} type="application/ld+json">${JSON.stringify( + orgLdJson + )}`} + + {@html `<${'script'} type="application/ld+json">${JSON.stringify( + articleLdJson + )}`} + {/key} + diff --git a/src/components/Scroller/Background.svelte b/src/components/Scroller/Background.svelte new file mode 100644 index 0000000..8a37201 --- /dev/null +++ b/src/components/Scroller/Background.svelte @@ -0,0 +1,51 @@ + + +{#each steps as step, i} + {#if showStep(i)} +
+ +
+ {/if} +{/each} + + diff --git a/src/components/Scroller/Embedded/Background.svelte b/src/components/Scroller/Embedded/Background.svelte new file mode 100644 index 0000000..b7bc244 --- /dev/null +++ b/src/components/Scroller/Embedded/Background.svelte @@ -0,0 +1,18 @@ + + + + + diff --git a/src/components/Scroller/Embedded/Foreground.svelte b/src/components/Scroller/Embedded/Foreground.svelte new file mode 100644 index 0000000..a1f451b --- /dev/null +++ b/src/components/Scroller/Embedded/Foreground.svelte @@ -0,0 +1,48 @@ + + +{#if step.foreground === '' || !step.foreground} + +
+ + {#if typeof step.altText === 'string'} +
+ +
+ {/if} +{:else if typeof step.foreground === 'string'} + +
+ +
+ + {#if typeof step.altText === 'string'} +
+ +
+ {/if} +
+{:else} +
+ +
+{/if} + + diff --git a/src/components/Scroller/Embedded/index.svelte b/src/components/Scroller/Embedded/index.svelte new file mode 100644 index 0000000..1148401 --- /dev/null +++ b/src/components/Scroller/Embedded/index.svelte @@ -0,0 +1,31 @@ + + +{#each steps as step, index} + + {#if embeddedLayout === 'bf'} + + + + {:else} + + + {/if} +{/each} diff --git a/src/components/Scroller/Foreground.svelte b/src/components/Scroller/Foreground.svelte new file mode 100644 index 0000000..e42912f --- /dev/null +++ b/src/components/Scroller/Foreground.svelte @@ -0,0 +1,64 @@ + + +{#each steps as step, i} +
+ {#if step.foreground === '' || !step.foreground} + +
+ {#if typeof step.altText === 'string'} +
+ +
+ {/if} + {:else} +
+ {#if typeof step.foreground === 'string'} + + {:else} + + {/if} +
+ {#if typeof step.altText === 'string'} +
+ +
+ {/if} + {/if} +
+{/each} + + diff --git a/src/components/Scroller/Scroller.mdx b/src/components/Scroller/Scroller.mdx new file mode 100644 index 0000000..9c2b9e1 --- /dev/null +++ b/src/components/Scroller/Scroller.mdx @@ -0,0 +1,279 @@ +import { Meta } from '@storybook/blocks'; + +import * as ScrollerStories from './Scroller.stories.svelte'; + + + +# Scroller + +The `Scroller` component creates a basic scrollytelling graphic with layout options. + +This component is designed to handle most common layouts for scrollytelling. To make something more complex, customise [ScrollerBase](?path=/story/components-graphics-scrollerbase--docs), which is a Svelte 5 version of the [svelte-scroller](https://github.com/sveltejs/svelte-scroller). + +[Demo](?path=/story/components-graphics-scroller--demo) + +```svelte + + + +``` + +## Using with ArchieML and ai2svelte + +[Demo](?path=/story/components-graphics-scroller--archie-ml) + +In your graphics kit project, import your ai2svelte graphics in `App.svelte` and add them to the `aiCharts` object: + +```svelte + + +``` + +Then add the following structure to your ArchieML doc, making sure that the names of your charts in the `aiCharts` object match the names of each step's `background` in the ArchieML doc: + +```yaml +# ArchieML doc +[blocks] +type: ai-scroller +id: my-map-scroller +width: fluid +foregroundPosition: right +stackBackground: true + +# Array of step objects + [.steps] + background: AiMap1 + foreground: #### Step 1 + + Here's where something happend. + :end + altText: A map showing the Upper West side in New York City. + + Can add paragraphs of alt text if you want to break up sentences. + :end + + background: AiMap2 + foreground: #### Step 2 + + Something happened on some street... + :end + altText: The same map now highlights 98th Street. + :end + + background: AiMap3 + foreground: #### Step 3 + + ... and now there are multiple protests. + :end + altText: The same map now highlights three locations near 98th Street where something particulary important happened. + :end + [] +[] +``` + +Then parse the relevant ArchieML block object before passing to the `Scroller` component. + +```svelte + +{#each content.blocks as block} + {#if block.type === 'ai-scroller'} + ({ + background: aiCharts[step.background], + backgroundProps: { assetsPath: assets || '/' }, + foreground: step.foreground, + altText: step.altText, + }))} + /> + {/if} +{/each} +``` + +> **Note:** Some props, like `stackBackground`, expect boolean values. If you're using the graphics kit, use the `truthy()` util function to convert a string value to a boolean. + +> **Note:** In the graphics kit, the image source paths in ai2svelte components have to be fixed by passing `assets` to each step object, like in the example above. + +## Custom foreground + +[Demo](?path=/story/components-graphics-scroller--custom-foreground) + +Instead of just text, you can use components as foregrounds, and optionally pass props to it. + +If you're customising your own foreground component, remember to add alt text that describes the background graphic. + +```svelte + + + +``` + +## Custom foreground with ArchieML + +[Demo](?path=/story/components-graphics-scroller--customforeground-archie-ml) + +You can use custom foreground components with ArchieML with a few additional steps. + +In your graphics kit project's `App.svelte`, import your custom foregroud components and add them to a `foregroundComponents` object, just as you import ai2svelte background graphics and add them to the `aiCharts` object: + +```svelte + + +``` + +Then add the following structure to your ArchieML doc, making sure that the names of your charts in the `aiCharts` and `foregroundComponents` objects match the names of each step's `background` and `foreground` in the ArchieML doc: + +```yaml +# ArchieML doc +[blocks] +type: ai-scroller +id: my-map-scroller +foregroundPosition: left +stackBackground: true + +# Array of step objects + [.steps] + background: AiMap1 + # You can still use a markdown string even if other step/s use a custom foreground component + foreground: #### Step 1 + + Here's where something happend. + :end + altText: A map showing the Upper West side in New York City. + :end + + background: AiMap2 + foreground: Foreground1 # The name of your custom foreground component + altText: The same map now highlights 98th Street. + :end + background: AiMap3 + foreground: #### Step 3 + + ... and now there are multiple protests. + :end + altText: The same map now highlights three locations near 98th Street where something particulary important happened. + :end + [] +[] +``` + +Then parse the relevant ArchieML block object before passing to the `Scroller` component. + +```svelte + +{#each content.blocks as block} + {#if block.type === 'ai-scroller'} + ({ + background: aiCharts[step.background], + backgroundProps: { assetsPath: assets || '/' }, + foreground: foregroundComponents[step.foreground] || step.foreground, + foregroundProps: { assetsPath: assets || '/' }, + altText: step.altText, + }))} + /> + {/if} +{/each} +``` + +> **Note:** You only need to pass `foregroundProps: { assetsPath: assets || '/' }` in the graphics kit if your foreground components are ai2svelte graphicss. diff --git a/src/components/Scroller/Scroller.stories.svelte b/src/components/Scroller/Scroller.stories.svelte new file mode 100644 index 0000000..ca233b3 --- /dev/null +++ b/src/components/Scroller/Scroller.stories.svelte @@ -0,0 +1,195 @@ + + + + + + + + ({ + background: step.background, + foreground: step.foreground, + altText: step.altText, + }))} + /> + + + + + + ({ + background: step.background, + foreground: step.foreground, + altText: step.altText, + }))} + /> + diff --git a/src/components/Scroller/Scroller.svelte b/src/components/Scroller/Scroller.svelte new file mode 100644 index 0000000..37415fa --- /dev/null +++ b/src/components/Scroller/Scroller.svelte @@ -0,0 +1,193 @@ + + + +{#if !embedded} + + + {#snippet backgroundSnippet()} + + {/snippet} + {#snippet foregroundSnippet()} +
+ +
+ {/snippet} +
+
+{:else} + + + +{/if} + + diff --git a/src/components/Scroller/demo/components/ai2svelte/ai-foreground.svelte b/src/components/Scroller/demo/components/ai2svelte/ai-foreground.svelte new file mode 100644 index 0000000..6af40a5 --- /dev/null +++ b/src/components/Scroller/demo/components/ai2svelte/ai-foreground.svelte @@ -0,0 +1,112 @@ + + +
+ + {#if width && width >= 0} +
+
+
+
+

Likelihood of something happening

+
+ +
+

0-25%

+
+
+

50-75%

+
+
+

75-100%

+
+
+

25-50%

+
+
+ {/if} +
+ + + + + + diff --git a/src/components/Scroller/demo/components/ai2svelte/ai-scroller-1.svelte b/src/components/Scroller/demo/components/ai2svelte/ai-scroller-1.svelte new file mode 100644 index 0000000..df60d00 --- /dev/null +++ b/src/components/Scroller/demo/components/ai2svelte/ai-scroller-1.svelte @@ -0,0 +1,121 @@ + + + + +
+ + {#if width && width >= 1200} +
+
+
+
+ {/if} + + {#if width && width >= 930 && width < 1200} +
+
+
+
+ {/if} + + {#if width && width >= 660 && width < 930} +
+
+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+ {/if} + + {#if width && width >= 0 && width < 510} +
+
+
+
+ {/if} +
+ + + + + + + diff --git a/src/components/Scroller/demo/components/ai2svelte/ai-scroller-2.svelte b/src/components/Scroller/demo/components/ai2svelte/ai-scroller-2.svelte new file mode 100644 index 0000000..18a5870 --- /dev/null +++ b/src/components/Scroller/demo/components/ai2svelte/ai-scroller-2.svelte @@ -0,0 +1,310 @@ + + + + +
+ + {#if width && width >= 1200} +
+
+
+
+

This thing here is

+

particularly important

+
+
+ {/if} + + {#if width && width >= 930 && width < 1200} +
+
+
+
+

This thing here is

+

particularly important

+
+
+ {/if} + + {#if width && width >= 660 && width < 930} +
+
+
+
+

This thing here is

+

particularly important

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

This thing here is

+

particularly important

+
+
+ {/if} + + {#if width && width >= 0 && width < 510} +
+
+
+
+

This thing here is

+

particularly important

+
+
+ {/if} +
+ + + + + + diff --git a/src/components/Scroller/demo/components/ai2svelte/ai-scroller-3.svelte b/src/components/Scroller/demo/components/ai2svelte/ai-scroller-3.svelte new file mode 100644 index 0000000..33538e0 --- /dev/null +++ b/src/components/Scroller/demo/components/ai2svelte/ai-scroller-3.svelte @@ -0,0 +1,310 @@ + + + + +
+ + {#if width && width >= 1200} +
+
+
+
+

Something

+

happened here

+
+
+ {/if} + + {#if width && width >= 930 && width < 1200} +
+
+
+
+

Something

+

happened here

+
+
+ {/if} + + {#if width && width >= 660 && width < 930} +
+
+
+
+

Something

+

happened here

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

Something

+

happened here

+
+
+ {/if} + + {#if width && width >= 0 && width < 510} +
+
+
+
+

Something

+

happened here

+
+
+ {/if} +
+ + + + + + diff --git a/src/components/Scroller/demo/components/ai2svelte/images/Body-issues-key-xs.png b/src/components/Scroller/demo/components/ai2svelte/images/Body-issues-key-xs.png new file mode 100644 index 0000000..e03e5e1 Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/Body-issues-key-xs.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-1-lg.png b/src/components/Scroller/demo/components/ai2svelte/images/step-1-lg.png new file mode 100644 index 0000000..de1888e Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-1-lg.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-1-md.png b/src/components/Scroller/demo/components/ai2svelte/images/step-1-md.png new file mode 100644 index 0000000..ead091c Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-1-md.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-1-sm.png b/src/components/Scroller/demo/components/ai2svelte/images/step-1-sm.png new file mode 100644 index 0000000..dada63c Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-1-sm.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-1-xl.png b/src/components/Scroller/demo/components/ai2svelte/images/step-1-xl.png new file mode 100644 index 0000000..55823fb Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-1-xl.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-1-xs.png b/src/components/Scroller/demo/components/ai2svelte/images/step-1-xs.png new file mode 100644 index 0000000..26e4449 Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-1-xs.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-2-lg.png b/src/components/Scroller/demo/components/ai2svelte/images/step-2-lg.png new file mode 100644 index 0000000..9619643 Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-2-lg.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-2-md.png b/src/components/Scroller/demo/components/ai2svelte/images/step-2-md.png new file mode 100644 index 0000000..37450dc Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-2-md.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-2-sm.png b/src/components/Scroller/demo/components/ai2svelte/images/step-2-sm.png new file mode 100644 index 0000000..e236862 Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-2-sm.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-2-xl.png b/src/components/Scroller/demo/components/ai2svelte/images/step-2-xl.png new file mode 100644 index 0000000..fa15744 Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-2-xl.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-2-xs.png b/src/components/Scroller/demo/components/ai2svelte/images/step-2-xs.png new file mode 100644 index 0000000..0fef62a Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-2-xs.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-3-lg.png b/src/components/Scroller/demo/components/ai2svelte/images/step-3-lg.png new file mode 100644 index 0000000..9e4f037 Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-3-lg.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-3-md.png b/src/components/Scroller/demo/components/ai2svelte/images/step-3-md.png new file mode 100644 index 0000000..91cfa1a Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-3-md.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-3-sm.png b/src/components/Scroller/demo/components/ai2svelte/images/step-3-sm.png new file mode 100644 index 0000000..876a388 Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-3-sm.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-3-xl.png b/src/components/Scroller/demo/components/ai2svelte/images/step-3-xl.png new file mode 100644 index 0000000..03e47dd Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-3-xl.png differ diff --git a/src/components/Scroller/demo/components/ai2svelte/images/step-3-xs.png b/src/components/Scroller/demo/components/ai2svelte/images/step-3-xs.png new file mode 100644 index 0000000..26223ca Binary files /dev/null and b/src/components/Scroller/demo/components/ai2svelte/images/step-3-xs.png differ diff --git a/src/components/Scroller/demo/components/basic/InteractiveForeground.svelte b/src/components/Scroller/demo/components/basic/InteractiveForeground.svelte new file mode 100644 index 0000000..769ec63 --- /dev/null +++ b/src/components/Scroller/demo/components/basic/InteractiveForeground.svelte @@ -0,0 +1,17 @@ + + +

Interactive step

+ +

The count is {count}

+ + diff --git a/src/components/Scroller/demo/components/basic/Step.svelte b/src/components/Scroller/demo/components/basic/Step.svelte new file mode 100644 index 0000000..d914ec8 --- /dev/null +++ b/src/components/Scroller/demo/components/basic/Step.svelte @@ -0,0 +1,18 @@ + + +
+ + diff --git a/src/components/ScrollerBase/ScrollerBase.mdx b/src/components/ScrollerBase/ScrollerBase.mdx new file mode 100644 index 0000000..7d8da9a --- /dev/null +++ b/src/components/ScrollerBase/ScrollerBase.mdx @@ -0,0 +1,77 @@ +import { Meta } from '@storybook/blocks'; + +import * as ScrollerBaseStories from './ScrollerBase.stories.svelte'; + + + +# ScrollerBase + +The `ScrollerBase` component powers the [`Scroller` component](?path=/story/components-graphics-scroller--docs), which creates a basic storytelling graphic with preset layout options. `ScrollerBase` contains the bare minimum code necessary for a scrollytelling section, and allows for customisation beyond what the [`Scroller` component](?path=/story/components-graphics-scroller--docs) allows. + +`ScrollerBase` is a Svelte 5 version of the [svelte-scroller](https://github.com/sveltejs/svelte-scroller). + +> **Importantโ—:** Make sure the HTML element containing each foreground is a div with the class `step-foreground-container`. If you're modifying this to something else, pass the appropriate selector to the `query` prop. + +[Demo](?path=/story/components-graphics-scrollerbase--demo) + +```svelte + + + + {#snippet backgroundSnippet()} + +

+ Current step: {index + 1}/{count} +

+ + +

Offset in current step

+ + +

Total progress

+ + {/snippet} + {#snippet foregroundSnippet()} + +
Step 1
+
Step 2
+
Step 3
+
Step 4
+
Step 5
+ {/snippet} +
+ + +``` diff --git a/src/components/ScrollerBase/ScrollerBase.stories.svelte b/src/components/ScrollerBase/ScrollerBase.stories.svelte new file mode 100644 index 0000000..e8cbb78 --- /dev/null +++ b/src/components/ScrollerBase/ScrollerBase.stories.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/components/ScrollerBase/ScrollerBase.svelte b/src/components/ScrollerBase/ScrollerBase.svelte new file mode 100644 index 0000000..13a8c11 --- /dev/null +++ b/src/components/ScrollerBase/ScrollerBase.svelte @@ -0,0 +1,270 @@ + + + + + + + + + + + {@render backgroundSnippet()} + + + + + {@render foregroundSnippet()} + + + + diff --git a/src/components/ScrollerBase/demo/DraggableLabel.svelte b/src/components/ScrollerBase/demo/DraggableLabel.svelte new file mode 100644 index 0000000..34e7cd8 --- /dev/null +++ b/src/components/ScrollerBase/demo/DraggableLabel.svelte @@ -0,0 +1,95 @@ + + +
{ + const customEvent = event as unknown as { detail: { value: number } }; + value = customEvent.detail.value; + }} + role="slider" + aria-valuemin="0" + aria-valuemax="1" + aria-valuenow={value} + tabindex="0" +> +
+
+

{label}: {round(value)}

+
+ + diff --git a/src/components/ScrollerBase/demo/ScrollerDemo.svelte b/src/components/ScrollerBase/demo/ScrollerDemo.svelte new file mode 100644 index 0000000..485f685 --- /dev/null +++ b/src/components/ScrollerBase/demo/ScrollerDemo.svelte @@ -0,0 +1,82 @@ + + + + +
+ + {#snippet backgroundSnippet()} +

+ Current step: {index + 1}/{count} +

+ + +

Offset in current step

+ + +

Total progress

+ + {/snippet} + {#snippet foregroundSnippet()} +
Step 1
+
Step 2
+
Step 3
+
Step 4
+
Step 5
+ {/snippet} +
+
+ + + + + + + + diff --git a/src/components/ScrollerVideo/Debug.svelte b/src/components/ScrollerVideo/Debug.svelte new file mode 100644 index 0000000..b922f22 --- /dev/null +++ b/src/components/ScrollerVideo/Debug.svelte @@ -0,0 +1,222 @@ + + + + +
+
+ + CONSOLE + +
+

Source:

+

{componentState.generalData.src}

+ +

Progress:

+
+

{componentState.generalData.videoPercentage}

+
+
+
+
+ +

Framerate:

+

{componentState.generalData.frameRate}

+ +

Current time:

+

+ {componentState.generalData.currentTime}/{componentState.generalData + .totalTime} +

+ + {#if componentState.usingWebCodecs} +

Codec:

+

+ {componentState.framesData.codec} +

+ + +

Current frame:

+

+ {componentState.framesData.currentFrame}/{componentState.framesData + .totalFrames} +

+ {/if} + +

Will Autoplay?:

+

+ {componentState.willAutoPlay} +

+ + {#if componentState.willAutoPlay} +

Autoplaying:

+

+ {componentState.isAutoPlaying} +

+

Autoplay progress:

+
+

{componentState.autoplayProgress}

+
+
+
+
+ {/if} +
+
+
+ + diff --git a/src/components/ScrollerVideo/ScrollerVideo.mdx b/src/components/ScrollerVideo/ScrollerVideo.mdx new file mode 100644 index 0000000..82c0069 --- /dev/null +++ b/src/components/ScrollerVideo/ScrollerVideo.mdx @@ -0,0 +1,483 @@ +import { Meta } from '@storybook/blocks'; + +import * as ScrollerVideoStories from './ScrollerVideo.stories.svelte'; + + + +# ScrollerVideo + +The `ScrollerVideo` component creates interactive video experiences that respond to user scrolling. It is built on top of [ScrollyVideo.js](https://scrollyvideo.js.org/) and is designed to work seamlessly with Svelte. + +## Basic demo + +To use the `ScrollerVideo` component, import it and provide the video source. The scroll height defaults to `200lvh`, but you can adjust this to any valid CSS height value such as `1200px` or `200lvh` with the `height` prop. + +> ๐Ÿ’กTIP: Use `lvh` or `svh` units instead of `vh` unit for the height, as [these units](https://www.w3.org/TR/css-values-4/#large-viewport-size) are more reliable on mobile or other devices where elements such as the address bar toggle between being shown and hidden. + +[Demo](?path=/story/components-graphics-scrollervideo--demo) + +```svelte + + + + +``` + +## Optimising videos + +When using the `ScrollerVideo` component, minimise the video file size and ensure that the video is encoded in a format that is widely supported across browsers. Videos encoded at higher frame rates (FPS) are bound to crash on mobile devices, so 24 FPS is recommended. + +If at any point your page crashes while using this component (happens often only on phone devices), it is likely due to the video being too large or encoded at a high frame rate. You could also try separate videos for desktop and phone devices to save quality for the desktop viewing experience. + +> ๐Ÿ’ก**TIP:** Set the `showDebugInfo` prop to `true` to see video encoding information + +To optimise your video for the web, you can use `ffmpeg` to convert the video to a suitable format. Here is an example terminal command that converts a video to H.264 format with a resolution of 720p and a frame rate of 24 FPS: + +```bash +npx ffmpeg -y -i .mp4 -c:v libx264 -movflags +faststart -crf 24 -r 24 -g 72 -vf scale=720:-1 -profile:v high -preset veryslow -pix_fmt yuv420p -color_primaries 1 -color_trc 1 -colorspace 1 -an .mp4 +``` + +Adjust the `-crf` value to control the quality. A lower `-crf` value means higher quality, with 20-24 being a generally good balance. The video framerate can be altered by using `-r` flag. Set keyframe intervals using the `-g` flag. It is advisable to keep it around 3 seconds (3 \* video framerate) for a good output. See [FFmpeg documentation](https://ffmpeg.org/ffmpeg.html) and [Testing Media Capabilities](https://cconcolato.github.io/media-mime-support/mediacapabilities.html) for more. + +## Setting custom width + +By default, the `ScrollerVideo` component takes up the full width of its container. To set a custom width, you can wrap the `ScrollerVideo` component in a `` with one of the acceptable `ContainerWidth` values. + +Further, it also allows you to set the `objectFit` property to control how the video should be resized to fit its container. The available options are `cover` and `contain`. The default value is `cover`. + +[Demo](?path=/story/components-graphics-scrollervideo--object-fit) + +```svelte + + + + + + +``` + +## Responsive videos + +To show different videos based on the screen width, use the `ScrollerVideo` component with conditional logic that uses a different video source depending on the [window width](https://svelte.dev/docs/svelte/svelte-window). + +[Demo](?path=/story/components-graphics-scrollervideo--responsive-videos) + +```svelte + + + + +{#if width < 600} + + +{:else if width < 1200} + + +{:else} + + +{/if} +``` + +## Embeds + +Setting `embedded` to `true` will turn `ScrollerVideo` into an embeddable version, where the video autoplays when the user scrolls upon it. Optionally, you can control the embed video behaviour by passing `embeddedProps` to control the autoplay `delay`, `threshold` for triggering autoplay, and the `duration` of the video. + +> ๐Ÿ’ก**TIP:** Another way to recreate the ScrollerVideo experience for embeds is to record the desktop screen with [Scroll Capture](https://chromewebstore.google.com/detail/scroll-capture/egmhoeaacclmanaimofoooiamhpkimkk?hl=en) while scrolling through the video and use that video instead as an HTML video component. + +[Demo](?path=/story/components-graphics-scrollervideo--embed) + +```svelte + + + +``` + +## Autoplay + +The `autoplay` option combines the autoplay and scrollytelling experience. If set to `true`, the video will start playing automatically when the component is mounted, but switch to scrollytelling when the user starts scrolling. The scroll height is calculated based on how much of the video remains, which means that if the user lets the video autoplay to near the end, the user would only have to scroll through a small height to get to the end. If the user lets the video autoplay to the end, there will be no scrolling effect. + +[Demo](?path=/story/components-graphics-scrollervideo--autoplay) + +```svelte + + + +``` + +## Time-based text foregrounds with ArchieML + +The `ScrollerVideo` component can also be used to display text as foregrounds at specific times in the video. To do so, use the `text` prop in `ScrollerVideoForeground` component. + +[Demo](?path=/story/components-graphics-scrollervideo--archie-ml-foregrounds) + +With the graphics kit, you'll likely get your text and prop values from an ArchieML doc... + +```yaml +# ArchieML doc + +[blocks] + type: scroller-video + id: alps-scroller + src: videos/alps.mp4 + height: 800lvh + + # Array of foregrounds + [.foregrounds] + startTime: 3 # When in the video to start showing the foreground + endTime: 7 # When to stop showing the foreground + width: normal # text container width + position: bottom center # Position of the text. Optional; defaults to 'center center'. Must be a combination of `top/bottom/center center/left/right` + backgroundColour: rgba(0, 0, 0, 0.8) # Optional; defaults to white + text: #### The Alps + The Alps stretch across eight countries: France, Switzerland, Italy, Monaco, Liechtenstein, Austria, Germany, and Slovenia, covering about 1,200 kilometers (750 miles). + :end + + startTime: 9 + endTime: 12 + width: normal + position: bottom center + backgroundColour: rgba(0, 0, 0, 0.8) + text: Mont Blanc, standing at 4,809 meters (15,777 feet), is the highest peak in the Alps and Western Europe, though there's ongoing debate between France and Italy about exactly where the summit lies. + :end + + startTime: 16 + endTime: 20 + width: normal + position: bottom center + backgroundColour: rgba(0, 0, 0, 0.8) + text: #### History + The Alps were formed around **65 million years** ago when the African and Eurasian tectonic plates collided, pushing the land upward. Over 14 million people live in the Alpine region, with tourism supporting approximately 120 million visitors annually. + :end + [] +[] +``` + +... which you'll parse out of a ArchieML block object before passing to the `ScrollerVideo` and `ScrollerVideoForeground` components. + +```svelte + + +{#each content.blocks as block} + + {#if block.type == 'scroller-video'} + + + {#each block.foregrounds as foreground} + + {/each} + + {/if} +{/each} +``` + +## Time-based component foregrounds with ArchieML + +The `ScrollerVideo` component can also be used to display components, such as `Headline` or ai2svelte files, as foregrounds at specific times in the video. To do so, use the `Foreground` prop in `ScrollerVideoForeground` component. + +> **IMPORTANTโ—**: When layering ai2svelte files over a video, the aspect ratio of the ai2svelte graphics should match that of the video. If the ai2svelte graphic is responsive and has, for example, small, medium and large versions โ€” which is generally the case โ€” make sure to also render small, medium and large versions of the video at the appropriate screen sizes. See [Responsive videos](#responsive-videos) for more details. + +[Demo](?path=/story/components-graphics-scrollervideo--component-archie-ml-foregrounds) + +With the graphics kit, you'll likely get your text and prop values from an ArchieML doc... + +```yaml +# ArchieML doc + +# Headline +hed: Wind and waves +[authors] + * Jane Doe +[] +publishTime: 2020-01-01T00:00:00Z +startTime: 0 # When in the video to start showing the headline +endTime: 0.3 # When to stop showing the headline + +[blocks] + type: scroller-video + id: my-scroller-video + height: 800lvh + + # Adjust prop names as needed + srcSm: videos/my-video-sm.mp4 + srcMd: videos/my-video-md.mp4 + srcLg: videos/my-video-lg.mp4 + + # Array of foregrounds + [.foregrounds] + startTime: 0.3 # When in the video to start showing the foreground + endTime: 2.2 # When to stop showing the foreground + width: fluid # foreground container width + Foreground: Foreground1 # Name of the ai2svelte component to render + + startTime: 2.2 + endTime: 3.2 + width: fluid + Foreground: Foreground2 + + startTime: 3.2 + endTime: 4.5 + width: fluid + Foreground: Foreground3 + + startTime: 6.5 + endTime: 8 + width: fluid + Foreground: Foreground4 + [] +[] +``` + +... which you'll parse out of a ArchieML block object before passing to the `ScrollerVideo` and `ScrollerVideoForeground` components. + +```svelte + + + + + +{#each content.blocks as block} + {#if block.type == 'scroller-video'} + + {#snippet ScrollVideo(height: string, src: string)} + + + + + + + + {#each block.foregrounds as foreground} + + {/each} + + {/snippet} + + + {#if width < 600} + {@render ScrollVideo(block.height, `${assets}/${block.srcSm}`)} + {:else if width < 1200} + {@render ScrollVideo(block.height, `${assets}/${block.srcMd}`)} + {:else} + {@render ScrollVideo(block.height, `${assets}/${block.srcLg}`)} + {/if} + {/if} +{/each} +``` + +## Using with `ScrollerBase` + +The `ScrollerVideo` component can be used inside the [ScrollerBase](?path=/story/components-graphics-scrollerbase--docs) component to add foreground content. This allows for a foreground that scrolls up and down over the video, instead of fading in and out at specific times. + +> **Note**: To use `ScrollerVideo` with `ScrollerBase`, set `trackScroll` to `false` and pass the bindable prop `progress` from `ScrollerBase` as `videoPercentage` to `ScrollerVideo`. + +[Demo](?path=/story/components-graphics-scrollervideo--scroller-base) + +```svelte + + + + {#snippet backgroundSnippet()} + + + {/snippet} + {#snippet foregroundSnippet()} + +
+

Step 1

+
+
+

Step 2

+
+
+

Step 3

+
+ {/snippet} +
+ + +``` + +## Advanced usecases + +Using the methods attached to the bindable prop `scrollerVideo` allows for advanced customisation of the scroll video behaviour. For example, you can create a looping video that plays a specific section of the video repeatedly, or jump to a specific time in the video when the user scrolls to a certain point. + +This code below would make the video smoothly jump to the halfway point of the video. Setting `jump` to `true` will make the video jump to the specified percentage abruptly: + +```js +scrollerVideo.setVideoPercentage( + 0.5, // progress set to 50% + { + transitionSpeed: 12, // playback rate for the video + jump: false, // flag to change transition video abruptly + easing: (t) => t, // linear easing. Can also pass d3 easing functions - d3.easeLinear + } +); +``` + +> **Note**: When using these methods, it's recommended to set `trackScroll` to `false` to avoid video playback on scroll and pass functions to the `onReady` prop to ensure that the video is ready before calling any methods on it. + +Here is a demo that uses `ScrollerVideo` with `ScrollerBase` to make the video jump to the start or the end of the video depending on what step of the scroller the user is on. + +[Demo](?path=/story/components-graphics-scrollervideo--advanced) + +```svelte + + + + + {#snippet backgroundSnippet()} + + + {/snippet} + + + {#snippet foregroundSnippet()} +
+

Index {index}

+
+
+

Index {index}

+
+ {/snippet} +
+``` diff --git a/src/components/ScrollerVideo/ScrollerVideo.stories.svelte b/src/components/ScrollerVideo/ScrollerVideo.stories.svelte new file mode 100644 index 0000000..94d9a1e --- /dev/null +++ b/src/components/ScrollerVideo/ScrollerVideo.stories.svelte @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + {#if width < 600} + + {:else if width < 1200} + + {:else} + + {/if} + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/ScrollerVideo/ScrollerVideo.svelte b/src/components/ScrollerVideo/ScrollerVideo.svelte new file mode 100644 index 0000000..3c1da95 --- /dev/null +++ b/src/components/ScrollerVideo/ScrollerVideo.svelte @@ -0,0 +1,299 @@ + + + + +{#snippet supportingElements()} + {#if scrollerVideo} + {#if showDebugInfo} +
+ +
+ {/if} + + + {#if children} + {@render children()} + {/if} + {/if} +{/snippet} + +{#if embedded} +
{ + if (scrollerVideo && embeddedContainer) { + let scrollProgress = + embeddedContainer.scrollTop / embeddedContainerScrollHeight; + scrollerVideo.setVideoPercentage(scrollProgress, { + jump: scrollProgress == 0, + easing: (t) => t, + }); + } + }} + > +
+
+ {@render supportingElements()} +
+
+
+{:else} +
+
+ {@render supportingElements()} +
+
+{/if} + + diff --git a/src/components/ScrollerVideo/ScrollerVideoForeground.svelte b/src/components/ScrollerVideo/ScrollerVideoForeground.svelte new file mode 100644 index 0000000..545432f --- /dev/null +++ b/src/components/ScrollerVideo/ScrollerVideoForeground.svelte @@ -0,0 +1,166 @@ + + + + {#if componentState.generalData.currentTime >= startTime && componentState.generalData.currentTime <= endTime} +
+ + {#if text} + +
+ +
+
+ + {:else if children} +
+ {@render children()} +
+ + {:else if Foreground} +
+ + + +
+ {/if} +
+ {/if} +
+ + diff --git a/src/components/ScrollerVideo/demo/AdvancedUsecases.svelte b/src/components/ScrollerVideo/demo/AdvancedUsecases.svelte new file mode 100644 index 0000000..6404978 --- /dev/null +++ b/src/components/ScrollerVideo/demo/AdvancedUsecases.svelte @@ -0,0 +1,84 @@ + + + + + {#snippet backgroundSnippet()} + + + {/snippet} + + + {#snippet foregroundSnippet()} +
+

Index {index}

+
+
+

Index {index}

+
+ {/snippet} +
+ + diff --git a/src/components/ScrollerVideo/demo/Embedded.svelte b/src/components/ScrollerVideo/demo/Embedded.svelte new file mode 100644 index 0000000..af9b4f9 --- /dev/null +++ b/src/components/ScrollerVideo/demo/Embedded.svelte @@ -0,0 +1,100 @@ + + + + + + + + + + + {#each scrollerVideoBlock.foregrounds as foreground} + + {/each} + + + + + + + + + diff --git a/src/components/ScrollerVideo/demo/WithAi2svelteForegrounds.svelte b/src/components/ScrollerVideo/demo/WithAi2svelteForegrounds.svelte new file mode 100644 index 0000000..9b0c8b9 --- /dev/null +++ b/src/components/ScrollerVideo/demo/WithAi2svelteForegrounds.svelte @@ -0,0 +1,119 @@ + + + + +{#snippet ScrollVideo(height: string, src: string)} + + + + + + {#each scrollerVideoBlock.foregrounds as foreground} + + {/each} + +{/snippet} + +{#if width < 600} + {@render ScrollVideo(scrollerVideoBlock.height, SM)} +{:else if width < 1200} + {@render ScrollVideo(scrollerVideoBlock.height, MD)} +{:else} + {@render ScrollVideo(scrollerVideoBlock.height, LG)} +{/if} + + diff --git a/src/components/ScrollerVideo/demo/WithScrollerBase.svelte b/src/components/ScrollerVideo/demo/WithScrollerBase.svelte new file mode 100644 index 0000000..9912fa7 --- /dev/null +++ b/src/components/ScrollerVideo/demo/WithScrollerBase.svelte @@ -0,0 +1,53 @@ + + + + {#snippet backgroundSnippet()} + + {/snippet} + {#snippet foregroundSnippet()} + +
+

Step 1

+
+
+

Step 2

+
+
+

Step 3

+
+ {/snippet} +
+ + diff --git a/src/components/ScrollerVideo/demo/WithTextForegrounds.svelte b/src/components/ScrollerVideo/demo/WithTextForegrounds.svelte new file mode 100644 index 0000000..46465c7 --- /dev/null +++ b/src/components/ScrollerVideo/demo/WithTextForegrounds.svelte @@ -0,0 +1,78 @@ + + + + {#each scrollerVideoBlock.foregrounds as foreground} + + {/each} + + + diff --git a/src/components/ScrollerVideo/demo/graphic/ai2svelte/ai-chart.svelte b/src/components/ScrollerVideo/demo/graphic/ai2svelte/ai-chart.svelte new file mode 100644 index 0000000..61bd743 --- /dev/null +++ b/src/components/ScrollerVideo/demo/graphic/ai2svelte/ai-chart.svelte @@ -0,0 +1,633 @@ + + + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

Shake intensity

+
+
+

Light

+
+
+

Moderate

+
+
+

Cap-Haitien

+
+
+

Strong

+
+
+

Very strong

+
+
+

Gonaรฏves

+
+
+

Caribbean

+

Sea

+
+
+

HAITI

+
+
+

Jeremie

+
+
+

Port-au-Prince

+
+
+

Epicenter

+
+
+

Jacmel

+
+
+

Les Cayes

+
+
+

50 mi

+
+
+

Dominican

+

Republic

+
+
+

50 km

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

Shake intensity

+
+
+

Light

+
+
+

Moderate

+
+
+

Cap-Haitien

+
+
+

Strong

+
+
+

Very strong

+
+
+

Gonaรฏves

+
+
+

Caribbean

+

Sea

+
+
+

HAITI

+
+
+

Jeremie

+
+
+

Port-au-Prince

+
+
+

Epicenter

+
+
+

Dominican

+

Republic

+
+
+

Jacmel

+
+
+

Les Cayes

+
+
+

50 mi

+
+
+

50 km

+
+
+ {/if} + + {#if width && width >= 660} +
+
+
+
+

Shake intensity

+
+
+

Light

+
+
+

Moderate

+
+
+

Cap-Haitien

+
+
+

Strong

+
+
+

Very strong

+
+
+

Gonaรฏves

+
+
+

Caribbean

+

Sea

+
+
+

HAITI

+
+
+

Dominican

+

Republic

+
+
+

Jeremie

+
+
+

Epicenter

+
+
+

Port-au-Prince

+
+
+

Jacmel

+
+
+

Les Cayes

+
+
+

50 mi

+
+
+

50 km

+
+
+ {/if} +
+ + + + + diff --git a/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation1.svelte b/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation1.svelte new file mode 100644 index 0000000..e69acb7 --- /dev/null +++ b/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation1.svelte @@ -0,0 +1,453 @@ + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

Solid southwest swell

+
+
+

+ Tahitian local Vahine Fierro drops into a double overhead wave during + a recentcompetition. Timing and position are critical to make the + take-off and maximize scoring +

+

+

 

+
+
+

Shallow water hides

+

a sharp reef

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

Wave forms from hitting reef, and

+

tube will track the line of the shelf

+
+
+

Solid southwest swell

+
+
+

Tahitian local Vahine Fierro drops into

+

a double overhead wave during a recent

+

competition. Timing and position are critical

+

to make the take-off and maximize scoring

+

+

 

+
+
+

Shallow water hides

+

a sharp reef

+
+
+ {/if} + + {#if width && width >= 660 && width < 930} +
+
+
+
+

Wave forms from hitting reef, and

+

tube will track the line of the shelf

+
+
+

Solid southwest swell

+
+
+

Tahitian local Vahine Fierro drops into

+

a double overhead wave during a recent

+

competition. Timing and position are critical

+

to make the take-off and maximize scoring

+

+

 

+
+
+

Shallow water hides

+

a sharp reef

+
+
+ {/if} + + {#if width && width >= 930 && width < 1200} +
+
+
+
+

Wave forms from hitting reef, and

+

tube will track the line of the shelf

+
+
+

Solid southwest swell

+
+
+

Tahitian local Vahine Fierro drops into

+

a double overhead wave during a recent

+

competition. Timing and position are critical

+

to make the take-off and maximize scoring

+

+

 

+
+
+

Shallow water hides

+

a sharp reef

+
+
+ {/if} + + {#if width && width >= 1200} +
+
+
+
+

Wave forms from hitting reef, and

+

tube will track the line of the shelf

+
+
+

Solid southwest swell

+
+
+

Tahitian local Vahine Fierro drops into

+

a double overhead wave during a recent

+

competition. Timing and position are critical

+

to make the take-off and maximize scoring

+

+

 

+
+
+

Shallow water hides

+

+ a sharp reef +

+
+
+ {/if} +
+ + + + + + diff --git a/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation2.svelte b/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation2.svelte new file mode 100644 index 0000000..73625d5 --- /dev/null +++ b/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation2.svelte @@ -0,0 +1,423 @@ + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

The wave at Teahupo'o is

+

known to be very heavy

+

with a thick lip that can

+

easily knock a surfer off the

+

wave and onto the reef below

+
+
+

Surfer speed is up

+

to 35 km per hour

+

(20 mph)

+
+
+

One cubic meter

+

of water weighs

+

1,000 kg. (2,200 lb)

+
+
+

+ A surfer will adjust speed to stay in the tube by dragging a hand to + slow, or pumping the board to speed up +

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+ {/if} + + {#if width && width >= 660 && width < 930} +
+
+
+
+

The wave at Teahupo'o is

+

known to be very heavy

+

with a thick lip that can

+

easily knock a surfer off the

+

wave and onto the reef below

+
+
+

Surfer speed is up to

+

35 km per hour (20 mph)

+
+
+

A surfer will adjust speed to stay in

+

the tube by dragging a hand to slow,

+

or pumping the board to speed up

+
+
+

One cubic meter of water

+

weighs 1,000 kg. (2,200 lb)

+
+
+ {/if} + + {#if width && width >= 930 && width < 1200} +
+
+
+
+

The wave at Teahupo'o is

+

known to be very heavy

+

with a thick lip that can

+

easily knock a surfer off the

+

wave and onto the reef below

+
+
+

The wave at Teahupo'o is

+

known to be very heavy

+

with a thick lip that can

+

easily knock a surfer off the

+

wave and onto the reef below

+
+
+

Surfer speed is up to

+

35 km per hour (20 mph)

+
+
+

Surfer speed is up to

+

35 km per hour (20 mph)

+
+
+

A surfer will adjust speed to stay in

+

the tube by dragging a hand to slow,

+

or pumping the board to speed up

+
+
+

A surfer will adjust speed to stay in

+

the tube by dragging a hand to slow,

+

or pumping the board to speed up

+
+
+

One cubic meter of water

+

weighs 1,000 kg. (2,200 lb)

+
+
+

One cubic meter of water

+

weighs 1,000 kg. (2,200 lb)

+
+
+ {/if} + + {#if width && width >= 1200} +
+
+
+
+

The wave at Teahupo'o is

+

known to be very heavy

+

with a thick lip that can

+

easily knock a surfer off the

+

wave and onto the reef below

+
+
+

Surfer speed is up to

+

35 km per hour (20 mph)

+
+
+

A surfer will adjust speed to stay in

+

the tube by dragging a hand to slow,

+

or pumping the board to speed up

+
+
+

One cubic meter of water

+

weighs 1,000 kg. (2,200 lb)

+
+
+ {/if} +
+ + + + + + diff --git a/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation3.svelte b/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation3.svelte new file mode 100644 index 0000000..18dee42 --- /dev/null +++ b/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation3.svelte @@ -0,0 +1,431 @@ + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

+ Fierro is envelopedin the barrel for over two seconds, which is a long + time in such an unstable environment +

+
+
+

+ In comptitions, more points are scored for being deep inside a barrel + which raises the chance the wave will close out on top of them. +

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

+ Fierro is envelopedin the barrel for over two seconds, which is a long + time in such an unstable environment +

+
+
+

+ Surfers often say time distorts inside the barrel, slowing down and + that the crashing wave noise falls silent, asthey expereince a sense + of awe +

+
+
+

+ In comptitions, more points are scored for being deep inside a barrel + which raises the chance the wave will close out on top of them. +

+
+
+ {/if} + + {#if width && width >= 660 && width < 930} +
+
+
+
+

+ Fierro is envelopedin the barrel for over two seconds, which is a long + time in such an unstable environment +

+
+
+

+ Surfers often say time distorts inside the barrel, slowing down and + that the crashing wave noise falls silent, as they expereince a sense + of awe +

+
+
+

+ In comptitions, more points are scored for being deep inside a barrel + which raises the chance the wave will close out on top of them. +

+
+
+ {/if} + + {#if width && width >= 930 && width < 1200} +
+
+
+
+

+ Fierro is envelopedin the barrel for over two seconds, which is a long + time in such an unstable environment +

+
+
+

+ Surfers often say time distorts inside the barrel, slowing down and + that the crashing wave noise falls silent, as they expereince a sense + of awe +

+
+
+

+ In comptitions, more points are scored for being deep inside a barrel + which raises the chance the wave will close out on top of them. +

+
+
+ {/if} + + {#if width && width >= 1200} +
+
+
+
+

+ Fierro is envelopedin the barrel for over two seconds, which is a long + time in such an unstable environment +

+
+
+

 

+

Fierro is enveloped

+

 

+

in the barrel for over

+

 

+

2 seconds, which is a

+

 

+

long time in such an

+

 

+

unstable environment

+

 

+

Surfers often say time distorts inside

+

 

+

the barrel, slowing down and that the

+

 

+

crashing wave noise falls silent, as

+

 

+

they expereince a sense of awe

+

 

+

In comptitions, more points are

+

 

+

scored for being deep inside a

+

 

+

barrel which raises the chance

+

 

+

the wave will close out on top of them.

+
+
+

+ Surfers often say time distorts inside the barrel, slowing down and + that the crashing wave noise falls silent, as they expereince a sense + of awe +

+
+
+

+ In comptitions, more points are scored for being deep inside a barrel + which raises the chance the wave will close out on top of them. +

+
+
+ {/if} +
+ + + + + + diff --git a/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation4.svelte b/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation4.svelte new file mode 100644 index 0000000..9aba7b4 --- /dev/null +++ b/src/components/ScrollerVideo/demo/graphic/ai2svelte/annotation4.svelte @@ -0,0 +1,392 @@ + + +
+ + {#if width && width >= 0 && width < 510} +
+
+
+
+

The wave path is a short one, only about 100 yards long

+
+
+

+ Fierro exits the barrel with a score of 9.33 out of 10, as she was + deep in the tube, had good speed and went over the foam ball on her + exit +

+
+
+ {/if} + + {#if width && width >= 510 && width < 660} +
+
+
+
+

The wave path is a short one, only about 100 yards long

+
+
+

+ Fierro exits the barrel with a score of 9.33 out of 10, as she was + deep in the tube, had good speed and went over the foam ball on her + exit +

+
+
+

+ The wave heaves so quickly that as it forms, it pulls water off the + reef, creating a ride that is often below sea level - seen as the + surfer exits up and over the wave to higher water +

+
+
+ {/if} + + {#if width && width >= 660 && width < 930} +
+
+
+
+

The wave path is a short one, only about 100 yards long

+
+
+

+ Fierro exits the barrel with a score of 9.33 out of 10, as she was + deep in the tube, had good speed and went over the foam ball on her + exit +

+
+
+

+ The wave heaves so quickly that as it forms, it pulls water off the + reef, creating a ride that is often below sea level - seen as the + surfer exits up and over the wave to higher water +

+
+
+ {/if} + + {#if width && width >= 930 && width < 1200} +
+
+
+
+

The wave path is a short one,

+

only about 100 yards long

+
+
+

+ Fierro exits the barrel with a score of 9.33 out of 10, as she was + deep in the tube, had good speed and went over the foam ball on her + exit +

+
+
+

+ The wave heaves so quickly that as it forms, it pulls water off the + reef, creating a ride that is often below sea level - seen as the + surfer exits up and over the wave to higher water +

+
+
+ {/if} + + {#if width && width >= 1200} +
+
+
+
+

The wave path is a short one,

+

only about 100 yards long

+
+
+

Fierro exits the barrel with a score of

+

9.33 out of 10, as she was deep in the

+

tube, had good speed and went over

+

the foam ball on her exit

+
+
+

The wave heaves so quickly that as it forms,

+

+ it pulls water off the reef, creating a rid e that +

+

is often below sea level - seen as the surfer

+

exits up and over the wave to higher water

+
+
+ {/if} +
+ + + + + + diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/ai-chart-md.png b/src/components/ScrollerVideo/demo/graphic/imgs/ai-chart-md.png new file mode 100644 index 0000000..7f62d44 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/ai-chart-md.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/ai-chart-sm.png b/src/components/ScrollerVideo/demo/graphic/imgs/ai-chart-sm.png new file mode 100644 index 0000000..49c06f6 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/ai-chart-sm.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/ai-chart-xs.png b/src/components/ScrollerVideo/demo/graphic/imgs/ai-chart-xs.png new file mode 100644 index 0000000..15d640d Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/ai-chart-xs.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-lg.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-lg.png new file mode 100644 index 0000000..66a9255 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-lg.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-md.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-md.png new file mode 100644 index 0000000..cf5353f Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-md.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-sm.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-sm.png new file mode 100644 index 0000000..7758da8 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-sm.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-xl.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-xl.png new file mode 100644 index 0000000..35731fc Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-xl.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-xs.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-xs.png new file mode 100644 index 0000000..9621a6f Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation1-xs.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-lg.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-lg.png new file mode 100644 index 0000000..deae2d2 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-lg.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-md.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-md.png new file mode 100644 index 0000000..5e45881 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-md.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-sm.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-sm.png new file mode 100644 index 0000000..16441ea Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-sm.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-xl.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-xl.png new file mode 100644 index 0000000..dbf15ba Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-xl.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-xs.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-xs.png new file mode 100644 index 0000000..911411f Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation2-xs.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-lg.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-lg.png new file mode 100644 index 0000000..6c22553 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-lg.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-md.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-md.png new file mode 100644 index 0000000..e536624 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-md.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-sm.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-sm.png new file mode 100644 index 0000000..16441ea Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-sm.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-xl.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-xl.png new file mode 100644 index 0000000..4acb55b Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-xl.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-xs.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-xs.png new file mode 100644 index 0000000..875f692 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation3-xs.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-lg.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-lg.png new file mode 100644 index 0000000..dc52b8b Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-lg.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-md.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-md.png new file mode 100644 index 0000000..7cdf4ba Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-md.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-sm.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-sm.png new file mode 100644 index 0000000..b220b1a Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-sm.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-xl.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-xl.png new file mode 100644 index 0000000..b70a645 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-xl.png differ diff --git a/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-xs.png b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-xs.png new file mode 100644 index 0000000..fcdde81 Binary files /dev/null and b/src/components/ScrollerVideo/demo/graphic/imgs/annotation4-xs.png differ diff --git a/src/components/ScrollerVideo/ts/ScrollerVideo.ts b/src/components/ScrollerVideo/ts/ScrollerVideo.ts new file mode 100644 index 0000000..acf4ba7 --- /dev/null +++ b/src/components/ScrollerVideo/ts/ScrollerVideo.ts @@ -0,0 +1,959 @@ +import { UAParser } from 'ua-parser-js'; +import videoDecoder from './videoDecoder'; +import { debounce, isScrollPositionAtTarget, map, constrain } from './utils'; +import { createComponentState, type ScrollerVideoState } from './state.svelte'; + +interface ScrollerVideoArgs { + src: string; + scrollerVideoContainer: HTMLElement | string; + objectFit?: string; + sticky?: boolean; + full?: boolean; + trackScroll?: boolean; + lockScroll?: boolean; + transitionSpeed?: number; + frameThreshold?: number; + useWebCodecs?: boolean; + onReady?: () => void; + onChange?: (percentage?: number) => void; + debug?: boolean; + autoplay?: boolean; + setVideoPercentage?: ( + percentage: number, + options?: TransitionOptions + ) => void; + resize?: () => void; +} + +export interface TransitionOptions { + jump: boolean; + transitionSpeed?: number; + easing?: ((progress: number) => number) | null; + autoplay?: boolean; +} + +/** + * ScrollerVideo class for scroll-driven or programmatic video playback with Svelte integration. + */ +class ScrollerVideo { + /** + * The container element for the video or canvas. + * @type {HTMLElement | null} + */ + container: HTMLElement | null; + /** + * The original container argument (element or string ID). + * @type {Element | string | undefined} + */ + scrollerVideoContainer: Element | string | undefined; + /** + * Video source URL. + * @type {string} + */ + src: string; + /** + * Speed of transitions. + * @type {number} + */ + transitionSpeed: number; + /** + * Threshold for frame transitions. + * @type {number} + */ + frameThreshold: number; + /** + * Whether to use WebCodecs for decoding. + * @type {boolean} + */ + useWebCodecs: boolean; + /** + * CSS object-fit property for video/canvas. + * @type {string} + */ + objectFit: string; + /** + * Whether to use sticky positioning. + * @type {boolean} + */ + sticky: boolean; + /** + * Whether to track scroll position. + * @type {boolean} + */ + trackScroll: boolean; + /** + * Callback when ready. + * @type {() => void} + */ + onReady: () => void; + /** + * Callback on scroll percentage change. + * @type {(percentage?: number) => void} + */ + onChange: (percentage?: number) => void; + /** + * Enable debug logging. + * @type {boolean} + */ + debug: boolean; + /** + * Enable autoplay. + * @type {boolean} + */ + autoplay: boolean; + /** + * The HTML video element. + * @type {HTMLVideoElement | undefined} + */ + video: HTMLVideoElement | undefined; + /** + * Current scroll/video percentage (0-1). + * @type {number} + */ + videoPercentage: number; + /** + * True if browser is Safari. + * @type {boolean} + */ + isSafari: boolean; + /** + * Current video time in seconds. + * @type {number} + */ + currentTime: number; + /** + * Target video time in seconds. + * @type {number} + */ + targetTime: number; + /** + * Canvas for rendering frames (if using WebCodecs). + * @type {HTMLCanvasElement | null} + */ + canvas: HTMLCanvasElement | null; + /** + * 2D context for the canvas. + * @type {CanvasRenderingContext2D | null} + */ + context: CanvasRenderingContext2D | null; + /** + * Decoded video frames (if using WebCodecs). + * @type {ImageBitmap[] | null} + */ + frames: ImageBitmap[] | null; + /** + * Video frame rate. + * @type {number} + */ + frameRate: number; + /** + * Target scroll position in pixels, if set. + * @type {number | null} + */ + targetScrollPosition: number | null = null; + /** + * Current frame index (if using WebCodecs). + * @type {number} + */ + currentFrame: number; + /** + * True if using WebCodecs for decoding. + * @type {boolean} + */ + usingWebCodecs: boolean; + /** + * Total video duration in seconds. + * @type {number} + */ + totalTime: number; + /** + * RequestAnimationFrame ID for transitions. + * @type {number | null} + */ + transitioningRaf: number | null; + /** + * State object for component-level state. + * @type {ScrollerVideoState} + */ + componentState: ScrollerVideoState; + /** + * Function to update scroll percentage (set in constructor). + * @type {((jump: boolean) => void) | undefined} + */ + updateScrollPercentage: ((jump: boolean) => void) | undefined; + /** + * Function to handle resize events (set in constructor). + * @type {(() => void) | undefined} + */ + resize: (() => void) | undefined; + + /** + * Creates a new ScrollerVideo instance. + * @param {ScrollerVideoArgs} args - The arguments for initialization. + */ + constructor({ + src, + scrollerVideoContainer, + objectFit = 'cover', + sticky = true, + full = true, + trackScroll = true, + lockScroll = true, + transitionSpeed = 8, + frameThreshold = 0.1, + useWebCodecs = true, + onReady = () => {}, + onChange = (_percentage?: number) => {}, + debug = false, + autoplay = false, + }: ScrollerVideoArgs) { + this.src = src; + this.scrollerVideoContainer = scrollerVideoContainer; + this.objectFit = objectFit; + this.sticky = sticky; + this.trackScroll = trackScroll; + this.transitionSpeed = transitionSpeed; + this.frameThreshold = frameThreshold; + this.useWebCodecs = useWebCodecs; + this.onReady = onReady; + this.onChange = onChange; + this.debug = debug; + this.autoplay = autoplay; + this.videoPercentage = 0; + this.isSafari = false; + this.currentTime = 0; + this.targetTime = 0; + this.canvas = null; + this.context = null; + this.container = null; + this.frames = null; + this.frameRate = 0; + this.currentTime = 0; // Saves the currentTime of the video, synced with this.video.currentTime + this.targetTime = 0; // The target time before a transition happens + this.canvas = null; // The canvas for drawing the frames decoded by webCodecs + this.context = null; // The canvas context + this.frames = []; // The frames decoded by webCodecs + this.frameRate = 0; // Calculation of frameRate so we know which frame to paint + this.currentFrame = 0; + this.videoPercentage = 0; + this.usingWebCodecs = false; // Whether we are using webCodecs + this.totalTime = 0; // The total time of the video, used for calculating percentage + this.transitioningRaf = null; + this.componentState = createComponentState(); + this.componentState.willAutoPlay = autoplay; + + // Save the container. If the container is a string we get the element + + if (scrollerVideoContainer && scrollerVideoContainer instanceof HTMLElement) + this.container = scrollerVideoContainer; + // otherwise it should better be an element + else if (typeof scrollerVideoContainer === 'string') { + this.container = document.getElementById(scrollerVideoContainer) || null; + if (!this.container) + throw new Error('scrollerVideoContainer must be a valid DOM object'); + } else { + throw new Error('scrollerVideoContainer must be a valid DOM object'); + } + + // Create the initial video object. Even if we are going to use webcodecs, + // we start with a paused video object + + this.video = document.createElement('video'); + this.video.src = src; + this.video.preload = 'auto'; + this.video.tabIndex = 0; + this.video.preload = 'auto'; + this.video.playsInline = true; + this.video.muted = true; + this.video.pause(); + this.video.load(); + + this.video.addEventListener( + 'canplaythrough', + () => { + this.onReady(); + if (this.autoplay && !this.useWebCodecs) { + this.autoplayScroll(); + } + }, + { once: true } + ); + + // Start the video percentage at 0 + this.videoPercentage = 0; + + // Adds the video to the container + this.container.appendChild(this.video); + + // Setting CSS properties for sticky + if (sticky) { + this.container.style.display = 'block'; + this.container.style.position = 'sticky'; + this.container.style.top = '0'; + } + + // Setting CSS properties for full + if (full) { + this.container.style.width = '100%'; + this.container.style.height = '100lvh'; + this.container.style.overflow = 'hidden'; + } + + // Setting CSS properties for cover + if (objectFit) this.setCoverStyle(this.video); + + // Detect webkit (safari), because webkit requires special attention + const browserEngine = new UAParser().getEngine(); + + this.isSafari = browserEngine.name === 'WebKit'; + if (debug && this.isSafari) console.info('Safari browser detected'); + + const debouncedScroll = debounce(() => { + window.requestAnimationFrame(() => { + this.setScrollPercent(this.videoPercentage); + }); + }, 100); + + // Add scroll listener for responding to scroll position + this.updateScrollPercentage = (jump = false) => { + // Used for internally setting the scroll percentage based on built-in listeners + let containerBoundingClientRect; + if ( + this.container && + this.container.parentNode && + (this.container.parentNode as Element).getBoundingClientRect + ) { + containerBoundingClientRect = ( + this.container.parentNode as Element + ).getBoundingClientRect(); + } else { + if (this.debug) { + console.error( + 'ScrollerVideo: container or parentNode is null or invalid.' + ); + } + return; + } + + // Calculate the current scroll percent of the video + let scrollPercent = + -containerBoundingClientRect.top / + (containerBoundingClientRect.height - window.innerHeight); + + // if autplay, trim the playing time to last locked video position + if (this.componentState.autoplayProgress > 0) { + scrollPercent = map( + scrollPercent, + 0, + 1, + this.componentState.autoplayProgress, + 1 + ); + } + + if (this.debug) { + console.info('ScrollerVideo scrolled to', scrollPercent); + } + + // toggle autoplaying state on manual intervention + if (this.componentState.isAutoPlaying && this.frames) { + if (this.debug) console.warn('Stopping autoplay due to manual scroll'); + + if (this.usingWebCodecs) { + this.componentState.autoplayProgress = parseFloat( + (this.currentFrame / this.frames.length).toFixed(4) + ); + } else { + this.componentState.autoplayProgress = parseFloat( + (this.currentTime / this.totalTime).toFixed(4) + ); + } + + this.componentState.isAutoPlaying = false; + } + + this.videoPercentage = scrollPercent; + + if (this.targetScrollPosition == null) { + this.setTargetTimePercent(scrollPercent, { jump }); + this.onChange(scrollPercent); + } else if (isScrollPositionAtTarget(this.targetScrollPosition)) { + this.targetScrollPosition = null; + } else if (lockScroll && this.targetScrollPosition != null) { + debouncedScroll(); + } + + this.updateDebugInfo(); + }; + + // Add our event listeners for handling changes to the window or scroll + if (this.trackScroll) { + window.addEventListener('scroll', () => { + if (this.updateScrollPercentage) { + this.updateScrollPercentage(false); + } + }); + + // Set the initial scroll percentage + this.video.addEventListener( + 'loadedmetadata', + () => { + if (this.updateScrollPercentage) { + this.updateScrollPercentage(true); + } + if (this.video) { + this.totalTime = this.video.duration; + } + this.setCoverStyle(this.canvas || this.video); + }, + { once: true } + ); + } else { + this.video.addEventListener( + 'loadedmetadata', + () => { + this.setTargetTimePercent(0, { jump: true }); + if (this.video) { + this.totalTime = this.video.duration; + } + this.setCoverStyle(this.canvas || this.video); + }, + { once: true } + ); + } + + // Add resize function + this.resize = () => { + if (this.debug) console.info('ScrollerVideo resizing...'); + // On resize, we need to reset the cover style + if (this.objectFit) this.setCoverStyle(this.canvas || this.video); + // Then repaint the canvas, if we are in useWebcodecs + this.paintCanvasFrame(Math.floor(this.currentTime * this.frameRate)); + }; + + window.addEventListener('resize', this.resize); + this.video.addEventListener('progress', this.resize); + + // Calls decode video to attempt webcodecs method + this.decodeVideo(); + this.updateDebugInfo(); + } + + /** + * Sets the currentTime of the video as a specified percentage of its total duration. + * + * @param percentage - The percentage of the video duration to set as the current time. + * @param options - Configuration options for adjusting the video playback. + * - autoplay: boolean - If true, the video will start playing immediately after setting the percentage. Default is false. + * - jump: boolean - If true, the video currentTime will jump directly to the specified percentage. If false, the change will be animated over time. + * - transitionSpeed: number - Defines the speed of the transition when `jump` is false. Represents the duration of the transition in milliseconds. Default is 8. + * - easing: (progress: number) => number - A function that defines the easing curve for the transition. It takes the progress ratio (a number between 0 and 1) as an argument and returns the eased value, affecting the playback speed during the transition. + */ + setVideoPercentage( + percentage: number, + options: TransitionOptions = { jump: false, transitionSpeed: 8 } + ) { + // Early termination if the video percentage is already at the percentage that is intended. + if (this.videoPercentage === percentage) return; + + if (this.transitioningRaf) { + window.cancelAnimationFrame(this.transitioningRaf); + } + + this.videoPercentage = percentage; + + this.onChange(percentage); + + if (this.trackScroll && !options.autoplay) { + this.setScrollPercent(percentage); + } + + this.setTargetTimePercent(percentage, options); + } + + /** + * Sets the style of the video or canvas to "cover" its container. + * @param {HTMLElement | HTMLCanvasElement | undefined} el - The element to style. + */ + setCoverStyle(el: HTMLElement | HTMLCanvasElement | undefined): void { + if (!el) { + if (this.debug) console.warn('No element to set cover style on'); + return; + } + + if (this.objectFit) { + el.style.position = 'absolute'; + el.style.top = '50%'; + el.style.left = '50%'; + el.style.transform = 'translate(-50%, -50%)'; + // el.style.minWidth = '101%'; + // el.style.minHeight = '101%'; + + // Gets the width and height of the container + const { width: containerWidth, height: containerHeight } = + this.container?.getBoundingClientRect() || { width: 0, height: 0 }; + + let width = 0, + height = 0; + + if (el instanceof HTMLVideoElement) { + width = el.videoWidth; + height = el.videoHeight; + } else if (el instanceof HTMLCanvasElement) { + width = el.width; + height = el.height; + } + + if (this.debug) + console.info('Container dimensions:', [ + containerWidth, + containerHeight, + ]); + if (this.debug) console.info('Element dimensions:', [width, height]); + + // Determines which axis needs to be 100% and which needs to be scaled + if (this.objectFit == 'cover') { + if (containerWidth / containerHeight > width / height) { + el.style.width = '100%'; + el.style.height = 'auto'; + } else { + el.style.height = '100%'; + el.style.width = 'auto'; + } + } else if (this.objectFit == 'contain') { + if (containerWidth / containerHeight > width / height) { + el.style.height = '100%'; + el.style.width = 'auto'; + } else { + el.style.width = '100%'; + el.style.height = 'auto'; + } + } + } + } + + /** + * Uses webCodecs to decode the video into frames. + * @returns {Promise} Resolves when decoding is complete. + */ + async decodeVideo(): Promise { + if (!this.useWebCodecs) { + if (this.debug) + console.warn('Cannot perform video decode: `useWebCodes` disabled'); + + return; + } + + if (!this.src) { + if (this.debug) + console.warn('Cannot perform video decode: no `src` found'); + + return; + } + + try { + await videoDecoder( + this.src, + (frame) => { + this.frames?.push(frame); + }, + this.debug + ).then((codec) => { + this.usingWebCodecs = true; + if (typeof codec == 'string') { + this.componentState.framesData.codec = codec; + } + }); + } catch (error) { + if (this.debug) + console.error('Error encountered while decoding video', error); + + // Remove all decoded frames if a failure happens during decoding + this.frames = []; + + // Force a video reload when videoDecoder fails + this.video?.load(); + } + + // If no frames, something went wrong + if (this.frames?.length === 0) { + if (this.debug) console.error('No frames were received from webCodecs'); + + this.onReady(); + return; + } + + // Calculate the frameRate based on number of frames and the duration + this.frameRate = + this.frames && this.video ? this.frames.length / this.video.duration : 0; + if (this.debug) + console.info( + 'Received', + this.frames?.length, + 'frames. Video frame rate:', + this.frameRate + ); + + // Remove the video and add the canvas + this.canvas = document.createElement('canvas'); + this.context = this.canvas.getContext('2d'); + + // Hide the video and add the canvas to the container + if (this.video) { + this.video.style.display = 'none'; + } + if (this.container) { + this.container.appendChild(this.canvas); + } + if (this.objectFit) this.setCoverStyle(this.canvas); + + // Paint our first frame + this.paintCanvasFrame(Math.floor(this.currentTime * this.frameRate)); + this.onReady(); + + if (this.autoplay) this.autoplayScroll(); + } + + /** + * Paints the frame to the canvas. + * @param {number} frameNum - The frame index to paint. + */ + paintCanvasFrame(frameNum: number): void { + if (!this.frames) { + if (this.debug) console.warn('No frames available to paint'); + return; + } + + // Get the frame and paint it to the canvas + const currFrame = this.frames[frameNum]; + this.currentFrame = frameNum; + + if (!this.canvas || !currFrame) { + return; + } + + if (this.debug) { + console.info('Painting frame', frameNum); + } + + // Make sure the canvas is scaled properly, similar to setCoverStyle + this.canvas.width = currFrame.width; + this.canvas.height = currFrame.height; + const { width, height } = this.container?.getBoundingClientRect() || { + width: 0, + height: 0, + }; + + if (this.objectFit == 'cover') { + if (width / height > currFrame.width / currFrame.height) { + this.canvas.style.width = '100%'; + this.canvas.style.height = 'auto'; + } else { + this.canvas.style.height = '100%'; + this.canvas.style.width = 'auto'; + } + } else if (this.objectFit == 'contain') { + if (width / height > currFrame.width / currFrame.height) { + this.canvas.style.height = '100%'; + this.canvas.style.width = 'auto'; + } else { + this.canvas.style.width = '100%'; + this.canvas.style.height = 'auto'; + } + } + + // Draw the frame to the canvas context + if (!this.context) { + if (this.debug) console.warn('No canvas context available to paint'); + return; + } + + this.context.drawImage(currFrame, 0, 0, currFrame.width, currFrame.height); + this.updateDebugInfo(); + } + + /** + * Transitions the video or the canvas to the proper frame. + * + * @param options - Configuration options for adjusting the video playback. + * - jump: boolean - If true, the video currentTime will jump directly to the specified percentage. If false, the change will be animated over time. + * - transitionSpeed: number - Defines the speed of the transition when `jump` is false. Represents the duration of the transition in milliseconds. Default is 8. + * - easing: (progress: number) => number - A function that defines the easing curve for the transition. It takes the progress ratio (a number between 0 and 1) as an argument and returns the eased value, affecting the playback speed during the transition. + */ + transitionToTargetTime({ + jump, + transitionSpeed = this.transitionSpeed, + easing = null, + }: TransitionOptions) { + if (!this.video) { + console.warn('No video found'); + return; + } + + if (this.debug) { + console.info( + 'Transitioning targetTime:', + this.targetTime, + 'currentTime:', + this.currentTime + ); + } + + const diff = this.targetTime - this.currentTime; + const distance = Math.abs(diff); + const duration = distance * 1000; + const isForwardTransition = diff > 0; + + const tick = ({ + startCurrentTime, + startTimestamp, + timestamp, + }: { + startCurrentTime: number; + startTimestamp: number; + timestamp: number; + }) => { + if (!this.video) { + console.warn('No video found during transition tick'); + return; + } + + const progress = (timestamp - startTimestamp) / duration; + + // if frameThreshold is too low to catch condition Math.abs(this.targetTime - this.currentTime) < this.frameThreshold + const hasPassedThreshold = + isForwardTransition ? + this.currentTime >= this.targetTime + : this.currentTime <= this.targetTime; + + if (this.componentState.isAutoPlaying) { + this.componentState.autoplayProgress = parseFloat( + (this.currentTime / this.totalTime).toFixed(4) + ); + } + + // If we are already close enough to our target, pause the video and return. + // This is the base case of the recursive function + if ( + isNaN(this.targetTime) || + // If the currentTime is already close enough to the targetTime + Math.abs(this.targetTime - this.currentTime) < this.frameThreshold || + hasPassedThreshold + ) { + this.video?.pause(); + + if (this.transitioningRaf) { + cancelAnimationFrame(this.transitioningRaf); + this.transitioningRaf = null; + } + + return; + } + + // Make sure we don't go out of time bounds + if (this.targetTime > this.video.duration) + this.targetTime = this.video.duration; + if (this.targetTime < 0) this.targetTime = 0; + + // How far forward we need to transition + const transitionForward = this.targetTime - this.currentTime; + const easedProgress = + easing && Number.isFinite(progress) ? easing(progress) : 0; + const easedCurrentTime = + isForwardTransition ? + startCurrentTime + + easedProgress * Math.abs(distance) * transitionSpeed + : startCurrentTime - + easedProgress * Math.abs(distance) * transitionSpeed; + + if (this.canvas) { + if (jump) { + // If jump, we go directly to the frame + this.currentTime = this.targetTime; + } else if (easedProgress) { + this.currentTime = easedCurrentTime; + } else { + this.currentTime += transitionForward / (256 / transitionSpeed); + } + + this.paintCanvasFrame(Math.floor(this.currentTime * this.frameRate)); + } else if (jump || this.isSafari || !isForwardTransition) { + // We can't use a negative playbackRate, so if the video needs to go backwards, + // We have to use the inefficient method of modifying currentTime rapidly to + // get an effect. + this.video.pause(); + + if (easedProgress) { + this.currentTime = easedCurrentTime; + } else { + this.currentTime += transitionForward / (64 / transitionSpeed); + } + + // If jump, we go directly to the frame + if (jump) { + this.currentTime = this.targetTime; + } + + this.video.currentTime = this.currentTime; + } else { + // Otherwise, we play the video and adjust the playbackRate to get a smoother + // animation effect. + const playbackRate = Math.max( + Math.min(transitionForward * 4, transitionSpeed, 16), + 1 + ); + if (this.debug) + console.info('ScrollerVideo playbackRate:', playbackRate); + + if (!isNaN(playbackRate)) { + this.video.playbackRate = playbackRate; + this.video.play(); + } + // Set the currentTime to the video's currentTime + this.currentTime = this.video.currentTime; + } + + // Recursively calls ourselves until the animation is done. + if (typeof requestAnimationFrame === 'function') { + this.transitioningRaf = requestAnimationFrame((currentTimestamp) => + tick({ + startCurrentTime, + startTimestamp, + timestamp: currentTimestamp, + }) + ); + } + }; + + if (typeof requestAnimationFrame === 'function') { + this.transitioningRaf = requestAnimationFrame((startTimestamp) => { + tick({ + startCurrentTime: this.currentTime, + startTimestamp, + timestamp: startTimestamp, + }); + }); + } + } + + /** + * Sets the currentTime of the video as a specified percentage of its total duration. + * + * @param percentage - The percentage of the video duration to set as the current time. + * @param options - Configuration options for adjusting the video playback. + * - jump: boolean - If true, the video currentTime will jump directly to the specified percentage. If false, the change will be animated over time. + * - transitionSpeed: number - Defines the speed of the transition when `jump` is false. Represents the duration of the transition in milliseconds. Default is 8. + * - easing: (progress: number) => number - A function that defines the easing curve for the transition. It takes the progress ratio (a number between 0 and 1) as an argument and returns the eased value, affecting the playback speed during the transition. + */ + setTargetTimePercent( + percentage: number, + options: TransitionOptions = { jump: false, transitionSpeed: 8 } + ) { + const targetDuration = + this.frames?.length && this.frameRate ? + this.frames.length / this.frameRate + : this.video?.duration || 0; + // The time we want to transition to + this.targetTime = Math.max(Math.min(percentage, 1), 0) * targetDuration; + + // If we are close enough, return early + if ( + !options.jump && + Math.abs(this.currentTime - this.targetTime) < this.frameThreshold + ) + return; + + // Play the video if we are in video mode + if (!this.canvas && !this.video?.paused) this.video?.play(); + + this.transitionToTargetTime(options); + } + + /** + * Simulate trackScroll programmatically (scrolls on page by percentage of video). + * @param {number} percentage - The percentage of the video to scroll to. + */ + setScrollPercent(percentage: number) { + if (!this.trackScroll) { + console.warn('`setScrollPercent` requires enabled `trackScroll`'); + return; + } + + const parent = this.container?.parentNode; + let top = 0, + height = 0; + + if (parent && parent instanceof Element) { + const rect = parent.getBoundingClientRect(); + top = rect.top; + height = rect.height; + } + + const startPoint = top + window.pageYOffset; + + const containerHeightInViewport = height - window.innerHeight; + const targetPosition = startPoint + containerHeightInViewport * percentage; + + if (isScrollPositionAtTarget(targetPosition)) { + this.targetScrollPosition = null; + } else { + window.scrollTo({ top: targetPosition, behavior: 'smooth' }); + this.targetScrollPosition = targetPosition; + } + } + + /** + * Call to destroy this ScrollerVideo object. + */ + destroy() { + if (this.debug) console.info('Destroying ScrollerVideo'); + + if (this.trackScroll && this.updateScrollPercentage) + window.removeEventListener('scroll', () => this.updateScrollPercentage); + + if (this.resize) { + window.removeEventListener('resize', this.resize); + } + + // Clear component + if (this.container) this.container.innerHTML = ''; + } + + /** + * Autoplay the video by scrolling to the end. + */ + autoplayScroll() { + this.setVideoPercentage(1, { + jump: false, + transitionSpeed: this.totalTime * 0.1, + easing: (i) => i, + autoplay: true, + }); + this.componentState.isAutoPlaying = true; + } + + /** + * Updates debug information in the component state. + */ + updateDebugInfo() { + this.componentState.generalData.src = this.src; + this.componentState.generalData.videoPercentage = constrain( + parseFloat(this.videoPercentage.toFixed(4)), + 0, + 1 + ); + this.componentState.generalData.frameRate = parseFloat( + this.frameRate.toFixed(2) + ); + this.componentState.generalData.currentTime = parseFloat( + this.currentTime.toFixed(4) + ); + this.componentState.generalData.totalTime = parseFloat( + this.totalTime.toFixed(4) + ); + this.componentState.usingWebCodecs = this.usingWebCodecs; + this.componentState.framesData.currentFrame = this.currentFrame; + this.componentState.framesData.totalFrames = this.frames?.length || 0; + } +} +export default ScrollerVideo; diff --git a/src/components/ScrollerVideo/ts/mp4box.d.ts b/src/components/ScrollerVideo/ts/mp4box.d.ts new file mode 100644 index 0000000..d5d9ed9 --- /dev/null +++ b/src/components/ScrollerVideo/ts/mp4box.d.ts @@ -0,0 +1,137 @@ +declare module 'mp4box' { + export interface MP4MediaTrack { + id: number; + created: Date; + modified: Date; + movie_duration: number; + movie_timescale: number; + layer: number; + alternate_group: number; + volume: number; + track_width: number; + track_height: number; + timescale: number; + duration: number; + bitrate: number; + codec: string; + language: string; + nb_samples: number; + } + + export interface MP4VideoData { + width: number; + height: number; + } + + export interface MP4VideoTrack extends MP4MediaTrack { + video: MP4VideoData; + } + + export interface MP4AudioData { + sample_rate: number; + channel_count: number; + sample_size: number; + } + + export interface MP4AudioTrack extends MP4MediaTrack { + audio: MP4AudioData; + } + + export type MP4Track = MP4VideoTrack | MP4AudioTrack; + + export interface MP4Info { + duration: number; + timescale: number; + fragment_duration: number; + isFragmented: boolean; + isProgressive: boolean; + hasIOD: boolean; + brands: string[]; + created: Date; + modified: Date; + tracks: MP4Track[]; + audioTracks: MP4AudioTrack[]; + videoTracks: MP4VideoTrack[]; + } + + export interface MP4Sample { + alreadyRead: number; + chunk_index: number; + chunk_run_index: number; + cts: number; + data: Uint8Array; + degradation_priority: number; + depends_on: number; + description: unknown; + description_index: number; + dts: number; + duration: number; + has_redundancy: number; + is_depended_on: number; + is_leading: number; + is_sync: boolean; + number: number; + offset: number; + size: number; + timescale: number; + track_id: number; + } + + export type MP4ArrayBuffer = ArrayBuffer & { fileStart: number }; + + export class DataStream { + static BIG_ENDIAN: boolean; + static LITTLE_ENDIAN: boolean; + buffer: ArrayBuffer; + constructor( + arrayBuffer?: ArrayBuffer, + byteOffset: number, + endianness: boolean + ): void; + // TODO: Complete interface + } + + export interface Trak { + mdia?: { + minf?: { + stbl?: { + stsd?: { + entries: { + avcC?: { + write: (stream: DataStream) => void; + }; + hvcC?: { + write: (stream: DataStream) => void; + }; + }[]; + }; + }; + }; + }; + // TODO: Complete interface + } + + export interface MP4File { + [x: string]: unknown; + onMoovStart?: () => void; + onReady?: (info: MP4Info) => void; + onError?: (e: string) => void; + onSamples?: (id: number, user: unknown, samples: MP4Sample[]) => unknown; + + appendBuffer(data: MP4ArrayBuffer): number; + start(): void; + stop(): void; + flush(): void; + releaseUsedSamples(trackId: number, sampleNumber: number): void; + setExtractionOptions( + trackId: number, + user?: unknown, + options?: { nbSamples?: number; rapAlignment?: number } + ): void; + getTrackById(trackId: number): Trak; + } + + export function createFile(): MP4File; + + export {}; +} diff --git a/src/components/ScrollerVideo/ts/state.svelte.ts b/src/components/ScrollerVideo/ts/state.svelte.ts new file mode 100644 index 0000000..e873790 --- /dev/null +++ b/src/components/ScrollerVideo/ts/state.svelte.ts @@ -0,0 +1,74 @@ +/** + * General video data for ScrollerVideo state. + * @typedef {Object} GeneralData + * @property {string} src - Video source URL. + * @property {number} videoPercentage - Current video percentage (0-1). + * @property {number} frameRate - Video frame rate. + * @property {number} currentTime - Current video time in seconds. + * @property {number} totalTime - Total video duration in seconds. + */ +type GeneralData = { + src: string; + videoPercentage: number; + frameRate: number; + currentTime: number; + totalTime: number; +}; + +/** + * Frame-level data for ScrollerVideo state. + * @typedef {Object} FramesData + * @property {string} codec - Video codec string. + * @property {number} currentFrame - Current frame index. + * @property {number} totalFrames - Total number of frames. + */ +type FramesData = { + codec: string; + currentFrame: number; + totalFrames: number; +}; + +/** + * State object for ScrollerVideo component. + * @typedef {Object} ScrollerVideoState + * @property {GeneralData} generalData - General video data. + * @property {boolean} usingWebCodecs - Whether WebCodecs is used. + * @property {FramesData} framesData - Frame-level data. + * @property {boolean} isAutoPlaying - Whether video is autoplaying. + * @property {number} autoplayProgress - Progress of autoplay (0-1). + */ +export type ScrollerVideoState = { + generalData: GeneralData; + usingWebCodecs: boolean; + framesData: FramesData; + willAutoPlay: boolean; + isAutoPlaying: boolean; + autoplayProgress: number; +}; + +/** + * Creates a new ScrollerVideoState object with default values. + * @returns {ScrollerVideoState} The initialized state object. + */ +export function createComponentState(): ScrollerVideoState { + const scrollerVideoState = $state({ + generalData: { + src: '', + videoPercentage: 0, + frameRate: 0, + currentTime: 0, + totalTime: 0, + }, + usingWebCodecs: false, + framesData: { + codec: '', + currentFrame: 0, + totalFrames: 0, + }, + willAutoPlay: false, + isAutoPlaying: false, + autoplayProgress: 0, + }); + + return scrollerVideoState; +} diff --git a/src/components/ScrollerVideo/ts/utils.ts b/src/components/ScrollerVideo/ts/utils.ts new file mode 100644 index 0000000..079415f --- /dev/null +++ b/src/components/ScrollerVideo/ts/utils.ts @@ -0,0 +1,146 @@ +import type { ScrollerVideoState } from './state.svelte'; + +/** + * Flattened version of ScrollerVideoState for easier access to all properties. + * @typedef {Object} FlattenedScrollerVideoState + * @property {string} src - Video source URL. + * @property {number} videoPercentage - Current video percentage (0-1). + * @property {number} frameRate - Video frame rate. + * @property {number} currentTime - Current video time in seconds. + * @property {number} totalTime - Total video duration in seconds. + * @property {boolean} usingWebCodecs - Whether WebCodecs is used. + * @property {string} codec - Video codec string. + * @property {number} currentFrame - Current frame index. + * @property {number} totalFrames - Total number of frames. + * @property {boolean} isAutoPlaying - Whether video is autoplaying. + * @property {number} autoplayProgress - Progress of autoplay (0-1). + */ +type FlattenedScrollerVideoState = { + src: string; + videoPercentage: number; + frameRate: number; + currentTime: number; + totalTime: number; + usingWebCodecs: boolean; + codec: string; + currentFrame: number; + totalFrames: number; + isAutoPlaying: boolean; + autoplayProgress: number; +}; + +/** + * Returns a debounced version of the given function. + * @template T + * @param {T} func - The function to debounce. + * @param {number} [delay=0] - The debounce delay in milliseconds. + * @returns {(...args: Parameters) => void} The debounced function. + */ +export function debounce void>( + func: T, + delay = 0 +) { + let timeoutId: ReturnType | undefined; + + return (...args: Parameters) => { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => { + func(...args); + }, delay); + }; +} + +/** + * Checks if the current scroll position is at the target position within a threshold. + * @param {number} targetScrollPosition - The target scroll position in pixels. + * @param {number} [threshold=1] - The allowed threshold in pixels. + * @returns {boolean} True if the current scroll position is within the threshold of the target. + */ +export const isScrollPositionAtTarget = ( + targetScrollPosition: number, + threshold: number = 1 +) => { + const currentScrollPosition = window.pageYOffset; + const difference = Math.abs(currentScrollPosition - targetScrollPosition); + + return difference < threshold; +}; + +/** + * Constrains a number between a lower and upper bound. + * @param {number} n - The number to constrain. + * @param {number} low - The lower bound. + * @param {number} high - The upper bound. + * @returns {number} The constrained value. + */ +export function constrain(n: number, low: number, high: number): number { + return Math.max(Math.min(n, high), low); +} + +/** + * Maps a number from one range to another. + * @param {number} n - The number to map. + * @param {number} start1 - Lower bound of the value's current range. + * @param {number} stop1 - Upper bound of the value's current range. + * @param {number} start2 - Lower bound of the value's target range. + * @param {number} stop2 - Upper bound of the value's target range. + * @param {boolean} [withinBounds=true] - Whether to constrain the result within the target range. + * @returns {number} The mapped value. + */ +export function map( + n: number, + start1: number, + stop1: number, + start2: number, + stop2: number, + withinBounds: boolean = true +): number { + const newval = ((n - start1) / (stop1 - start1)) * (stop2 - start2) + start2; + if (!withinBounds) { + return newval; + } + if (start2 < stop2) { + return constrain(newval, start2, stop2); + } else { + return constrain(newval, stop2, start2); + } +} + +/** + * Flattens a ScrollerVideoState object into a single-level object for easier access. + * @param {ScrollerVideoState} obj - The state object to flatten. + * @returns {FlattenedScrollerVideoState} The flattened state object. + */ +export function flattenObject( + obj: ScrollerVideoState +): FlattenedScrollerVideoState { + const result: { [key: string]: unknown } = {}; + + function flatten(current: string | unknown[] | object, property: string) { + if (Object(current) !== current) { + result[property] = current; + } else if (Array.isArray(current)) { + for (let i = 0, l = current.length; i < l; i++) { + flatten(current[i], property + '[' + i + ']'); + if (l === 0) { + result[property] = []; + } + } + } else if (typeof current === 'object') { + let isEmpty = true; + for (const p in current) { + isEmpty = false; + flatten( + (current as { [key: string]: string | object | unknown[] })[p], + p + ); + } + if (isEmpty && property) { + result[property] = {}; + } + } + } + + flatten(obj, ''); + return result as FlattenedScrollerVideoState; +} diff --git a/src/components/ScrollerVideo/ts/videoDecoder.ts b/src/components/ScrollerVideo/ts/videoDecoder.ts new file mode 100644 index 0000000..d9758d4 --- /dev/null +++ b/src/components/ScrollerVideo/ts/videoDecoder.ts @@ -0,0 +1,299 @@ +import { createFile } from 'mp4box'; + +interface MP4BoxBuffer extends ArrayBuffer { + fileStart: number; +} + +/** + * Taken from https://github.com/w3c/webcodecs/blob/main/samples/mp4-decode/mp4_demuxer.js + */ +class Writer { + data: Uint8Array; + idx: number; + size: number; + + constructor(size: number) { + this.data = new Uint8Array(size); + this.idx = 0; + this.size = size; + } + + getData(): Uint8Array { + if (this.idx !== this.size) + throw new Error('Mismatch between size reserved and sized used'); + return this.data.slice(0, this.idx); + } + + writeUint8(value: number): void { + this.data.set([value], this.idx); + this.idx += 1; + } + + writeUint16(value: number): void { + const arr = new Uint16Array(1); + arr[0] = value; + const buffer = new Uint8Array(arr.buffer); + this.data.set([buffer[1], buffer[0]], this.idx); + this.idx += 2; + } + + writeUint8Array(value: number[]): void { + this.data.set(value, this.idx); + this.idx += value.length; + } +} + +/** + * Taken from https://github.com/w3c/webcodecs/blob/main/samples/mp4-decode/mp4_demuxer.js + * + * @param avccBox + * @returns {*} + */ +interface NALUnit { + length: number; + nalu: number[]; +} + +const getExtradata = (avccBox: { + SPS: NALUnit[]; + PPS: NALUnit[]; + configurationVersion: number; + AVCProfileIndication: number; + profile_compatibility: number; + AVCLevelIndication: number; + lengthSizeMinusOne: number; + nb_SPS_nalus: number; + nb_PPS_nalus: number; +}) => { + let i; + let size = 7; + for (i = 0; i < avccBox.SPS.length; i += 1) { + // nalu length is encoded as a uint16. + size += 2 + (avccBox.SPS[i] as { length: number }).length; + } + for (i = 0; i < avccBox.PPS.length; i += 1) { + // nalu length is encoded as a uint16. + size += 2 + (avccBox.PPS[i] as { length: number }).length; + } + + const writer = new Writer(size); + + writer.writeUint8(avccBox.configurationVersion); + writer.writeUint8(avccBox.AVCProfileIndication); + writer.writeUint8(avccBox.profile_compatibility); + writer.writeUint8(avccBox.AVCLevelIndication); + + writer.writeUint8(avccBox.lengthSizeMinusOne + (63 << 2)); + + writer.writeUint8(avccBox.nb_SPS_nalus + (7 << 5)); + for (i = 0; i < avccBox.SPS.length; i += 1) { + writer.writeUint16(avccBox.SPS[i].length); + writer.writeUint8Array(avccBox.SPS[i].nalu); + } + + writer.writeUint8(avccBox.nb_PPS_nalus); + for (i = 0; i < avccBox.PPS.length; i += 1) { + writer.writeUint16(avccBox.PPS[i].length); + writer.writeUint8Array(avccBox.PPS[i].nalu); + } + + return writer.getData(); +}; + +/** + * decodeVideo takes an url to a mp4 file and converts it into frames. + * + * The steps for this are: + * 1. Determine the codec for this video file and demux it into chunks. + * 2. Read the chunks with VideoDecoder as fast as possible. + * 3. Return an array of frames that we can efficiently draw to a canvas. + * + * @param src + * @param VideoDecoder + * @param EncodedVideoChunk + * @param emitFrame + * @param debug + * @returns {Promise} + */ +const decodeVideo = ( + src: string, + emitFrame: (frame: ImageBitmap) => void, + { + VideoDecoder, + EncodedVideoChunk, + debug, + }: { + VideoDecoder: typeof window.VideoDecoder; + EncodedVideoChunk: typeof window.EncodedVideoChunk; + debug: boolean; + } +): Promise => + new Promise((resolve, reject) => { + if (debug) console.info('Decoding video from', src); + + try { + // Uses mp4box for demuxing + const mp4boxfile = createFile(); + + // Holds the codec value + let codec = 'N/A'; + + // Creates a VideoDecoder instance + const decoder = new VideoDecoder({ + output: (frame) => { + createImageBitmap(frame, { resizeQuality: 'high' }).then((bitmap) => { + emitFrame(bitmap); + frame.close(); + + if (decoder.decodeQueueSize <= 0) { + // Give it an extra half second to finish everything + setTimeout(() => { + if (decoder.state !== 'closed') { + decoder.close(); + resolve(codec); + } + }, 500); + } + }); + }, + error: (e) => { + console.error(e); + reject(e); + }, + }); + + mp4boxfile.onReady = (info) => { + if (info && info.videoTracks && info.videoTracks[0]) { + [{ codec }] = info.videoTracks; + if (debug) console.info('Video with codec:', codec); + + // Define a type for moov to avoid using 'any' + interface AvcCBox { + SPS: NALUnit[]; + PPS: NALUnit[]; + configurationVersion: number; + AVCProfileIndication: number; + profile_compatibility: number; + AVCLevelIndication: number; + lengthSizeMinusOne: number; + nb_SPS_nalus: number; + nb_PPS_nalus: number; + } + interface StsdEntry { + avcC: AvcCBox; + } + interface Stsd { + entries: StsdEntry[]; + } + interface Stbl { + stsd: Stsd; + } + interface Minf { + stbl: Stbl; + } + interface Mdia { + minf: Minf; + } + interface Trak { + mdia: Mdia; + } + interface Moov { + traks: Trak[]; + } + + // Gets the avccbox used for reading extradata + const moov = mp4boxfile.moov as Moov | undefined; + const avccBox = moov?.traks[0].mdia.minf.stbl.stsd.entries[0].avcC; + if (!avccBox) { + reject(new Error('Could not find avcC box for extradata.')); + return; + } + const extradata = getExtradata(avccBox); + + // configure decoder + decoder.configure({ codec, description: extradata }); + + // Setup mp4box file for breaking it into chunks + mp4boxfile.setExtractionOptions(info.videoTracks[0].id); + mp4boxfile.start(); + } else reject(new Error('URL provided is not a valid mp4 video file.')); + }; + + mp4boxfile.onSamples = (_track_id, _ref, samples) => { + for (let i = 0; i < samples.length; i += 1) { + const sample = samples[i]; + const type = sample.is_sync ? 'key' : 'delta'; + + const chunk = new EncodedVideoChunk({ + type, + timestamp: sample.cts, + duration: sample.duration, + data: sample.data, + }); + + decoder.decode(chunk); + } + }; + + // Fetches the file into arraybuffers + fetch(src).then((res) => { + if (!res.body) throw new Error('Response body is null'); + const reader = res.body.getReader(); + let offset = 0; + + function appendBuffers( + result: ReadableStreamReadResult + ): Promise { + if (result.done) { + mp4boxfile.flush(); + return Promise.resolve(); + } + + const buf = result.value.buffer as MP4BoxBuffer; + buf.fileStart = offset; + offset += buf.byteLength; + mp4boxfile.appendBuffer(buf); + + return reader.read().then(appendBuffers); + } + + return reader.read().then(appendBuffers); + }); + } catch (e) { + reject(e); + } + }); + +/** + * The main function for decoding video. Deals with the polyfill cases first, + * then calls our decodeVideo. + * + * @param src + * @param emitFrame + * @param debug + * @returns {Promise|Promise} + */ +export default ( + src: string, + emitFrame: (frame: ImageBitmap) => void, + debug: boolean = false +) => { + // If our browser supports WebCodecs natively + if ( + typeof VideoDecoder === 'function' && + typeof EncodedVideoChunk === 'function' + ) { + if (debug) + console.info('WebCodecs is natively supported, using native version...'); + + return decodeVideo(src, emitFrame, { + VideoDecoder, + EncodedVideoChunk, + debug, + }); + } + + // Otherwise, resolve nothing + if (debug) console.info('WebCodecs is not available in this browser.'); + return Promise.resolve('N/A'); +}; diff --git a/src/components/ScrollerVideo/videos/HPO.mp4 b/src/components/ScrollerVideo/videos/HPO.mp4 new file mode 100644 index 0000000..7da0cb5 Binary files /dev/null and b/src/components/ScrollerVideo/videos/HPO.mp4 differ diff --git a/src/components/ScrollerVideo/videos/drone.mp4 b/src/components/ScrollerVideo/videos/drone.mp4 new file mode 100644 index 0000000..b5fdf74 Binary files /dev/null and b/src/components/ScrollerVideo/videos/drone.mp4 differ diff --git a/src/components/ScrollerVideo/videos/goldengate.mp4 b/src/components/ScrollerVideo/videos/goldengate.mp4 new file mode 100644 index 0000000..70c266b Binary files /dev/null and b/src/components/ScrollerVideo/videos/goldengate.mp4 differ diff --git a/src/components/ScrollerVideo/videos/tennis.mp4 b/src/components/ScrollerVideo/videos/tennis.mp4 new file mode 100644 index 0000000..688cb4e Binary files /dev/null and b/src/components/ScrollerVideo/videos/tennis.mp4 differ diff --git a/src/components/ScrollerVideo/videos/waves_lg.mp4 b/src/components/ScrollerVideo/videos/waves_lg.mp4 new file mode 100644 index 0000000..cbcaa0a Binary files /dev/null and b/src/components/ScrollerVideo/videos/waves_lg.mp4 differ diff --git a/src/components/ScrollerVideo/videos/waves_md.mp4 b/src/components/ScrollerVideo/videos/waves_md.mp4 new file mode 100644 index 0000000..08f6b44 Binary files /dev/null and b/src/components/ScrollerVideo/videos/waves_md.mp4 differ diff --git a/src/components/ScrollerVideo/videos/waves_sm.mp4 b/src/components/ScrollerVideo/videos/waves_sm.mp4 new file mode 100755 index 0000000..59b5539 Binary files /dev/null and b/src/components/ScrollerVideo/videos/waves_sm.mp4 differ diff --git a/src/components/SearchInput/SearchInput.mdx b/src/components/SearchInput/SearchInput.mdx new file mode 100644 index 0000000..6c347cd --- /dev/null +++ b/src/components/SearchInput/SearchInput.mdx @@ -0,0 +1,29 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as SearchInputStories from './SearchInput.stories.svelte'; + + + +# SearchInput + +The `SearchInput` component creates a search bar. + +```svelte + + + +``` + + diff --git a/src/components/SearchInput/SearchInput.stories.svelte b/src/components/SearchInput/SearchInput.stories.svelte new file mode 100644 index 0000000..ae596d5 --- /dev/null +++ b/src/components/SearchInput/SearchInput.stories.svelte @@ -0,0 +1,24 @@ + + + + + + + diff --git a/src/components/SearchInput/SearchInput.svelte b/src/components/SearchInput/SearchInput.svelte new file mode 100644 index 0000000..831f2c3 --- /dev/null +++ b/src/components/SearchInput/SearchInput.svelte @@ -0,0 +1,85 @@ + + + + + + diff --git a/src/components/SearchInput/components/MagnifyingGlass.svelte b/src/components/SearchInput/components/MagnifyingGlass.svelte new file mode 100644 index 0000000..b095408 --- /dev/null +++ b/src/components/SearchInput/components/MagnifyingGlass.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/src/components/SearchInput/components/X.svelte b/src/components/SearchInput/components/X.svelte new file mode 100644 index 0000000..d495bba --- /dev/null +++ b/src/components/SearchInput/components/X.svelte @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/src/components/SimpleTimeline/SimpleTimeline.mdx b/src/components/SimpleTimeline/SimpleTimeline.mdx new file mode 100644 index 0000000..7eb4c72 --- /dev/null +++ b/src/components/SimpleTimeline/SimpleTimeline.mdx @@ -0,0 +1,121 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as SimpleTimelineStories from './SimpleTimeline.stories.svelte'; + + + +# SimpleTimeline + +The `SimpleTimeline` component creates a basic timeline with dates, titles and descriptions of events. + +```svelte + + + +``` + + + +## Using with ArchieML docs + +With the graphics kit, you'll likely get your text value from an ArchieML doc. + +```yaml +# Archie ML doc + +type: timeline +# Optional +class: timeline +id: timeline-1 +symbolColour: var(--theme-colour-brand-rules, grey) +dateColour: var(--theme-colour-accent, red) +[.dates] + # date object with events + date: May 10 + [.events] + title: U.S. House passes $40 bln bill to bolster Ukraine against Russian invasion + context: The U.S. House of Representatives approved more than $40 billion more aid for Ukraine on Tuesday, as Congress races to keep military aid flowing and boost the government in Kyiv as it grapples with the Russian invasion. + titleLink: https://www.reuters.com/world/us-house-vote-40-billion-ukraine-aid-package-tuesday-pelosi-2022-05-10/ + [] + +# More dates and events... +[] +``` + +... which you'll pass to the `SimpleTimeline` component. + +```svelte + + + + +``` + + + +# Multiple events + +You can add multiple events to a single date by adding objects to the `events` array. + +```svelte + + + +``` + + diff --git a/src/components/SimpleTimeline/SimpleTimeline.stories.svelte b/src/components/SimpleTimeline/SimpleTimeline.stories.svelte new file mode 100644 index 0000000..bcf8d85 --- /dev/null +++ b/src/components/SimpleTimeline/SimpleTimeline.stories.svelte @@ -0,0 +1,95 @@ + + + + + + + diff --git a/src/components/SimpleTimeline/SimpleTimeline.svelte b/src/components/SimpleTimeline/SimpleTimeline.svelte new file mode 100644 index 0000000..0a13767 --- /dev/null +++ b/src/components/SimpleTimeline/SimpleTimeline.svelte @@ -0,0 +1,135 @@ + + + + +
+ {#each dates as date} +
+ + + +
+ {date.date} +
+ {#each date.events as event} +
+ {#if event.titleLink} + +
+ {event.title} + +
+
+ {:else} +
+ {event.title} +
+ {/if} + {#if event.context} + + {/if} +
+ {/each} +
+ {/each} +
+
+ + diff --git a/src/components/SiteFooter/CompanyLinks.svelte b/src/components/SiteFooter/CompanyLinks.svelte new file mode 100644 index 0000000..4ed6b01 --- /dev/null +++ b/src/components/SiteFooter/CompanyLinks.svelte @@ -0,0 +1,177 @@ + + +{#if links.social_links} +
+
+
+

Information you can trust

+

{links.company_description}

+
+ +
+
+{/if} + + diff --git a/src/components/SiteFooter/LegalLinks.svelte b/src/components/SiteFooter/LegalLinks.svelte new file mode 100644 index 0000000..c4e950f --- /dev/null +++ b/src/components/SiteFooter/LegalLinks.svelte @@ -0,0 +1,181 @@ + + +{#if links.ad_links} + +{/if} + + diff --git a/src/components/SiteFooter/QuickLinks.svelte b/src/components/SiteFooter/QuickLinks.svelte new file mode 100644 index 0000000..f17363b --- /dev/null +++ b/src/components/SiteFooter/QuickLinks.svelte @@ -0,0 +1,265 @@ + + + + +{#if links.latest_links} + +{/if} + + diff --git a/src/components/SiteFooter/SiteFooter.mdx b/src/components/SiteFooter/SiteFooter.mdx new file mode 100644 index 0000000..fb724d8 --- /dev/null +++ b/src/components/SiteFooter/SiteFooter.mdx @@ -0,0 +1,45 @@ +import { Meta } from '@storybook/blocks'; + +import * as SiteFooterStories from './SiteFooter.stories.svelte'; + + + +# SiteFooter + +Reuters dotcom site footer with graphics referrals, ported from [Raptor UI components](https://github.com/tr/rcom-arc_raptor-ui/tree/develop/packages/rcom-raptor-ui_common/src/components/site-footer). + +> **Note:** In the graphics kit, you can find this component in `pages/+page.svelte`. Customise it there for the default page. + +```svelte + + + +``` + +## Dark theme + +Colours are customised by the [`Theme`](?path=/docs/theming-theme--default) component. ([Demo](?path=/story/components-page-furniture-sitefooter--customised-theme)) + +```svelte + + + + + +``` + +## Removing referrals + +Remove graphics referrals. ([Demo](?path=/story/components-page-furniture-sitefooter--remove-referrals)) + +```svelte + + + +``` diff --git a/src/components/SiteFooter/SiteFooter.stories.svelte b/src/components/SiteFooter/SiteFooter.stories.svelte new file mode 100644 index 0000000..d05461a --- /dev/null +++ b/src/components/SiteFooter/SiteFooter.stories.svelte @@ -0,0 +1,29 @@ + + + + + +
+ + + +
+
+ + + + diff --git a/src/components/SiteFooter/SiteFooter.svelte b/src/components/SiteFooter/SiteFooter.svelte new file mode 100644 index 0000000..ece8bd1 --- /dev/null +++ b/src/components/SiteFooter/SiteFooter.svelte @@ -0,0 +1,85 @@ + + + +
+
+ {#if includeReferrals} + + + + {/if} + + + +
+
+ + diff --git a/src/components/SiteFooter/data.json b/src/components/SiteFooter/data.json new file mode 100644 index 0000000..76a8f61 --- /dev/null +++ b/src/components/SiteFooter/data.json @@ -0,0 +1,210 @@ +[ + { + "company_description": "Reuters, the news and media division of Thomson Reuters, is the worldโ€™s largest multimedia news provider, reaching billions of people worldwide every day. Reuters provides business, financial, national and international news to professionals via desktop terminals, the world's media organizations, industry events and directly to consumers.", + "disclaimer_link": "https://www.reuters.com/info-pages/disclaimer/", + "copyright_link": "https://www.thomsonreuters.com/en/policies/copyright.html", + "copyright_year": "2025", + "latest_links": [ + { + "text": "Home", + "url": "/", + "self": true + } + ], + "browse_links": [ + { + "text": "World", + "url": "/world/", + "self": true + }, + { + "text": "Business", + "url": "/business/", + "self": true + }, + { + "text": "Legal", + "url": "/legal/", + "self": true + }, + { + "text": "Markets", + "url": "/markets/", + "self": true + }, + { + "text": "Breakingviews", + "url": "/breakingviews/", + "self": true + }, + { + "text": "Technology", + "url": "/technology/", + "self": true + }, + { + "text": "Investigations", + "url": "/investigates/" + }, + { + "text": "Lifestyle", + "url": "/lifestyle/", + "self": true + } + ], + "media_links": [ + { + "text": "Videos", + "url": "https://www.reuters.com/video/", + "symbol": "videos" + }, + { + "text": "Pictures", + "url": "https://www.reuters.com/news/pictures", + "symbol": "pictures" + }, + { + "text": "Graphics", + "url": "https://graphics.reuters.com/", + "symbol": "graphics" + } + ], + "about_links": [ + { + "text": "About Reuters", + "url": "https://www.reutersagency.com/en/about/about-us/" + }, + { + "text": "Careers", + "url": "https://www.thomsonreuters.com/en/careers.html" + }, + { + "text": "Reuters News Agency", + "url": "https://www.reutersagency.com/en/?utm_source=website&utm_medium=reuters&utm_campaign=site-referral&utm_content=us&utm_term=0" + }, + { + "text": "Brand Attribution Guidelines", + "url": "https://www.reutersagency.com/en/about/about-us/brand-attribution-guidelines/" + }, + { + "text": "Reuters Leadership", + "url": "https://www.reutersagency.com/en/about/leadership-team/" + }, + { + "text": "Reuters Fact Check", + "url": "https://www.reuters.com/fact-check/" + }, + { + "text": "Reuters Diversity Report", + "url": "https://www.reuters.com/DiversityReportApril2022" + } + ], + "stay_informed_links": [ + { + "text": "Download the App", + "url": "https://www.reuters.com/tools/mobile/us" + }, + { + "text": "Newsletters", + "url": "https://newslink.reuters.com/join/subscribe" + } + ], + "social_links": [ + { + "type": "twitter", + "url": "https://www.twitter.com/Reuters" + }, + { + "type": "facebook", + "url": "https://www.facebook.com/Reuters" + }, + { + "type": "instagram", + "url": "https://www.instagram.com/Reuters" + }, + { + "type": "youtube", + "url": "https://www.youtube.com/user/ReutersVideo" + }, + { + "type": "linkedin", + "url": "https://www.linkedin.com/company/10256858/" + } + ], + "tr_products": [ + { + "name": "Westlaw", + "description": "Build the strongest argument relying on authoritative content, attorney-editor expertise, and industry defining technology.", + "url": "https://legal.thomsonreuters.com/en/products/westlaw" + }, + { + "name": "Onesource", + "description": "The most comprehensive solution to manage all your complex and ever-expanding tax and compliance needs.", + "url": "https://tax.thomsonreuters.com/en/onesource" + }, + { + "name": "Checkpoint", + "description": "The industry leader for online information for tax, accounting and finance professionals.", + "url": "https://tax.thomsonreuters.com/en/checkpoint" + } + ], + "refinitiv_products": [ + { + "name": "Refinitiv Workspace", + "description": " Access unmatched financial data, news and content in a highly-customised workflow experience on desktop, web and mobile.", + "url": " https://www.refinitiv.com/en/products/refinitiv-workspace" + }, + { + "name": "Refinitiv Data Catalogue", + "description": " Browse an unrivalled portfolio of real-time and historical market data and insights from worldwide sources and experts.", + "url": " https://www.refinitiv.com/en/financial-data" + }, + { + "name": "Refinitiv World-Check", + "description": "Screen for heightened risk individual and entities globally to help uncover hidden risks in business relationships and human networks.", + "url": "https://www.refinitiv.com/en/products/world-check-kyc-screening" + } + ], + "ad_links": [ + { + "text": "Advertise With Us", + "url": "https://www.reutersagency.com/en/services/advertising-solutions/" + }, + { + "text": "Advertising Guidelines", + "url": "/info-pages/advertising-guidelines/" + } + ], + "misc_links": [ + { + "text": "Cookies", + "url": "https://www.thomsonreuters.com/en/privacy-statement.html#cookies" + }, + { + "text": "Terms of Use", + "url": "/info-pages/terms-of-use/" + }, + { + "text": "Privacy", + "url": "https://www.thomsonreuters.com/en/privacy-statement.html" + }, + { + "text": "Digital Accessibility", + "url": "https://www.thomsonreuters.com/en/policies/digital-accessibility-policy.html" + }, + { + "text": "Corrections", + "url": "/info-pages/contact-us/" + }, + { + "text": "Site Feedback", + "url": "https://trdigital.iad1.qualtrics.com/jfe/form/SV_8kte8gArGyCGVhz" + }, + { + "text": "Do Not Sell My Personal Information", + "url": "javascript:window.OneTrust.ToggleInfoDisplay();", + "self": true + } + ] + } +] diff --git a/src/components/SiteFooter/svgs/Facebook.svelte b/src/components/SiteFooter/svgs/Facebook.svelte new file mode 100644 index 0000000..045cd7b --- /dev/null +++ b/src/components/SiteFooter/svgs/Facebook.svelte @@ -0,0 +1,25 @@ + + + + + diff --git a/src/components/SiteFooter/svgs/Graphics.svelte b/src/components/SiteFooter/svgs/Graphics.svelte new file mode 100644 index 0000000..c15bb5f --- /dev/null +++ b/src/components/SiteFooter/svgs/Graphics.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/components/SiteFooter/svgs/Instagram.svelte b/src/components/SiteFooter/svgs/Instagram.svelte new file mode 100644 index 0000000..1e45cc2 --- /dev/null +++ b/src/components/SiteFooter/svgs/Instagram.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/src/components/SiteFooter/svgs/LinkedIn.svelte b/src/components/SiteFooter/svgs/LinkedIn.svelte new file mode 100644 index 0000000..bb3505c --- /dev/null +++ b/src/components/SiteFooter/svgs/LinkedIn.svelte @@ -0,0 +1,25 @@ + + + + + diff --git a/src/components/SiteFooter/svgs/Pictures.svelte b/src/components/SiteFooter/svgs/Pictures.svelte new file mode 100644 index 0000000..2d15743 --- /dev/null +++ b/src/components/SiteFooter/svgs/Pictures.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/components/SiteFooter/svgs/Twitter.svelte b/src/components/SiteFooter/svgs/Twitter.svelte new file mode 100644 index 0000000..1c5e81c --- /dev/null +++ b/src/components/SiteFooter/svgs/Twitter.svelte @@ -0,0 +1,27 @@ + + + + + diff --git a/src/components/SiteFooter/svgs/Videos.svelte b/src/components/SiteFooter/svgs/Videos.svelte new file mode 100644 index 0000000..937bda4 --- /dev/null +++ b/src/components/SiteFooter/svgs/Videos.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/components/SiteFooter/svgs/YouTube.svelte b/src/components/SiteFooter/svgs/YouTube.svelte new file mode 100644 index 0000000..cadb5e0 --- /dev/null +++ b/src/components/SiteFooter/svgs/YouTube.svelte @@ -0,0 +1,25 @@ + + + + + diff --git a/src/components/SiteHeader/MobileMenu/index.svelte b/src/components/SiteHeader/MobileMenu/index.svelte new file mode 100644 index 0000000..94c47c1 --- /dev/null +++ b/src/components/SiteHeader/MobileMenu/index.svelte @@ -0,0 +1,197 @@ + + +{#if isMobileMenuOpen} +
+
+ + +
+ {#each data.sections as section} +
+ {section.name} + {#if section.children} + + {/if} +
+ {/each} +
+{/if} + + diff --git a/src/components/SiteHeader/NavBar/DownArrow.svelte b/src/components/SiteHeader/NavBar/DownArrow.svelte new file mode 100644 index 0000000..24467c9 --- /dev/null +++ b/src/components/SiteHeader/NavBar/DownArrow.svelte @@ -0,0 +1,33 @@ + + + + + diff --git a/src/components/SiteHeader/NavBar/NavDropdown/MoreDropdown.svelte b/src/components/SiteHeader/NavBar/NavDropdown/MoreDropdown.svelte new file mode 100644 index 0000000..6e0508a --- /dev/null +++ b/src/components/SiteHeader/NavBar/NavDropdown/MoreDropdown.svelte @@ -0,0 +1,110 @@ + + + +
+
+ {#each sections as section} +
+ + {section.name} + + {#if section.children} +
    + {#each section.children as sub} +
  • + {sub.name} +
  • + {/each} +
+ {/if} +
+ {/each} +
+
+
+ + diff --git a/src/components/SiteHeader/NavBar/NavDropdown/SectionDropdown.svelte b/src/components/SiteHeader/NavBar/NavDropdown/SectionDropdown.svelte new file mode 100644 index 0000000..676a684 --- /dev/null +++ b/src/components/SiteHeader/NavBar/NavDropdown/SectionDropdown.svelte @@ -0,0 +1,134 @@ + + + + + + Browse {section.name} + + +
+ {#if splitCount > 0} +
    + {#each section.children.slice(0, splitCount) as sub} +
  • + + {sub.name} + +
  • + {/each} +
+ {/if} +
    + {#each section.children.slice(splitCount) as sub} +
  • + + {sub.name} + +
  • + {/each} +
+
+
+ + diff --git a/src/components/SiteHeader/NavBar/NavDropdown/Spinner/index.svelte b/src/components/SiteHeader/NavBar/NavDropdown/Spinner/index.svelte new file mode 100644 index 0000000..3e96749 --- /dev/null +++ b/src/components/SiteHeader/NavBar/NavDropdown/Spinner/index.svelte @@ -0,0 +1,49 @@ +
+
+
+
+
+ + diff --git a/src/components/SiteHeader/NavBar/NavDropdown/StoryCard/index.svelte b/src/components/SiteHeader/NavBar/NavDropdown/StoryCard/index.svelte new file mode 100644 index 0000000..8496750 --- /dev/null +++ b/src/components/SiteHeader/NavBar/NavDropdown/StoryCard/index.svelte @@ -0,0 +1,94 @@ + + +
+ +
+ {story.title} + +
+ {#if thumbnail && (thumbnail.resizer_url || thumbnail?.renditions?.square?.['120w'])} +
+ {#if thumbnail.resizer_url} + {thumbnail.alt_text} + {:else} + {thumbnail.alt_text} + {/if} +
+ {/if} +
+
+ + diff --git a/src/components/SiteHeader/NavBar/NavDropdown/StoryCard/time.ts b/src/components/SiteHeader/NavBar/NavDropdown/StoryCard/time.ts new file mode 100644 index 0000000..db2455a --- /dev/null +++ b/src/components/SiteHeader/NavBar/NavDropdown/StoryCard/time.ts @@ -0,0 +1,74 @@ +import advancedFormat from 'dayjs/plugin/advancedFormat.js'; +import dayjs from 'dayjs'; +import localizedFormat from 'dayjs/plugin/localizedFormat.js'; +import relativeTime from 'dayjs/plugin/relativeTime.js'; +import timezone from 'dayjs/plugin/timezone.js'; +import updateLocale from 'dayjs/plugin/updateLocale.js'; +import utc from 'dayjs/plugin/utc.js'; + +dayjs.extend(relativeTime); +dayjs.extend(localizedFormat); +dayjs.extend(advancedFormat); +dayjs.extend(utc); +dayjs.extend(timezone); +dayjs.extend(updateLocale); + +dayjs.updateLocale('en', { + relativeTime: { + future: 'in %s', + past: '%s ago', + s: 'a few seconds', + m: 'a min', + mm: '%d min', + h: 'an hour', + hh: '%d hours', + d: 'a day', + dd: '%d days', + M: 'a month', + MM: '%d months', + y: 'a year', + yy: '%d years', + }, +}); + +const getTimeZone = (local: boolean) => { + if (local) { + return dayjs.tz.guess(); + } + + return 'UTC'; +}; + +const diff = ( + dateFrom: Date, + dateTo: number, + measurement: 'day' | 'hour' = 'day' +) => { + return dayjs(dateFrom).diff(dayjs(dateTo), measurement, true); +}; + +const olderThanHour = (dateFrom: Date, dateTo: number, hours = 1) => { + return diff(dateFrom, dateTo, 'hour') < -hours; +}; + +const isSameDay = (dateFrom: Date, dateTo: number) => { + const first = new Date(dateFrom); + const second = new Date(dateTo); + return ( + first.getFullYear() === second.getFullYear() && + first.getMonth() === second.getMonth() && + first.getDate() === second.getDate() + ); +}; + +export const getTime = (datetime: dayjs.ConfigType) => { + const publishTime = dayjs(datetime, { utc: true }); + const showRelativeTime = !olderThanHour(publishTime.toDate(), Date.now()); + const showTime = isSameDay(publishTime.toDate(), Date.now()); + const timezone = getTimeZone(false); + if (showRelativeTime) { + return dayjs().to(publishTime); + } + if (showTime) return dayjs(datetime).tz(timezone).format('h:mm A z'); + return publishTime.format('MMMM D, YYYY'); +}; diff --git a/src/components/SiteHeader/NavBar/NavDropdown/index.svelte b/src/components/SiteHeader/NavBar/NavDropdown/index.svelte new file mode 100644 index 0000000..e9b2e99 --- /dev/null +++ b/src/components/SiteHeader/NavBar/NavDropdown/index.svelte @@ -0,0 +1,248 @@ + + + + + diff --git a/src/components/SiteHeader/NavBar/index.svelte b/src/components/SiteHeader/NavBar/index.svelte new file mode 100644 index 0000000..b448392 --- /dev/null +++ b/src/components/SiteHeader/NavBar/index.svelte @@ -0,0 +1,268 @@ + + + + + + + diff --git a/src/components/SiteHeader/NavBar/utils/index.ts b/src/components/SiteHeader/NavBar/utils/index.ts new file mode 100644 index 0000000..bbb458b --- /dev/null +++ b/src/components/SiteHeader/NavBar/utils/index.ts @@ -0,0 +1,2 @@ +export const normalizeUrl = (url: string) => + /^http/.test(url) ? url : `https://www.reuters.com${url}`; diff --git a/src/components/SiteHeader/SiteHeader.mdx b/src/components/SiteHeader/SiteHeader.mdx new file mode 100644 index 0000000..abd6348 --- /dev/null +++ b/src/components/SiteHeader/SiteHeader.mdx @@ -0,0 +1,33 @@ +import { Meta } from '@storybook/blocks'; + +import * as SiteHeaderStories from './SiteHeader.stories.svelte'; + + + +# SiteHeader + +Reuters dotcom site header, ported from [Raptor UI components](https://github.com/tr/rcom-arc_raptor-ui/tree/develop/packages/rcom-raptor-ui_common/src/components/site-header). + +> **Note:** In the graphics kit, you can find this component in `pages/+page.svelte`. Customise it there for the default page. + +```svelte + + + +``` + +## Dark theme + +Colours are customised by the [`Theme`](?path=/docs/theming-theme--default) component. ([Demo](?path=/story/components-page-furniture-siteheader--customised-theme)) + +```svelte + + + + + +``` diff --git a/src/components/SiteHeader/SiteHeader.stories.svelte b/src/components/SiteHeader/SiteHeader.stories.svelte new file mode 100644 index 0000000..3fe3f8d --- /dev/null +++ b/src/components/SiteHeader/SiteHeader.stories.svelte @@ -0,0 +1,47 @@ + + + { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByText('More')); + await waitFor(() => + expect(canvas.getByText('Graphics')).toBeInTheDocument() + ); + await userEvent.click(canvas.getByText('World')); + await waitFor(() => expect(canvas.getByText('Europe')).toBeInTheDocument()); + }} +> +
+ +
+
+ + +
+ + + +
+
+ + diff --git a/src/components/SiteHeader/SiteHeader.svelte b/src/components/SiteHeader/SiteHeader.svelte new file mode 100644 index 0000000..a6e3cc3 --- /dev/null +++ b/src/components/SiteHeader/SiteHeader.svelte @@ -0,0 +1,268 @@ + + + +
+ + +
+ + { + isMobileMenuOpen = false; + }} + data={data[0]} +/> + + diff --git a/src/components/SiteHeader/data.json b/src/components/SiteHeader/data.json new file mode 100644 index 0000000..97f4bd6 --- /dev/null +++ b/src/components/SiteHeader/data.json @@ -0,0 +1,347 @@ +[ + { + "sections": [ + { + "id": "/world/", + "url": "/world/", + "name": "World", + "type": "section", + "children": [ + { "id": "/world/africa/", "url": "/world/africa/", "name": "Africa" }, + { + "id": "/world/americas/", + "url": "/world/americas/", + "name": "Americas" + }, + { + "id": "/world/asia-pacific/", + "url": "/world/asia-pacific/", + "name": "Asia Pacific" + }, + { "id": "/world/china/", "url": "/world/china/", "name": "China" }, + { "id": "/world/europe/", "url": "/world/europe/", "name": "Europe" }, + { "id": "/world/india/", "url": "/world/india/", "name": "India" }, + { + "id": "/world/middle-east/", + "url": "/world/middle-east/", + "name": "Middle East" + }, + { "id": "/world/uk/", "url": "/world/uk/", "name": "United Kingdom" }, + { "id": "/world/us/", "url": "/world/us/", "name": "United States" }, + { + "id": "/world/the-great-reboot/", + "url": "/world/the-great-reboot/", + "name": "The Great Reboot" + }, + { + "id": "/world/reuters-next/", + "url": "/world/reuters-next/", + "name": "Reuters Next" + } + ] + }, + { + "id": "/business/", + "url": "/business/", + "name": "Business", + "type": "section", + "children": [ + { + "id": "/business/aerospace-defense/", + "url": "/business/aerospace-defense/", + "name": "Aerospace & Defense" + }, + { + "id": "/business/autos-transportation/", + "url": "/business/autos-transportation/", + "name": "Autos & Transportation" + }, + { + "id": "/business/energy/", + "url": "/business/energy/", + "name": "Energy" + }, + { + "id": "/business/environment/", + "url": "/business/environment/", + "name": "Environment" + }, + { + "id": "/business/finance/", + "url": "/business/finance/", + "name": "Finance" + }, + { + "id": "/business/healthcare-pharmaceuticals/", + "url": "/business/healthcare-pharmaceuticals/", + "name": "Healthcare & Pharmaceuticals" + }, + { + "id": "/business/media-telecom/", + "url": "/business/media-telecom/", + "name": "Media & Telecom" + }, + { + "id": "/business/retail-consumer/", + "url": "/business/retail-consumer/", + "name": "Retail & Consumer" + }, + { + "id": "/business/sustainable-business/", + "url": "/business/sustainable-business/", + "name": "Sustainable Business" + }, + { + "id": "/business/charged/", + "url": "/business/charged/", + "name": "Charged" + }, + { + "id": "/business/future-of-health/", + "url": "/business/future-of-health/", + "name": "Future of Health" + }, + { + "id": "/business/future-of-money/", + "url": "/business/future-of-money/", + "name": "Future of Money" + }, + { + "id": "/business/take-five/", + "url": "/business/take-five/", + "name": "Take Five" + }, + { + "id": "/business/reuters-impact/", + "url": "/business/reuters-impact/", + "name": "Reuters Impact" + }, + { + "id": "/business/davos/", + "url": "/business/davos/", + "name": "Davos" + } + ] + }, + { + "id": "/legal/", + "url": "/legal/", + "name": "Legal", + "type": "section", + "children": [ + { + "id": "/legal/government/", + "url": "/legal/government/", + "name": "Government" + }, + { + "id": "/legal/legalindustry/", + "url": "/legal/legalindustry/", + "name": "Legal Industry" + }, + { + "id": "/legal/litigation/", + "url": "/legal/litigation/", + "name": "Litigation" + }, + { + "id": "/legal/transactional/", + "url": "/legal/transactional/", + "name": "Transactional" + } + ] + }, + { + "id": "/markets/", + "url": "/markets/", + "name": "Markets", + "type": "section", + "children": [ + { + "id": "/markets/asia/", + "url": "/markets/asia/", + "name": "Asian Markets" + }, + { + "id": "/markets/carbon/", + "url": "/markets/carbon/", + "name": "Carbon Markets" + }, + { + "id": "/markets/commodities/", + "url": "/markets/commodities/", + "name": "Commodities" + }, + { + "id": "/markets/currencies/", + "url": "/markets/currencies/", + "name": "Currencies" + }, + { + "id": "/markets/deals/", + "url": "/markets/deals/", + "name": "Deals" + }, + { + "id": "/markets/emerging/", + "url": "/markets/emerging/", + "name": "Emerging Markets" + }, + { + "id": "/markets/europe/", + "url": "/markets/europe/", + "name": "European Markets" + }, + { + "id": "/markets/funds/", + "url": "/markets/funds/", + "name": "Funds" + }, + { + "id": "/markets/global-market-data/", + "url": "/markets/global-market-data/", + "name": "Global Market Data" + }, + { + "id": "/markets/rates-bonds/", + "url": "/markets/rates-bonds/", + "name": "Rates & Bonds" + }, + { + "id": "/markets/stocks/", + "url": "/markets/stocks/", + "name": "Stocks" + }, + { + "id": "/markets/us/", + "url": "/markets/us/", + "name": "U.S. Markets" + }, + { + "id": "/markets/wealth/", + "url": "/markets/wealth/", + "name": "Wealth" + }, + { + "id": "/markets/macromatters/", + "url": "/markets/macromatters/", + "name": "Macro Matters" + } + ] + }, + { + "id": "/breakingviews/", + "url": "/breakingviews/", + "name": "Breakingviews", + "type": "section" + }, + { + "id": "/technology/", + "url": "/technology/", + "name": "Technology", + "type": "section", + "children": [ + { + "id": "/technology/disrupted/", + "url": "/technology/disrupted/", + "name": "Disrupted" + }, + { + "id": "/technology/reuters-momentum/", + "url": "/technology/reuters-momentum/", + "name": "Reuters Momentum" + } + ] + }, + { + "id": "/investigates/", + "url": "https://www.reuters.com/investigates/", + "name": "Investigations", + "type": "link" + }, + { + "id": "/lifestyle/sports/", + "url": "/lifestyle/sports/", + "name": "Sports", + "type": "section", + "children": [ + { + "id": "/lifestyle/sports/athletics/", + "url": "/lifestyle/sports/athletics/", + "name": "Athletics" + }, + { + "id": "/lifestyle/sports/cricket/", + "url": "/lifestyle/sports/cricket/", + "name": "Cricket" + }, + { + "id": "/lifestyle/sports/cycling/", + "url": "/lifestyle/sports/cycling/", + "name": "Cycling" + }, + { + "id": "/lifestyle/sports/golf/", + "url": "/lifestyle/sports/golf/", + "name": "Golf" + }, + { + "id": "/lifestyle/sports/motor-sports/", + "url": "/lifestyle/sports/motor-sports/", + "name": "Motor Sports" + }, + { + "id": "/lifestyle/sports/soccer/", + "url": "/lifestyle/sports/soccer/", + "name": "Soccer" + }, + { + "id": "/lifestyle/sports/tennis/", + "url": "/lifestyle/sports/tennis/", + "name": "Tennis" + } + ] + }, + { + "id": "/lifestyle/", + "url": "/lifestyle/", + "name": "Lifestyle", + "type": "section", + "children": [ + { + "id": "/lifestyle/oddly-enough/", + "url": "/lifestyle/oddly-enough/", + "name": "Oddly Enough" + }, + { + "id": "/lifestyle/science/", + "url": "/lifestyle/science/", + "name": "Science" + } + ] + }, + { + "id": "/graphics/", + "url": "https://graphics.reuters.com/", + "name": "Graphics", + "type": "link" + }, + { + "id": "/pictures/", + "url": "/pictures/", + "name": "Pictures", + "type": "section" + }, + { "id": "/video/", "url": "/video/", "name": "Video", "type": "section" } + ], + "home_url": "/", + "search_url": "/site-search/", + "sign_in_url": "/signin/", + "sign_up_url": "/signup/", + "subscribe_url": "", + "my_account_url": "/myaccount/", + "my_view_url": "/myview/all", + "following_url": "/myview/following-feed", + "saved_url": "/myview/saved" + } +] diff --git a/src/components/SiteHeader/scss/_breakpoints.scss b/src/components/SiteHeader/scss/_breakpoints.scss new file mode 100644 index 0000000..57266b1 --- /dev/null +++ b/src/components/SiteHeader/scss/_breakpoints.scss @@ -0,0 +1,79 @@ +// From FSC: +// Our design layouts are based on 2 artboard sizes: +// 375px for small screens and 1440px for desktop. + +// However, these are snapshots to inform the core layouts. +// Some aspects of the design system adapt to breakpoints between these sizes. + +// Our design layouts therefore show the snapshots for mobile on the 375px artboard and wide on the 1440px artboard. + +// Note that if we refer only to desktop it means all layouts above 1023px, similarly mobile in general is below 1024px. + +// Note that the desktop breakpoint kicks-in at 1024px, which also accommodates iPad/tablet in landscape. +// This is the last size before the layout adapts to the mobile view. + +$maxWidth: 1440px; + +@mixin for-small-mobile { + @media (max-width: 518px) { + @content; + } +} + +@mixin for-mobile { + @media (max-width: 745px) { + @content; + } +} + +@mixin for-tablet { + @media (min-width: 746px) and (max-width: 1023px) { + @content; + } +} + +@mixin for-tablet-up { + @media (min-width: 746px) { + @content; + } +} + +@mixin for-tablet-down { + @media (max-width: 1023px) { + @content; + } +} + +@mixin for-tight-desktop { + @media (min-width: 1024px) and (max-width: 1060px) { + @content; + } +} + +@mixin for-desktop { + @media (min-width: 1024px) { + @content; + } +} + +@mixin for-wide-desktop { + @media (min-width: 1300px) { + @content; + } +} + +@mixin for-extra-wide-desktop { + @media (min-width: 1440px) { + @content; + } +} + +@mixin above-max { + @media (min-width: $maxWidth) { + @content; + } +} + +@mixin max-width { + max-width: $maxWidth; +} diff --git a/src/components/SiteHeader/scss/_colors.scss b/src/components/SiteHeader/scss/_colors.scss new file mode 100644 index 0000000..1f731a5 --- /dev/null +++ b/src/components/SiteHeader/scss/_colors.scss @@ -0,0 +1,25 @@ +// Sheet of project colors +$tr-orange: #fa6400; +$tr-dark-orange: #dc4300; +$tr-light-orange: #ffa100; +$tr-dark-grey: #404040; +$tr-medium-grey: #666666; +$tr-light-grey: #afafaf; +$tr-muted-grey: #d0d0d0; +$tr-hover-background-grey: #f8f8f8; +$tr-light-muted-grey: #f4f4f4; +$tr-ultra-light-grey: #fafafa; +$tr-dark-blue: #005da2; +$tr-light-blue: #0099c4; +$tr-muted-blue: #4386b9; +$tr-lighter-blue: #7facce; +$tr-superlight-blue: #e5eef5; +$tr-dark-purple: #621f95; +$tr-light-purple: #6e3ab7; +$tr-dark-red: #a00000; +$tr-light-red: #dc0a0a; +$tr-dark-green: #387c2b; +$tr-light-green: #77a22d; +$black: #000; +$white: #fff; +$ad-placeholder: #ffb1b1; diff --git a/src/components/SiteHeader/scss/_eases.scss b/src/components/SiteHeader/scss/_eases.scss new file mode 100644 index 0000000..ae36571 --- /dev/null +++ b/src/components/SiteHeader/scss/_eases.scss @@ -0,0 +1,9 @@ +$principleDefaultEase: cubic-bezier(0.25, 0.1, 0.25, 1); +$easeOutExpo: cubic-bezier(0.19, 1, 0.22, 1); +$easeOutCubic: cubic-bezier(0.215, 0.61, 0.355, 1); +$easeInOutCubic: cubic-bezier(0.645, 0.045, 0.355, 1); +$easeInOutQuad: cubic-bezier(0.455, 0.03, 0.515, 0.955); +$easeInQuad: cubic-bezier(0.55, 0.085, 0.68, 0.53); +$easeOutQuad: cubic-bezier(0.25, 0.46, 0.45, 0.94); +$navContainerEase: cubic-bezier(0.25, 0.1, 0.25, 1); +$rtvDefaultEase: cubic-bezier(0.165, 0.84, 0.44, 1); diff --git a/src/components/SiteHeader/scss/_grids.scss b/src/components/SiteHeader/scss/_grids.scss new file mode 100644 index 0000000..74ed066 --- /dev/null +++ b/src/components/SiteHeader/scss/_grids.scss @@ -0,0 +1,158 @@ +@use 'sass:math'; + +@use '_breakpoints.scss' as *; + +@mixin spacing-single($properties, $delta: 1) { + @each $property in $properties { + & { + #{$property}: (math.div(32, 1440) * 100vw * $delta); + } + } + + @include for-tablet-down { + @each $property in $properties { + & { + #{$property}: (math.div(16, 375) * 100vw * $delta); + } + } + } + + @include above-max { + @each $property in $properties { + & { + #{$property}: (32px * $delta); + } + } + } +} + +@mixin spacing-single-half($properties, $delta: 1) { + @each $property in $properties { + & { + #{$property}: (calc(16 / 1440) * 100vw * $delta); + } + } + + @include for-tablet-down { + @each $property in $properties { + & { + #{$property}: (math.div(8, 375) * 100vw * $delta); + } + } + } + + @include above-max { + @each $property in $properties { + & { + #{$property}: (16px * $delta); + } + } + } +} + +@mixin spacing-single-34($properties, $delta: 1) { + @each $property in $properties { + & { + #{$property}: (math.div(24, 1440) * 100vw * $delta); + } + } + + @include for-tablet-down { + @each $property in $properties { + & { + #{$property}: (math.div(12, 375) * 100vw * $delta); + } + } + } + + @include above-max { + @each $property in $properties { + & { + #{$property}: (24px * $delta); + } + } + } +} + +@mixin spacing-150($properties, $delta: 1) { + @each $property in $properties { + & { + #{$property}: (math.div(48, 1440) * 100vw * $delta); + } + } + + @include for-tablet-down { + @each $property in $properties { + & { + #{$property}: (math.div(24, 375) * 100vw * $delta); + } + } + } + + @include above-max { + @each $property in $properties { + & { + #{$property}: (48px * $delta); + } + } + } +} + +@mixin spacing-75($properties, $delta: 1) { + @each $property in $properties { + & { + #{$property}: (math.div(24, 1440) * 100vw * $delta); + } + } + + @include above-max { + @each $property in $properties { + & { + #{$property}: (24px * $delta); + } + } + } +} + +@mixin spacing-50($properties, $delta: 1) { + @each $property in $properties { + & { + #{$property}: (math.div(16, 1440) * 100vw * $delta); + } + } + + @include above-max { + @each $property in $properties { + & { + #{$property}: (16px * $delta); + } + } + } +} + +@mixin responsive-columns($columns, $size: 1fr) { + @content; + + display: grid; + grid-template-columns: repeat($columns, $size); + + // Desktop grid (all screens greater than or equal to 1024px) + @include spacing-single(grid-column-gap); + + // Mobile grid (all screens up to and including 1023px) + @include for-tablet-down { + grid-template-columns: repeat(4, $size); + } +} + +@mixin at-4-columns { + @include for-tablet-down { + @content; + } +} + +@mixin above-4-columns { + @include for-desktop { + @content; + } +} diff --git a/src/components/SiteHeader/scss/_z-indexes.scss b/src/components/SiteHeader/scss/_z-indexes.scss new file mode 100644 index 0000000..c3bb9cb --- /dev/null +++ b/src/components/SiteHeader/scss/_z-indexes.scss @@ -0,0 +1,15 @@ +/* +Several components utilize z-index, the CSS property that helps control layout by providing a third axis to arrange content. We utilize a default z-index scale thatโ€™s been designed to properly layer navigation, tooltips and popovers, modals, and more. +These higher values start at an arbitrary number, high and specific enough to ideally avoid conflicts. We need a standard set of these across our layered componentsโ€”tooltips, popovers, navbars, dropdowns, modalsโ€”so we can be reasonably consistent in the behaviors. +To handle overlapping borders within components (e.g., buttons and inputs in input groups), we use low single digit z-index values of 1, 2, and 3 for default, hover, and active states. On hover/focus/active, we bring a particular element to the forefront with a higher z-index value to show their border over the sibling elements. +*/ + +$zindex-dropdown: 1000; +$zindex-sticky: 1020; +$zindex-fixed: 1030; +$zindex-modal-backdrop: 1040; +$zindex-offcanvas: 1050; +$zindex-modal: 1060; +$zindex-popover: 1070; +$zindex-tooltip: 1080; +$zindex-close-button: 1090; diff --git a/src/components/SiteHeader/svgs/Close.svelte b/src/components/SiteHeader/svgs/Close.svelte new file mode 100644 index 0000000..0a6d359 --- /dev/null +++ b/src/components/SiteHeader/svgs/Close.svelte @@ -0,0 +1,18 @@ + + + diff --git a/src/components/SiteHeader/svgs/Menu.svelte b/src/components/SiteHeader/svgs/Menu.svelte new file mode 100644 index 0000000..924657c --- /dev/null +++ b/src/components/SiteHeader/svgs/Menu.svelte @@ -0,0 +1,26 @@ + + + + + diff --git a/src/components/SiteHeadline/SiteHeadline.mdx b/src/components/SiteHeadline/SiteHeadline.mdx new file mode 100644 index 0000000..da70943 --- /dev/null +++ b/src/components/SiteHeadline/SiteHeadline.mdx @@ -0,0 +1,69 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as SiteHeadlineStories from './SiteHeadline.stories.svelte'; + + + +# SiteHeadline + +The `SiteHeadline` component creates a simplified Reuters Graphics headline, loosely modelled off the Reuters.com styles. + +Styles for this headline are intentionally restricted. It is meant to serve as a unifying style for quick-turnaround breaking news pages. + +```svelte + + + +``` + + + +## Using with ArchieML docs + +With the graphics kit, you'll likely get your text value from an ArchieML doc... + +```yaml +# ArchieML doc +section: Global News # Optional +sectionUrl: https://www.reuters.com/graphics/ # Optional +hed: A beautiful page +[authors] +* Samuel Granados +* Dea Bankova +[] +published: 2022-09-12T08:30:00.000Z +updated: +``` + +... which you'll pass to the `SiteHeadline` component. + +```svelte + + + + +``` + + diff --git a/src/components/SiteHeadline/SiteHeadline.stories.svelte b/src/components/SiteHeadline/SiteHeadline.stories.svelte new file mode 100644 index 0000000..0988b41 --- /dev/null +++ b/src/components/SiteHeadline/SiteHeadline.stories.svelte @@ -0,0 +1,49 @@ + + + + + + + + + diff --git a/src/components/SiteHeadline/SiteHeadline.svelte b/src/components/SiteHeadline/SiteHeadline.svelte new file mode 100644 index 0000000..f1d5cc1 --- /dev/null +++ b/src/components/SiteHeadline/SiteHeadline.svelte @@ -0,0 +1,86 @@ + + + + +
+
+ {#if section} +

+ {#if sectionUrl} + {section} + {:else} + {section} + {/if} +

+ {/if} + {#if hed} +

+ {hed} +

+ {/if} +
+ +
+
diff --git a/src/components/Spinner/Spinner.mdx b/src/components/Spinner/Spinner.mdx new file mode 100644 index 0000000..fc15c31 --- /dev/null +++ b/src/components/Spinner/Spinner.mdx @@ -0,0 +1,25 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as SpinnerStories from './Spinner.stories.svelte'; + + + +# Spinner + +The `Spinner` component creates a simple loading spinner. Use it to hide long loading times for components that may be loading expensive media files or crunching through lots of data. + +```svelte + + +{#if somethingsLoading} + +{:else} +

The real deal is here.

+{/if} +``` + + diff --git a/src/components/Spinner/Spinner.stories.svelte b/src/components/Spinner/Spinner.stories.svelte new file mode 100644 index 0000000..f29e0b8 --- /dev/null +++ b/src/components/Spinner/Spinner.stories.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/components/Spinner/Spinner.svelte b/src/components/Spinner/Spinner.svelte new file mode 100644 index 0000000..62cc38a --- /dev/null +++ b/src/components/Spinner/Spinner.svelte @@ -0,0 +1,92 @@ + + + +
+
+
+
+
+
+
+ + diff --git a/src/components/Table/Table.mdx b/src/components/Table/Table.mdx new file mode 100644 index 0000000..d5e63e8 --- /dev/null +++ b/src/components/Table/Table.mdx @@ -0,0 +1,177 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as TableStories from './Table.stories.svelte'; + + + +# Table + +The `Table` component presents data as a table that you can make searchable, filtereable, sortable, or paginated. + +```svelte + + + +``` + + + +## Text elements + +Set the `title`, `dek`, `notes` and `source` options to add supporting metadata above and below the table. + +```svelte +
+``` + + + +## Truncated + +When your table has 10 or more rows, consider clipping it by setting the `truncated` option. When it is enabled, the table is clipped and readers must click a button below the table to see all rows. + +By default, this configuration will limit the table to 5 records. Change the cutoff point by adjusting the `truncateLength` option. + +This is a good option for simple tables with between 10 and 30 rows. It works best when the table doesn't require interactivity. + +```svelte +
+``` + + + +## Paginated + +When your table has many rows, you should consider breaking it up into pages by setting `paginated` to `true`. When it is enabled, readers can leaf through the data using a set of buttons below the table. + +By default, there are 25 records per page. Change the number by adjusting the `pageSize` option. + +This is a good option when publishing large tables for readers to explore. It works well with interactive features like searching and filters. + +```svelte +
+``` + + + +## Search bar + +Allow users to search the table by setting the optional `searchable` option to `true`. Modify the default text that appears in the box by setting `searchPlaceholder` to a different placeholder text. + +```svelte +
+``` + + + +## Filter + +Allow users to filter the table by providing one of the attributes as the `filterField`. This works best with categorical columns. + +Set `filterLabel` to make the category name more readable. For example, if the column is `Region`, set `filterLabel` to `regions` or `regions of the world`. + +```svelte +
+``` + + + +## Search and filter + +Feel free to both search and filter. + +```svelte +
+``` + + +``` + +## Sort + +Allow users to sort the table by setting `sortable` to `true`. Specify the starting order by setting `sortField` to a column name and `sortDirection` to `ascending` or `descending`. + +By default, all fields are sortable. If you'd like to limit the columns where sorting is allowed, provide a list to the `sortableFields` option. + +```svelte +
+``` + + + +## Format + +Format column values by supplying functions keyed to field names with the `fieldFormatters` option. Columns are still sorted using the raw, underlying values. + +Among other things, this feature can be used to provide a unit of measurement, such as `$` or `%`, with numeric fields. + +```svelte + + +
+``` + + diff --git a/src/components/Table/Table.stories.svelte b/src/components/Table/Table.stories.svelte new file mode 100644 index 0000000..7b230b9 --- /dev/null +++ b/src/components/Table/Table.stories.svelte @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + +, + }, + sortable: true, + sortField: 'Net worth (in billions)', + sortDirection: 'descending', + title: 'The Richest Women in the World', + source: 'Source: Forbes', + }} +/> diff --git a/src/components/Table/Table.svelte b/src/components/Table/Table.svelte new file mode 100644 index 0000000..0cd90bb --- /dev/null +++ b/src/components/Table/Table.svelte @@ -0,0 +1,385 @@ + + + + +
+ {#if title || dek || searchable || filterList} +
+ {#if title} +

{@html title}

+ {/if} + {#if dek} +

{@html dek}

+ {/if} + {#if searchable || filterList} +
truncateLength} + > + + + {#each includedFields as field} + + {/each} + + + + {#each currentPageData as item, idx} + + {#each includedFields as field} + + {/each} + + {/each} + {#if searchable && searchText && currentPageData.length === 0} + + + + {/if} + + {#if notes || source} + + {#if notes} + + + + {/if} + {#if source} + + + + {/if} + + {/if} +
+ {field} + {#if sortable && sortableFields.includes(field)} +
+ +
+ {/if} +
+ {@html formatValue(item, field, fieldFormatters)} +
+ No results found for "{searchText}" +
+
+ {@html notes} +
+
+
+ {@html source} +
+
+ + {#if truncated && searchableData.length > truncateLength} + + {/if} + {#if paginated} + {/if} + +
+ + diff --git a/src/components/Table/components/NextArrow.svelte b/src/components/Table/components/NextArrow.svelte new file mode 100644 index 0000000..3749a68 --- /dev/null +++ b/src/components/Table/components/NextArrow.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/components/Table/components/Pagination.svelte b/src/components/Table/components/Pagination.svelte new file mode 100644 index 0000000..10f3443 --- /dev/null +++ b/src/components/Table/components/Pagination.svelte @@ -0,0 +1,126 @@ + + + + + diff --git a/src/components/Table/components/PrevArrow.svelte b/src/components/Table/components/PrevArrow.svelte new file mode 100644 index 0000000..3545a94 --- /dev/null +++ b/src/components/Table/components/PrevArrow.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/components/Table/components/Select.svelte b/src/components/Table/components/Select.svelte new file mode 100644 index 0000000..9df3166 --- /dev/null +++ b/src/components/Table/components/Select.svelte @@ -0,0 +1,77 @@ + + +
+ +
+ +
+
+ + diff --git a/src/components/Table/components/SortArrow.svelte b/src/components/Table/components/SortArrow.svelte new file mode 100644 index 0000000..7eb22c7 --- /dev/null +++ b/src/components/Table/components/SortArrow.svelte @@ -0,0 +1,48 @@ + + + + + + + + diff --git a/src/components/Table/demo/homeRuns.json b/src/components/Table/demo/homeRuns.json new file mode 100644 index 0000000..4653061 --- /dev/null +++ b/src/components/Table/demo/homeRuns.json @@ -0,0 +1,42 @@ +[ + { + "Name": "Barryย Bonds", + "Home runs": 762 + }, + { + "Name": "Hank Aaron", + "Home runs": 755 + }, + { + "Name": "Babe Ruth", + "Home runs": 714 + }, + { + "Name": "Albert Pujols", + "Home runs": 703 + }, + { + "Name": "Alex Rodriguez", + "Home runs": 696 + }, + { + "Name": "Willie Mays", + "Home runs": 660 + }, + { + "Name": "Ken Griffey Jr.", + "Home runs": 630 + }, + { + "Name": "Jim Thome", + "Home runs": 612 + }, + { + "Name": "Sammy Sosa", + "Home runs": 609 + }, + { + "Name": "Frank Robinson", + "Home runs": 586 + } +] diff --git a/src/components/Table/demo/pressFreedom.json b/src/components/Table/demo/pressFreedom.json new file mode 100644 index 0000000..3c53add --- /dev/null +++ b/src/components/Table/demo/pressFreedom.json @@ -0,0 +1,887 @@ +[ + { + "Country": "Afghanistan", + "Region": "Southern Asia", + "Score": 40.19 + }, + { + "Country": "Albania", + "Region": "Southern Europe", + "Score": 30.59 + }, + { + "Country": "Algeria", + "Region": "Northern Africa", + "Score": 47.26 + }, + { + "Country": "Andorra", + "Region": "Southern Europe", + "Score": 23.32 + }, + { + "Country": "Angola", + "Region": "Sub-Saharan Africa", + "Score": 34.06 + }, + { + "Country": "Argentina", + "Region": "Latin America and the Caribbean", + "Score": 28.99 + }, + { + "Country": "Armenia", + "Region": "Western Asia", + "Score": 28.83 + }, + { + "Country": "Australia", + "Region": "Australia and New Zealand", + "Score": 19.79 + }, + { + "Country": "Austria", + "Region": "Western Europe", + "Score": 16.34 + }, + { + "Country": "Azerbaijan", + "Region": "Western Asia", + "Score": 58.77 + }, + { + "Country": "Bahrain", + "Region": "Western Asia", + "Score": 61.1 + }, + { + "Country": "Bangladesh", + "Region": "Southern Asia", + "Score": 49.71 + }, + { + "Country": "Belarus", + "Region": "Eastern Europe", + "Score": 50.82 + }, + { + "Country": "Belgium", + "Region": "Western Europe", + "Score": 11.69 + }, + { + "Country": "Belize", + "Region": "Latin America and the Caribbean", + "Score": 27.61 + }, + { + "Country": "Benin", + "Region": "Sub-Saharan Africa", + "Score": 38.18 + }, + { + "Country": "Bhutan", + "Region": "Southern Asia", + "Score": 28.86 + }, + { + "Country": "Bolivia", + "Region": "Latin America and the Caribbean", + "Score": 35.47 + }, + { + "Country": "Bosnia and Herzegovina", + "Region": "Southern Europe", + "Score": 28.34 + }, + { + "Country": "Botswana", + "Region": "Sub-Saharan Africa", + "Score": 23.25 + }, + { + "Country": "Brazil", + "Region": "Latin America and the Caribbean", + "Score": 36.25 + }, + { + "Country": "Brunei", + "Region": "South-eastern Asia", + "Score": 49.91 + }, + { + "Country": "Bulgaria", + "Region": "Eastern Europe", + "Score": 37.29 + }, + { + "Country": "Burkina Faso", + "Region": "Sub-Saharan Africa", + "Score": 23.17 + }, + { + "Country": "Burundi", + "Region": "Sub-Saharan Africa", + "Score": 47.57 + }, + { + "Country": "Cambodia", + "Region": "South-eastern Asia", + "Score": 46.84 + }, + { + "Country": "Cameroon", + "Region": "Sub-Saharan Africa", + "Score": 43.78 + }, + { + "Country": "Canada", + "Region": "Northern America", + "Score": 15.25 + }, + { + "Country": "Cape Verde", + "Region": "Sub-Saharan Africa", + "Score": 20.09 + }, + { + "Country": "Central African Republic", + "Region": "Sub-Saharan Africa", + "Score": 41.92 + }, + { + "Country": "Chad", + "Region": "Sub-Saharan Africa", + "Score": 40.2 + }, + { + "Country": "Chile", + "Region": "Latin America and the Caribbean", + "Score": 27.89 + }, + { + "Country": "China", + "Region": "Eastern Asia", + "Score": 78.72 + }, + { + "Country": "Colombia", + "Region": "Latin America and the Caribbean", + "Score": 43.74 + }, + { + "Country": "Comoros", + "Region": "Sub-Saharan Africa", + "Score": 30.65 + }, + { + "Country": "Congo", + "Region": "Sub-Saharan Africa", + "Score": 38.83 + }, + { + "Country": "Costa Rica", + "Region": "Latin America and the Caribbean", + "Score": 8.76 + }, + { + "Country": "Cote d'Ivoire", + "Region": "Sub-Saharan Africa", + "Score": 28.87 + }, + { + "Country": "Croatia", + "Region": "Southern Europe", + "Score": 27.95 + }, + { + "Country": "Cuba", + "Region": "Latin America and the Caribbean", + "Score": 63.94 + }, + { + "Country": "Cyprus", + "Region": "Western Asia", + "Score": 19.85 + }, + { + "Country": "Czechia", + "Region": "Eastern Europe", + "Score": 23.38 + }, + { + "Country": "Democratic Republic of Congo", + "Region": "Sub-Saharan Africa", + "Score": 48.59 + }, + { + "Country": "Denmark", + "Region": "Northern Europe", + "Score": 8.57 + }, + { + "Country": "Djibouti", + "Region": "Sub-Saharan Africa", + "Score": 78.62 + }, + { + "Country": "Dominican Republic", + "Region": "Latin America and the Caribbean", + "Score": 25.6 + }, + { + "Country": "Ecuador", + "Region": "Latin America and the Caribbean", + "Score": 32.83 + }, + { + "Country": "Egypt", + "Region": "Northern Africa", + "Score": 56.17 + }, + { + "Country": "El Salvador", + "Region": "Latin America and the Caribbean", + "Score": 30.49 + }, + { + "Country": "Equatorial Guinea", + "Region": "Sub-Saharan Africa", + "Score": 55.67 + }, + { + "Country": "Eritrea", + "Region": "Sub-Saharan Africa", + "Score": 81.45 + }, + { + "Country": "Estonia", + "Region": "Northern Europe", + "Score": 15.25 + }, + { + "Country": "Eswatini", + "Region": "Sub-Saharan Africa", + "Score": 46.34 + }, + { + "Country": "Ethiopia", + "Region": "Sub-Saharan Africa", + "Score": 33.63 + }, + { + "Country": "Fiji", + "Region": "Melanesia", + "Score": 27.92 + }, + { + "Country": "Finland", + "Region": "Northern Europe", + "Score": 6.99 + }, + { + "Country": "France", + "Region": "Western Europe", + "Score": 22.6 + }, + { + "Country": "Gabon", + "Region": "Sub-Saharan Africa", + "Score": 38.6 + }, + { + "Country": "Gambia", + "Region": "Sub-Saharan Africa", + "Score": 30.76 + }, + { + "Country": "Georgia", + "Region": "Western Asia", + "Score": 28.64 + }, + { + "Country": "Germany", + "Region": "Western Europe", + "Score": 15.24 + }, + { + "Country": "Ghana", + "Region": "Sub-Saharan Africa", + "Score": 21.33 + }, + { + "Country": "Greece", + "Region": "Southern Europe", + "Score": 29.01 + }, + { + "Country": "Guatemala", + "Region": "Latin America and the Caribbean", + "Score": 38.45 + }, + { + "Country": "Guinea", + "Region": "Sub-Saharan Africa", + "Score": 35.42 + }, + { + "Country": "Guinea-Bissau", + "Region": "Sub-Saharan Africa", + "Score": 32.68 + }, + { + "Country": "Guyana", + "Region": "Latin America and the Caribbean", + "Score": 25.61 + }, + { + "Country": "Haiti", + "Region": "Latin America and the Caribbean", + "Score": 31.12 + }, + { + "Country": "Honduras", + "Region": "Latin America and the Caribbean", + "Score": 49.35 + }, + { + "Country": "Hong Kong", + "Region": "Eastern Asia", + "Score": 30.44 + }, + { + "Country": "Hungary", + "Region": "Eastern Europe", + "Score": 31.76 + }, + { + "Country": "Iceland", + "Region": "Northern Europe", + "Score": 15.37 + }, + { + "Country": "India", + "Region": "Southern Asia", + "Score": 46.56 + }, + { + "Country": "Indonesia", + "Region": "South-eastern Asia", + "Score": 37.4 + }, + { + "Country": "Iran", + "Region": "Southern Asia", + "Score": 72.7 + }, + { + "Country": "Iraq", + "Region": "Western Asia", + "Score": 55.57 + }, + { + "Country": "Ireland", + "Region": "Northern Europe", + "Score": 11.91 + }, + { + "Country": "Israel", + "Region": "Western Asia", + "Score": 30.9 + }, + { + "Country": "Italy", + "Region": "Southern Europe", + "Score": 23.39 + }, + { + "Country": "Jamaica", + "Region": "Latin America and the Caribbean", + "Score": 9.96 + }, + { + "Country": "Japan", + "Region": "Eastern Asia", + "Score": 28.88 + }, + { + "Country": "Jordan", + "Region": "Western Asia", + "Score": 42.89 + }, + { + "Country": "Kazakhstan", + "Region": "Central Asia", + "Score": 50.28 + }, + { + "Country": "Kenya", + "Region": "Sub-Saharan Africa", + "Score": 33.65 + }, + { + "Country": "Kuwait", + "Region": "Western Asia", + "Score": 34.36 + }, + { + "Country": "Kyrgyzstan", + "Region": "Central Asia", + "Score": 30.37 + }, + { + "Country": "Laos", + "Region": "South-eastern Asia", + "Score": 70.56 + }, + { + "Country": "Latvia", + "Region": "Northern Europe", + "Score": 19.26 + }, + { + "Country": "Lebanon", + "Region": "Western Asia", + "Score": 34.93 + }, + { + "Country": "Lesotho", + "Region": "Sub-Saharan Africa", + "Score": 31.61 + }, + { + "Country": "Liberia", + "Region": "Sub-Saharan Africa", + "Score": 33.36 + }, + { + "Country": "Libya", + "Region": "Northern Africa", + "Score": 55.73 + }, + { + "Country": "Liechtenstein", + "Region": "Western Europe", + "Score": 19.49 + }, + { + "Country": "Lithuania", + "Region": "Northern Europe", + "Score": 20.15 + }, + { + "Country": "Luxembourg", + "Region": "Western Europe", + "Score": 17.56 + }, + { + "Country": "Madagascar", + "Region": "Sub-Saharan Africa", + "Score": 28.24 + }, + { + "Country": "Malawi", + "Region": "Sub-Saharan Africa", + "Score": 28.8 + }, + { + "Country": "Malaysia", + "Region": "South-eastern Asia", + "Score": 39.47 + }, + { + "Country": "Maldives", + "Region": "Southern Asia", + "Score": 29.13 + }, + { + "Country": "Mali", + "Region": "Sub-Saharan Africa", + "Score": 33.5 + }, + { + "Country": "Malta", + "Region": "Southern Europe", + "Score": 30.46 + }, + { + "Country": "Mauritania", + "Region": "Sub-Saharan Africa", + "Score": 32.25 + }, + { + "Country": "Mauritius", + "Region": "Sub-Saharan Africa", + "Score": 28.74 + }, + { + "Country": "Mexico", + "Region": "Latin America and the Caribbean", + "Score": 46.71 + }, + { + "Country": "Moldova", + "Region": "Eastern Europe", + "Score": 31.61 + }, + { + "Country": "Mongolia", + "Region": "Eastern Asia", + "Score": 28.97 + }, + { + "Country": "Montenegro", + "Region": "Southern Europe", + "Score": 34.33 + }, + { + "Country": "Morocco", + "Region": "Northern Africa", + "Score": 43.94 + }, + { + "Country": "Mozambique", + "Region": "Sub-Saharan Africa", + "Score": 35.39 + }, + { + "Country": "Myanmar", + "Region": "South-eastern Asia", + "Score": 46.14 + }, + { + "Country": "Namibia", + "Region": "Sub-Saharan Africa", + "Score": 19.72 + }, + { + "Country": "Nepal", + "Region": "Southern Asia", + "Score": 34.62 + }, + { + "Country": "Netherlands", + "Region": "Western Europe", + "Score": 9.67 + }, + { + "Country": "New Zealand", + "Region": "Australia and New Zealand", + "Score": 10.04 + }, + { + "Country": "Nicaragua", + "Region": "Latin America and the Caribbean", + "Score": 39.98 + }, + { + "Country": "Niger", + "Region": "Sub-Saharan Africa", + "Score": 28.44 + }, + { + "Country": "Nigeria", + "Region": "Sub-Saharan Africa", + "Score": 39.69 + }, + { + "Country": "North Korea", + "Region": "Eastern Asia", + "Score": 81.28 + }, + { + "Country": "North Macedonia", + "Region": "Southern Europe", + "Score": 31.67 + }, + { + "Country": "Norway", + "Region": "Northern Europe", + "Score": 6.72 + }, + { + "Country": "Oman", + "Region": "Western Asia", + "Score": 43.37 + }, + { + "Country": "Pakistan", + "Region": "Southern Asia", + "Score": 46.86 + }, + { + "Country": "Palestine", + "Region": "Western Asia", + "Score": 43.18 + }, + { + "Country": "Panama", + "Region": "Latin America and the Caribbean", + "Score": 29.94 + }, + { + "Country": "Papua New Guinea", + "Region": "Melanesia", + "Score": 24.88 + }, + { + "Country": "Paraguay", + "Region": "Latin America and the Caribbean", + "Score": 33.52 + }, + { + "Country": "Peru", + "Region": "Latin America and the Caribbean", + "Score": 31.71 + }, + { + "Country": "Philippines", + "Region": "South-eastern Asia", + "Score": 45.64 + }, + { + "Country": "Poland", + "Region": "Eastern Europe", + "Score": 28.84 + }, + { + "Country": "Portugal", + "Region": "Southern Europe", + "Score": 10.11 + }, + { + "Country": "Qatar", + "Region": "Western Asia", + "Score": 42.6 + }, + { + "Country": "Romania", + "Region": "Eastern Europe", + "Score": 24.91 + }, + { + "Country": "Russia", + "Region": "Eastern Europe", + "Score": 48.71 + }, + { + "Country": "Rwanda", + "Region": "Sub-Saharan Africa", + "Score": 50.66 + }, + { + "Country": "Samoa", + "Region": "Polynesia", + "Score": 19.24 + }, + { + "Country": "Saudi Arabia", + "Region": "Western Asia", + "Score": 62.73 + }, + { + "Country": "Senegal", + "Region": "Sub-Saharan Africa", + "Score": 25.22 + }, + { + "Country": "Serbia", + "Region": "Southern Europe", + "Score": 32.03 + }, + { + "Country": "Seychelles", + "Region": "Sub-Saharan Africa", + "Score": 25.66 + }, + { + "Country": "Sierra Leone", + "Region": "Sub-Saharan Africa", + "Score": 29.61 + }, + { + "Country": "Singapore", + "Region": "South-eastern Asia", + "Score": 55.2 + }, + { + "Country": "Slovakia", + "Region": "Eastern Europe", + "Score": 23.02 + }, + { + "Country": "Slovenia", + "Region": "Southern Europe", + "Score": 23.1 + }, + { + "Country": "Somalia", + "Region": "Sub-Saharan Africa", + "Score": 55.47 + }, + { + "Country": "South Africa", + "Region": "Sub-Saharan Africa", + "Score": 21.59 + }, + { + "Country": "South Korea", + "Region": "Eastern Asia", + "Score": 23.43 + }, + { + "Country": "South Sudan", + "Region": "Sub-Saharan Africa", + "Score": 45.78 + }, + { + "Country": "Spain", + "Region": "Southern Europe", + "Score": 20.44 + }, + { + "Country": "Sri Lanka", + "Region": "Southern Asia", + "Score": 42.2 + }, + { + "Country": "Sudan", + "Region": "Northern Africa", + "Score": 52.93 + }, + { + "Country": "Suriname", + "Region": "Latin America and the Caribbean", + "Score": 16.95 + }, + { + "Country": "Sweden", + "Region": "Northern Europe", + "Score": 7.24 + }, + { + "Country": "Switzerland", + "Region": "Western Europe", + "Score": 10.55 + }, + { + "Country": "Syria", + "Region": "Western Asia", + "Score": 70.63 + }, + { + "Country": "Taiwan", + "Region": "Eastern Asia", + "Score": 23.86 + }, + { + "Country": "Tajikistan", + "Region": "Central Asia", + "Score": 55.52 + }, + { + "Country": "Tanzania", + "Region": "Sub-Saharan Africa", + "Score": 40.69 + }, + { + "Country": "Thailand", + "Region": "South-eastern Asia", + "Score": 45.22 + }, + { + "Country": "Timor", + "Region": "South-eastern Asia", + "Score": 29.11 + }, + { + "Country": "Togo", + "Region": "Sub-Saharan Africa", + "Score": 29.59 + }, + { + "Country": "Tonga", + "Region": "Polynesia", + "Score": 24.59 + }, + { + "Country": "Trinidad and Tobago", + "Region": "Latin America and the Caribbean", + "Score": 21.55 + }, + { + "Country": "Tunisia", + "Region": "Northern Africa", + "Score": 29.53 + }, + { + "Country": "Turkey", + "Region": "Western Asia", + "Score": 49.79 + }, + { + "Country": "Turkmenistan", + "Region": "Central Asia", + "Score": 80.03 + }, + { + "Country": "Uganda", + "Region": "Sub-Saharan Africa", + "Score": 41.19 + }, + { + "Country": "Ukraine", + "Region": "Eastern Europe", + "Score": 32.96 + }, + { + "Country": "United Arab Emirates", + "Region": "Western Asia", + "Score": 43.13 + }, + { + "Country": "United Kingdom", + "Region": "Northern Europe", + "Score": 21.59 + }, + { + "Country": "United States", + "Region": "Northern America", + "Score": 23.93 + }, + { + "Country": "Uruguay", + "Region": "Latin America and the Caribbean", + "Score": 16.38 + }, + { + "Country": "Uzbekistan", + "Region": "Central Asia", + "Score": 50.74 + }, + { + "Country": "Venezuela", + "Region": "Latin America and the Caribbean", + "Score": 47.6 + }, + { + "Country": "Vietnam", + "Region": "South-eastern Asia", + "Score": 78.46 + }, + { + "Country": "Yemen", + "Region": "Western Asia", + "Score": 62.35 + }, + { + "Country": "Zambia", + "Region": "Sub-Saharan Africa", + "Score": 38.21 + }, + { + "Country": "Zimbabwe", + "Region": "Sub-Saharan Africa", + "Score": 43.12 + } +] diff --git a/src/components/Table/demo/richestWomen.json b/src/components/Table/demo/richestWomen.json new file mode 100644 index 0000000..d3c9083 --- /dev/null +++ b/src/components/Table/demo/richestWomen.json @@ -0,0 +1,42 @@ +[ + { + "Name": "Francoise Bettencourt Meyers", + "Net worth (in billions)": 74.8 + }, + { + "Name": "Alice Walton", + "Net worth (in billions)": 65.3 + }, + { + "Name": "Julia Koch", + "Net worth (in billions)": 60 + }, + { + "Name": "MacKenzie Scott", + "Net worth (in billions)": 43.6 + }, + { + "Name": "Jacqueline Mars", + "Net worth (in billions)": 31.7 + }, + { + "Name": "Gina Rinehart", + "Net worth (in billions)": 30.2 + }, + { + "Name": "Miriam Adelson", + "Net worth (in billions)": 27.5 + }, + { + "Name": "Susanne Klatten", + "Net worth (in billions)": 24.3 + }, + { + "Name": "Iris Fontbona", + "Net worth (in billions)": 22.8 + }, + { + "Name": "Abigail Johnson", + "Net worth (in billions)": 21.2 + } +] diff --git a/src/components/Table/utils.ts b/src/components/Table/utils.ts new file mode 100644 index 0000000..51b36a7 --- /dev/null +++ b/src/components/Table/utils.ts @@ -0,0 +1,122 @@ +type FilterableDatum> = T & { + searchStr: string; +}; + +export function filterArray>( + data: FilterableDatum[], + searchText: string, + filterField: keyof FilterableDatum, + filterValue: FilterableDatum[keyof FilterableDatum] +) { + if (searchText) { + data = data.filter((item) => { + return item.searchStr.includes(searchText.toLowerCase()); + }); + } + + if (filterValue) { + data = data.filter((item) => { + if (!filterField) return true; // or handle the undefined case as appropriate + + return item[filterField] === filterValue; + }); + } + + return data; +} +export function paginateArray( + array: T[], + pageSize: number, + pageNumber: number +) { + return array.slice((pageNumber - 1) * pageSize, pageNumber * pageSize); +} + +/** + * We specify the output type here by adding `string` to the union because we want to explicitly define the output array as accepting strings. + * + * This is to get rid of the type error from `attrList.unshift('All')` + */ +function uniqueAttr(array: T[], attr: keyof T): (T[keyof T] | string)[] { + return array.map((e) => e[attr]).filter(unique); +} + +function unique(value: T, index: number, array: T[]) { + return array.indexOf(value) === index; +} + +export function getOptions(data: T[], attr: keyof T) { + // Get all the unique values in the provided field. Sort it. + const attrList = uniqueAttr(data, attr).sort((a, b) => { + // Throw errors if a and b are not strings. + // a and b should be strings since they are keys of T. + if (typeof a !== 'string' || typeof b !== 'string') { + throw new Error(`Expected string, got ${typeof a} and ${typeof b}`); + } + + return a.localeCompare(b); + }); + + // Tack 'All' at the start of `attrList`, making it the first option. + attrList.unshift('All'); + + // Convert the list into Option typed objects ready for our Select component + return attrList.map((a) => ({ text: a, value: a })); +} +interface SortableItem { + [key: string]: unknown; // Or more specific types if known +} + +/** + * Sorts an array of objects based on a specified column and direction. + */ +export function sortArray( + /** The array to sort. */ + array: T[], + /** The column to sort by. */ + column: keyof T, + /** The sorting direction ('ascending' or 'descending'). */ + direction: 'ascending' | 'descending', + /** Whether or not sorting is turned on */ + sortable: boolean +) { + if (!sortable) return array; + + const sorted = [...array].sort((a, b) => { + if (a[column] < b[column]) { + return direction === 'ascending' ? -1 : 1; + } else if (a[column] > b[column]) { + return direction === 'ascending' ? 1 : -1; + } else { + return 0; + } + }); + + return sorted; +} + +export type Formatter = (value: T) => string; + +export type FieldFormatters = { + [K in keyof T]?: Formatter; +}; +/** + * Formats a value based on a field and a dictionary of formatters. + */ +export function formatValue>( + /** The object containing the field. */ + item: FilterableDatum, + /** The field to format. */ + field: keyof T, + /** An optional dictionary of formatters. */ + fieldFormatters?: FieldFormatters +) { + const value = item[field]; + + if (fieldFormatters && field in fieldFormatters && fieldFormatters[field]) { + const formatter = fieldFormatters[field]; + return formatter(value); + } else { + return value; + } +} diff --git a/src/components/Theme/@types/component.ts b/src/components/Theme/@types/component.ts new file mode 100644 index 0000000..74de2bd --- /dev/null +++ b/src/components/Theme/@types/component.ts @@ -0,0 +1,54 @@ +export interface Colour { + background: string; + 'text-primary': string; + 'text-secondary': string; + accent: string; + 'brand-logo': string; + 'brand-rules': string; + 'brand-shadow': string; +} + +export interface FontFamily { + serif: string; + 'sans-serif': string; + monospace: string; + hed: string; + subhed: string; + body: string; + note: string; +} + +export interface FontSize { + xxs: string; + xs: string; + sm: string; + base: string; + lg: string; + xl: string; + '2xl': string; + '3xl': string; + '4xl': string; + '5xl': string; + '6xl': string; +} + +export interface Font { + family: FontFamily; + size: FontSize; +} + +export interface CustomFont { + family?: Partial; + size?: Partial; +} + +export interface ThemeConfig { + colour: Colour; + font: Font; +} + +export interface CustomThemeConfig { + colour?: Partial; + font?: Partial; + [customProperty: string]: unknown; +} diff --git a/src/components/Theme/Theme.mdx b/src/components/Theme/Theme.mdx new file mode 100644 index 0000000..c821f5c --- /dev/null +++ b/src/components/Theme/Theme.mdx @@ -0,0 +1,164 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as ThemeStories from './Theme.stories.svelte'; + + + +# Theme + +The `Theme` component wraps your page content and uses [CSS variables](../?path=/docs/scss-css-variables--page) to set major colour and typography styles for your page. All the components from this library that are added to your page will use the CSS variables set by `Theme`. + +Use the [theme builder](?path=/docs/components-theming-theme-builder--docs) to test custom themes. + +```svelte + + + + + +``` + +> In the graphics kit, the `Theme` is set in both `pages/+page.svelte` and in `App.svelte`. + + + +## Custom theme + +You can customise your page's theme in two ways: + +- Choose the `base` theme, either `light` or `dark` +- Pass a custom theme object to the `theme` prop, which will override styles in the `base` theme. + +Use the [theme builder](?path=/docs/components-theming-theme-builder--docs) to see what properties you can customise. + +```svelte + + + +``` + +> **Note:** The `Theme` component only styles child components or elements, so if you're changing the background colour of your page, make sure to also set the `background-color` on your `body` element in global SCSS. +> +> ```scss +> // global.scss +> body { +> background-color: #2e3440; +> } +> ``` + + + +## Custom font + +To use typefaces other than the defaults provided by the graphics kit, download the font files from services such as [Google Fonts](https://fonts.google.com/) or [Adobe Typekit](https://fonts.adobe.com/). Make a folder called `fonts` inside `statics/` and put the font file -- for example, `IndieFlower-Regular.ttf` downloaded from [Google Fonts](https://fonts.google.com/share?selection.family=Indie+Flower) -- in `statics/fonts/`. + +Then, declare it as a `@font-face` in `global.scss`: + +```scss +/* global.scss in the graphics kit */ +@font-face { + // If you're unsure of the font-family name, + // click on "Get embed code" on the Google font page and check the CSS class. + font-family: 'Indie Flower'; + + // Path to the font file. Change format depending on the font file type. + src: url('/fonts/IndieFlower-Regular.ttf') format('truetype'); + font-weight: normal; // Optional + font-style: normal; // Optional +} +``` + +Finally, pass the font to the appropriate text type in `Theme`: + +```svelte + + + +``` + + + +## Background patterns + +To use a background pattern or image, set the background colour property in `Theme` to `transparent`: + +```svelte + + + +``` + +Then in `global.scss`, set your image, which should be stored in `statics/images/`, as `background-image`: + +```scss +/* global.scss */ +body { + background-image: url('/images/my-pattern.png'); +} +``` + +You may also want to override the background on the header nav if it conflicts with your background, especially the dropdown menu: + +```scss +/* global.scss +Main nav container */ +.nav-container .inner { + background: darkblue !important; + /* Dropdown menu */ + .dropdown { + background: darkblue !important; + } +} +/* Mobile nav overlay */ +header + .overlay { + background: darkblue !important; +} +``` + + + +## Inheritance + +Styles that use `Theme`'s CSS variables will always use those set by the nearest parent `Theme`. That lets you change the theme for parts of your page by simply wrapping that bit in a new `Theme` with different styles. + +The demo below shows a more complex example of nesting themes, but more likely you'll so something like this: + +```svelte + + + + + + + + + +``` + + diff --git a/src/components/Theme/Theme.stories.svelte b/src/components/Theme/Theme.stories.svelte new file mode 100644 index 0000000..554fb83 --- /dev/null +++ b/src/components/Theme/Theme.stories.svelte @@ -0,0 +1,150 @@ + + + + + +
+ + + +
+
+ + + + + + + + + +
+ + +
+
+
+ + +
+ + + + + +
+
+ + + +
+

Theme

+ +
+

Sub-theme

+ +
+

Sub-sub

+
+
+ +
+

Sub-sub sibling

+
+
+
+
+
+
+
+ + diff --git a/src/components/Theme/Theme.svelte b/src/components/Theme/Theme.svelte new file mode 100644 index 0000000..dbea6cb --- /dev/null +++ b/src/components/Theme/Theme.svelte @@ -0,0 +1,55 @@ + + + + + +
+ +
+ + {@render children()} +
+
diff --git a/src/components/Theme/demo/ThemedPage.svelte b/src/components/Theme/demo/ThemedPage.svelte new file mode 100644 index 0000000..57c3236 --- /dev/null +++ b/src/components/Theme/demo/ThemedPage.svelte @@ -0,0 +1,36 @@ + + +
+ + + +
+
+ +
+ + diff --git a/src/components/Theme/themes/common.js b/src/components/Theme/themes/common.js new file mode 100644 index 0000000..65af9e2 --- /dev/null +++ b/src/components/Theme/themes/common.js @@ -0,0 +1,32 @@ +/** @type {Omit} */ +/* Generated from +https://www.fluid-type-scale.com/calculate?minFontSize=18&minWidth=320&minRatio=1.125&maxFontSize=21&maxWidth=1280&maxRatio=1.25&steps=xxs%2Cxs%2Csm%2Cbase%2Clg%2Cxl%2C2xl%2C3xl%2C4xl%2C5xl%2C6xl&baseStep=base&prefix=&decimals=2&useRems=on&remValue=16&previewFont=Noto+Sans&previewText=Almost+before+we+knew+it%2C+we+had+left+the+ground&previewWidth=0 +*/ + +export default { + font: { + family: { + serif: '"Newsreader Text", serif', + 'sans-serif': 'Knowledge, sans-serif', + monospace: + '"Droid Sans Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace', + hed: 'var(--theme-font-family-sans-serif)', + subhed: 'var(--theme-font-family-sans-serif)', + body: 'var(--theme-font-family-serif)', + note: 'var(--theme-font-family-sans-serif)', + }, + size: { + xxs: 'clamp(0.79rem, -0.2vw + 0.83rem, 0.67rem)', + xs: 'clamp(0.89rem, -0.08vw + 0.91rem, 0.84rem)', + sm: 'clamp(1rem, 0.08vw + 0.98rem, 1.05rem)', + base: 'clamp(1.13rem, 0.31vw + 1.06rem, 1.31rem)', + lg: 'clamp(1.27rem, 0.63vw + 1.14rem, 1.64rem)', + xl: 'clamp(1.42rem, 1.04vw + 1.21rem, 2.05rem)', + '2xl': 'clamp(1.6rem, 1.6vw + 1.28rem, 2.56rem)', + '3xl': 'clamp(1.8rem, 2.34vw + 1.33rem, 3.2rem)', + '4xl': 'clamp(2.03rem, 3.3vw + 1.37rem, 4.01rem)', + '5xl': 'clamp(2.28rem, 4.54vw + 1.37rem, 5.01rem)', + '6xl': 'clamp(2.57rem, 6.15vw + 1.33rem, 6.26rem)', + }, + }, +}; diff --git a/src/components/Theme/themes/dark.js b/src/components/Theme/themes/dark.js new file mode 100644 index 0000000..f5d6a33 --- /dev/null +++ b/src/components/Theme/themes/dark.js @@ -0,0 +1,15 @@ +import common from './common.js'; + +/** @type {import('../@types/component').ThemeConfig} */ +export default { + ...common, + colour: { + background: '#2e3440', + 'text-primary': '#ffffff', + 'text-secondary': 'rgb(255 255 255 / 60%)', + accent: '#ef3c2a', + 'brand-logo': '#ffffff', + 'brand-rules': 'rgb(255 255 255 / 25%)', + 'brand-shadow': 'rgb(255 255 255 / 10%)', + }, +}; diff --git a/src/components/Theme/themes/light.js b/src/components/Theme/themes/light.js new file mode 100644 index 0000000..5749c7b --- /dev/null +++ b/src/components/Theme/themes/light.js @@ -0,0 +1,15 @@ +import common from './common.js'; + +/** @type {import('../@types/component').ThemeConfig} */ +export default { + ...common, + colour: { + background: '#ffffff', + 'text-primary': '#404040', + 'text-secondary': '#666666', + accent: ' #d64000', + 'brand-logo': '#d64000', + 'brand-rules': '#d0d0d0', + 'brand-shadow': 'rgba(64, 64, 64, .08)', + }, +}; diff --git a/src/components/Theme/utils/flatten.ts b/src/components/Theme/utils/flatten.ts new file mode 100644 index 0000000..ae84fcf --- /dev/null +++ b/src/components/Theme/utils/flatten.ts @@ -0,0 +1,46 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function isBuffer(obj: any): boolean { + return ( + obj && + obj.constructor && + typeof obj.constructor.isBuffer === 'function' && + obj.constructor.isBuffer(obj) + ); +} + +const transformKey = (key: string): string => key.replace(/[^a-z0-9-]/gi, ''); + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export default function flatten>(target: T) { + const delimiter = '-'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const output: Record = {}; + + function step( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + object: Record, + prev?: string, + currentDepth = 1 + ): void { + Object.keys(object).forEach(function (key) { + const value = object[key]; + const isArray = Array.isArray(value); + const type = Object.prototype.toString.call(value); + const isbuffer = isBuffer(value); + const isObject = type === '[object Object]' || type === '[object Array]'; + + const newKey = + prev ? prev + delimiter + transformKey(key) : transformKey(key); + + if (!isArray && !isbuffer && isObject && Object.keys(value).length) { + return step(value, newKey, currentDepth + 1); + } + + output[newKey] = value; + }); + } + + step(target); + + return output; +} diff --git a/src/components/Theme/utils/merge.ts b/src/components/Theme/utils/merge.ts new file mode 100644 index 0000000..7a90c23 --- /dev/null +++ b/src/components/Theme/utils/merge.ts @@ -0,0 +1,31 @@ +import type { ThemeConfig, CustomThemeConfig } from '../@types/component'; + +function isObject(item: unknown): item is Record { + return item !== null && typeof item === 'object' && !Array.isArray(item); +} + +/** + * Deep merges theme objects. + */ +export default function merge>( + target: T, + ...sources: (ThemeConfig | CustomThemeConfig)[] +): T { + if (!sources.length) return target; + const source = sources.shift(); + + if (isObject(target) && isObject(source)) { + for (const key in source) { + if (isObject(source[key])) { + if (!target[key]) Object.assign(target, { [key]: {} }); + merge( + target[key] as Record, + source[key] as Record + ); + } else { + Object.assign(target, { [key]: source[key] }); + } + } + } + return merge(target, ...sources); +} diff --git a/src/components/TileMap/TileMap.mdx b/src/components/TileMap/TileMap.mdx new file mode 100644 index 0000000..cee4dbf --- /dev/null +++ b/src/components/TileMap/TileMap.mdx @@ -0,0 +1,281 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as TileMapStories from './TileMap.stories.svelte'; + + + +# TileMap + +Easily add an interactive map to your page using MapLibre GL and PMTiles. + +```svelte + + + +``` + +The TileMap component uses [MapLibre GL JS](https://maplibre.org/) and [PMTiles](https://protomaps.com/docs/pmtiles) for efficient, interactive mapping. It automatically configures the PMTiles protocol and uses the Reuters Protomaps style by default. + + + +## Globe view + +Use the `projection` prop to display a 3D globe. The projection accepts a [ProjectionSpecification](https://maplibre.org/maplibre-style-spec/types/#projectiondefinition) object: + + + +```svelte + +``` + +## Non-interactive mode + +Disable interaction for static maps: + + + +## Adding GeoJSON layers + +Use the `TileMapLayer` component to add GeoJSON data to your map. You can pass GeoJSON data directly or fetch it from a URL. Layer rendering order will directly correspond to the order in which you add the layers in the code. + + + +### Basic example with local data + +```svelte + + + + + + + + + +``` + +### Fetching GeoJSON from a URL + +You can also pass a URL string to fetch GeoJSON data: + +```svelte + + + +``` + +### Adding point markers + +```svelte + + + + + + + + + +``` + +### TileMapLayer Props + +- **id**: `string` (required) - Unique identifier for the layer +- **data**: `object | string` (required) - GeoJSON data or URL to fetch from +- **type**: `'fill' | 'line' | 'circle' | 'symbol' | 'fill-extrusion' | 'raster' | 'background' | 'heatmap' | 'hillshade'` - Layer type (default: `'fill'`) +- **paint**: `Record` - Paint properties for the layer +- **layout**: `Record` - Layout properties for the layer +- **beforeId**: `string` - Layer ID to insert before (for ordering) +- **minZoom**: `number` - Minimum zoom level to display layer +- **maxZoom**: `number` - Maximum zoom level to display layer +- **filter**: `unknown[]` - Filter expression for the layer + +### Multiple layers example + +You can combine multiple layers to create rich visualizations: + +```svelte + + + + + + + + + + + + + +``` + +## Advanced usage + +For more control over the map, you can use the `onMapReady` callback to access the MapLibre GL instance: + +```svelte + + + +``` + +## Props + +- **center**: `[longitude, latitude]` - Map center coordinates (default: `[0, 0]`) +- **zoom**: `number` - Initial zoom level (default: `2`) +- **minZoom**: `number` - Minimum zoom level (default: `0`) +- **maxZoom**: `number` - Maximum zoom level (default: `22`) +- **interactive**: `boolean` - Enable interactive controls (default: `true`) +- **styleUrl**: `string` - Map style URL (default: Reuters Protomaps style) +- **height**: `string` - Map height in CSS units (default: `'500px'`) +- **width**: `ContainerWidth` - Width within the text well (default: `'normal'`) +- **onMapReady**: `(map: maplibregl.Map) => void` - Callback when map is ready diff --git a/src/components/TileMap/TileMap.stories.svelte b/src/components/TileMap/TileMap.stories.svelte new file mode 100644 index 0000000..7464e34 --- /dev/null +++ b/src/components/TileMap/TileMap.stories.svelte @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/components/TileMap/TileMap.svelte b/src/components/TileMap/TileMap.svelte new file mode 100644 index 0000000..6d5f5cd --- /dev/null +++ b/src/components/TileMap/TileMap.svelte @@ -0,0 +1,199 @@ + + + + + + +
+
+ {#if children} + {@render children()} + {/if} +
+
+ + diff --git a/src/components/TileMap/TileMapLayer.svelte b/src/components/TileMap/TileMapLayer.svelte new file mode 100644 index 0000000..d0abe6c --- /dev/null +++ b/src/components/TileMap/TileMapLayer.svelte @@ -0,0 +1,211 @@ + + diff --git a/src/components/ToolsHeader/ToolsHeader.mdx b/src/components/ToolsHeader/ToolsHeader.mdx new file mode 100644 index 0000000..1247302 --- /dev/null +++ b/src/components/ToolsHeader/ToolsHeader.mdx @@ -0,0 +1,23 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as ToolsHeaderStories from './ToolsHeader.stories.svelte'; + + + +# ToolsHeader + +The `ToolsHeader` component adds a header with the Reuters Graphics logo for internal tooling sites. + +> **Note:** Don't use this component for public pages. + +```svelte + + + + + +``` + + diff --git a/src/components/ToolsHeader/ToolsHeader.stories.svelte b/src/components/ToolsHeader/ToolsHeader.stories.svelte new file mode 100644 index 0000000..1c46b89 --- /dev/null +++ b/src/components/ToolsHeader/ToolsHeader.stories.svelte @@ -0,0 +1,22 @@ + + + +
+ +
+
+ + diff --git a/src/components/ToolsHeader/ToolsHeader.svelte b/src/components/ToolsHeader/ToolsHeader.svelte new file mode 100644 index 0000000..2d68b00 --- /dev/null +++ b/src/components/ToolsHeader/ToolsHeader.svelte @@ -0,0 +1,96 @@ + + + +
+
+ + + +
+ + + {#if children} + + {/if} +
+ + diff --git a/src/components/Video/Video.mdx b/src/components/Video/Video.mdx new file mode 100644 index 0000000..3cd7ccb --- /dev/null +++ b/src/components/Video/Video.mdx @@ -0,0 +1,155 @@ +import { Meta, Canvas } from '@storybook/blocks'; + +import * as VideoStories from './Video.stories.svelte'; + + + +# Video + +The `Video` component adds a video with various controls to your page such as: + +- Play/pause button +- Autoplay controls, i.e. whether the video plays when it comes into view or on page load +- Looping +- Audio controls +- Text elements such as notes and titles + +```svelte + + +