From 4b3f93d9d05eca4f43151c94422b6b5ddff83273 Mon Sep 17 00:00:00 2001 From: David Di Biase <1168397+davedbase@users.noreply.github.com> Date: Fri, 2 Oct 2026 13:02:20 -0400 Subject: [PATCH] feat(@lucide/solid): Support for Solid 2.0 RC (#4751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Updates needed to support Solid 2 * Switch to the next tag * feat(packages): add `@lucide/solid` package for Solid 2 Solid 2's API is a breaking change from Solid 1 and is still an RC, so `lucide-solid` stays on Solid 1 (`solid-js: ^1.4.7`) untouched and Solid 2 support ships as a new `packages/solid` package named `@lucide/solid` — the same scheme already used by `@lucide/svelte` and `@lucide/angular`. The package is a copy of `lucide-solid` on the `@lucide/shared` build architecture, ported to Solid 2: - `splitProps` -> `omit`, `solid-js/web` -> `@solidjs/web`, `JSXElement` -> `Element`, `Context.Provider` -> `` - `jsxImportSource` is `@solidjs/web` in tsconfig, the esbuild step and `ts.createProgram`; rollup externals drop the removed `solid-js/store` - `vite-plugin-solid` -> `@solidjs/vite-plugin` - tests keep upstream's coverage with two Solid 2 adaptations: boolean attribute literals must be strings (`aria-hidden="false"`), and writes are batched so the reactivity tests need a `flush()` before asserting Rendered output is unchanged — the snapshots are byte-identical to `lucide-solid`'s. Co-Authored-By: Claude Opus 5 * docs(solid): fix React leftovers in the Solid guide The Solid guide was derived from the React guide and three things were not carried across: - `advanced/typescript.md` still told readers the types are for "a TypeScript React project" - its `LucideIcon` example kept React's destructured-props signature. The `: ButtonProps` annotation had also been dropped in the copy, so `ButtonProps` was declared but unused and the parameters were implicitly `any`. Destructuring props breaks reactivity in Solid — verified: with `({ icon: Icon, label })` a changing `label` never reaches the DOM, while `props.label` updates correctly. - `advanced/aliased-names.md` had an orphaned `###` heading; its parent `## Choosing import name style` was dropped during the conversion because it documents React-only subpath exports. Co-Authored-By: Claude Opus 5 * docs: type the shared Sandpack wrapper with `SandpackProps` The base Sandpack wrapper declared its props as `FunctionalComponent` with `LucideProps` imported from `@lucide/vue`, which has nothing to do with a Sandpack embed. None of the props the markdown plugin actually passes (`template`, `files`, `options`, `customSetup`, `theme`) were declared, so they only reached the inner `` via Vue's fallthrough attributes. Declare `SandpackProps` from `sandpack-vue3` instead and forward them explicitly. This also removes the `@lucide/vue` import that made every framework guide — including the Solid one, which uses this wrapper directly — appear to reference the Vue package. Verified with a full `vitepress build`: each framework guide's chunk still carries its own template (react/vue/vite-svelte/vanilla/ vite-solid) and all five props reach the component. Co-Authored-By: Claude Opus 5 * docs(solid): document the Solid 2 flavour in the getting started guide The Solid guide teaches `lucide-solid` throughout (64 references), so the one-line note about `@lucide/solid` left Solid 2 readers on a page whose every install command and live example is Solid 1 — and the packages list points `@lucide/solid` at this same page. Replace that note with a "Using Solid 2?" callout holding its own tabbed install group, the import-specifier swap, and a table of the Solid 2 changes that affect code written around Lucide (`@solidjs/web`, `jsxImportSource`, `splitProps` -> `omit`, ``), linking out to Solid's own migration guide for the rest. The claim that both packages expose the same components and props is checked, not assumed: `dist/types/lucide-solid.d.ts` is identical between the two packages, and the only differences anywhere in the public type surface are Solid's own renames (the `JSX` namespace source and `JSXElement` -> `Element`). Keeps one guide section for both packages, matching how upstream handles the two Svelte packages. Co-Authored-By: Claude Opus 5 * feat(solid): port lucide-solid to Solid 2 - Icon/context/types use Solid 2 APIs: omit() instead of splitProps(), Dynamic and JSX types from @solidjs/web. - solid-js / @solidjs/web 2.0 (rc) as peer and dev dependencies, babel-preset-solid 2; rollup and tsconfig updated to match. Co-Authored-By: Claude Opus 5.5 (1M context) * Add integration test * Update rollup file * Fix tests * Revert lucide-solid changes * update lockfile * Fix docs * Format code --------- Co-authored-by: Claude Opus 5 Co-authored-by: Eric --- .github/labeler.yml | 1 + .github/workflows/release.yml | 1 + .github/workflows/solid-2.yml | 71 ++ .prettierignore | 1 + .../api/gh-icon/diff/[...data].get.tsx | 1 - .../api/gh-icon/symmetry/[...data].get.tsx | 1 - docs/.vitepress/api/icons/[iconName].get.ts | 11 +- docs/.vitepress/data/packageData.json | 22 +- docs/.vitepress/lib/SvgPreview/index.tsx | 13 +- .../theme/components/editors/Sandpack.vue | 8 +- docs/guide/installation.md | 1 + docs/guide/solid/advanced/aliased-names.md | 2 +- docs/guide/solid/advanced/typescript.md | 8 +- docs/guide/solid/getting-started.md | 46 ++ docs/package.json | 2 + eslint.config.js | 1 + integrations/lucide-solid-2/README.md | 36 + .../lucide-solid-2/vite/file-routes.d.ts | 71 ++ integrations/lucide-solid-2/vite/package.json | 29 + integrations/lucide-solid-2/vite/src/App.tsx | 6 + .../lucide-solid-2/vite/src/Document.tsx | 19 + .../lucide-solid-2/vite/src/IconShowcase.tsx | 31 + .../lucide-solid-2/vite/src/router.ts | 7 + .../lucide-solid-2/vite/src/routes/about.tsx | 10 + .../lucide-solid-2/vite/src/routes/index.tsx | 10 + .../lucide-solid-2/vite/src/vite-env.d.ts | 2 + .../vite/tests/icons.browser.spec.tsx | 46 ++ .../vite/tsconfig.declarations.json | 8 + .../lucide-solid-2/vite/tsconfig.json | 18 + .../lucide-solid-2/vite/vite.config.ts | 22 + package.json | 1 + packages/solid/README.md | 89 +++ packages/solid/package.json | 94 +++ packages/solid/rollup.config.mjs | 137 ++++ packages/solid/scripts/exportTemplate.mts | 33 + packages/solid/src/Icon.tsx | 75 ++ packages/solid/src/aliases/index.ts | 3 + packages/solid/src/context.tsx | 37 + packages/solid/src/defaultAttributes.ts | 1 + packages/solid/src/icons/.gitkeep | 1 + packages/solid/src/lucide-solid.ts | 7 + packages/solid/src/types.ts | 33 + packages/solid/tests/Icon.spec.tsx | 154 +++++ .../tests/__snapshots__/Icon.spec.tsx.snap | 34 + .../tests/__snapshots__/context.spec.tsx.snap | 26 + .../__snapshots__/lucide-solid.spec.tsx.snap | 123 ++++ packages/solid/tests/context.spec.tsx | 121 ++++ packages/solid/tests/lucide-solid.spec.tsx | 90 +++ packages/solid/tests/setupVitest.js | 10 + packages/solid/tests/testIconNodes.ts | 22 + packages/solid/tsconfig.json | 22 + packages/solid/vitest.config.mts | 11 + pnpm-lock.yaml | 644 +++++++++++++++++- 53 files changed, 2230 insertions(+), 43 deletions(-) create mode 100644 .github/workflows/solid-2.yml create mode 100644 integrations/lucide-solid-2/README.md create mode 100644 integrations/lucide-solid-2/vite/file-routes.d.ts create mode 100644 integrations/lucide-solid-2/vite/package.json create mode 100644 integrations/lucide-solid-2/vite/src/App.tsx create mode 100644 integrations/lucide-solid-2/vite/src/Document.tsx create mode 100644 integrations/lucide-solid-2/vite/src/IconShowcase.tsx create mode 100644 integrations/lucide-solid-2/vite/src/router.ts create mode 100644 integrations/lucide-solid-2/vite/src/routes/about.tsx create mode 100644 integrations/lucide-solid-2/vite/src/routes/index.tsx create mode 100644 integrations/lucide-solid-2/vite/src/vite-env.d.ts create mode 100644 integrations/lucide-solid-2/vite/tests/icons.browser.spec.tsx create mode 100644 integrations/lucide-solid-2/vite/tsconfig.declarations.json create mode 100644 integrations/lucide-solid-2/vite/tsconfig.json create mode 100644 integrations/lucide-solid-2/vite/vite.config.ts create mode 100644 packages/solid/README.md create mode 100644 packages/solid/package.json create mode 100644 packages/solid/rollup.config.mjs create mode 100644 packages/solid/scripts/exportTemplate.mts create mode 100644 packages/solid/src/Icon.tsx create mode 100644 packages/solid/src/aliases/index.ts create mode 100644 packages/solid/src/context.tsx create mode 100644 packages/solid/src/defaultAttributes.ts create mode 100644 packages/solid/src/icons/.gitkeep create mode 100644 packages/solid/src/lucide-solid.ts create mode 100644 packages/solid/src/types.ts create mode 100644 packages/solid/tests/Icon.spec.tsx create mode 100644 packages/solid/tests/__snapshots__/Icon.spec.tsx.snap create mode 100644 packages/solid/tests/__snapshots__/context.spec.tsx.snap create mode 100644 packages/solid/tests/__snapshots__/lucide-solid.spec.tsx.snap create mode 100644 packages/solid/tests/context.spec.tsx create mode 100644 packages/solid/tests/lucide-solid.spec.tsx create mode 100644 packages/solid/tests/setupVitest.js create mode 100644 packages/solid/tests/testIconNodes.ts create mode 100644 packages/solid/tsconfig.json create mode 100644 packages/solid/vitest.config.mts diff --git a/.github/labeler.yml b/.github/labeler.yml index 39a681277..6029f5e00 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -82,6 +82,7 @@ - changed-files: - any-glob-to-any-file: - 'packages/lucide-solid/*' + - 'packages/solid/*' # For changes in the Lucide astro package 🚀 astro package: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 241128acf..01955f2f9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,6 +53,7 @@ jobs: '@lucide/angular', '@lucide/astro', '@lucide/icons', + '@lucide/solid', '@lucide/svelte', '@lucide/vue', ] diff --git a/.github/workflows/solid-2.yml b/.github/workflows/solid-2.yml new file mode 100644 index 000000000..f65ffa092 --- /dev/null +++ b/.github/workflows/solid-2.yml @@ -0,0 +1,71 @@ +name: Lucide Solid 2 Checks + +on: + push: + branches: + - next + pull_request: + paths: + - packages/solid/** + - packages/shared/** + - tools/build-icons/** + - tools/rollup-plugins/** + - integrations/lucide-solid-2/** + - package.json + - pnpm-workspace.yaml + - pnpm-lock.yaml + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + cache: 'pnpm' + node-version-file: 'package.json' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build + run: pnpm --filter @lucide/solid build + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + cache: 'pnpm' + node-version-file: 'package.json' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Test + run: pnpm --filter @lucide/solid test + + integration: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + cache: 'pnpm' + node-version-file: 'package.json' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Install Chromium + run: pnpm --filter @lucide/integration-solid-2-vite exec playwright install --with-deps chromium + + - name: Run integration checks + run: pnpm test:integrations:solid-2 diff --git a/.prettierignore b/.prettierignore index 88be62c65..e8a4863bb 100644 --- a/.prettierignore +++ b/.prettierignore @@ -23,6 +23,7 @@ packages/svelte/.svelte-kit integrations/**/.react-router integrations/**/next-env.d.ts integrations/**/routeTree.gen.ts +integrations/**/file-routes.d.ts integrations/**/.vitest-attachments integrations/**/__screenshots__ integrations/**/.output diff --git a/docs/.vitepress/api/gh-icon/diff/[...data].get.tsx b/docs/.vitepress/api/gh-icon/diff/[...data].get.tsx index 34d15b684..900c4f11c 100644 --- a/docs/.vitepress/api/gh-icon/diff/[...data].get.tsx +++ b/docs/.vitepress/api/gh-icon/diff/[...data].get.tsx @@ -41,7 +41,6 @@ export default eventHandler((event) => { diff --git a/docs/.vitepress/api/gh-icon/symmetry/[...data].get.tsx b/docs/.vitepress/api/gh-icon/symmetry/[...data].get.tsx index 08033bd4d..441704f8e 100644 --- a/docs/.vitepress/api/gh-icon/symmetry/[...data].get.tsx +++ b/docs/.vitepress/api/gh-icon/symmetry/[...data].get.tsx @@ -48,7 +48,6 @@ export default eventHandler((event) => { diff --git a/docs/.vitepress/api/icons/[iconName].get.ts b/docs/.vitepress/api/icons/[iconName].get.ts index 733eeb5ea..ec8ab0b83 100644 --- a/docs/.vitepress/api/icons/[iconName].get.ts +++ b/docs/.vitepress/api/icons/[iconName].get.ts @@ -18,11 +18,12 @@ export default eventHandler((event) => { return sendError(event, error); } - const width = getQuery(event).width || undefined; - const height = getQuery(event).height || undefined; - const color = getQuery(event).color || undefined; - const strokeWidth = getQuery(event).strokeWidth || undefined; - const background = getQuery(event).background || undefined; + const query = getQuery>(event); + const width = query.width || undefined; + const height = query.height || undefined; + const color = query.color || undefined; + const strokeWidth = query.strokeWidth || undefined; + const background = query.background || undefined; const LucideIcon = createLucideIcon(params.iconName, iconNode); diff --git a/docs/.vitepress/data/packageData.json b/docs/.vitepress/data/packageData.json index 9dd193f59..6009b6f2e 100644 --- a/docs/.vitepress/data/packageData.json +++ b/docs/.vitepress/data/packageData.json @@ -85,8 +85,26 @@ } ] }, - "lucide-react-native": { + "@lucide/solid": { "order": 5, + "icon": "solid", + "docsAlias": "solid", + "packageDirname": "solid", + "shields": [ + { + "alt": "npm", + "src": "https://img.shields.io/npm/v/@lucide/solid", + "href": "https://www.npmjs.com/package/@lucide/solid" + }, + { + "alt": "npm", + "src": "https://img.shields.io/npm/dw/@lucide/solid", + "href": "https://www.npmjs.com/package/@lucide/solid" + } + ] + }, + "lucide-react-native": { + "order": 6, "icon": "react-native", "docsAlias": "react-native", "shields": [ @@ -103,7 +121,7 @@ ] }, "@lucide/angular": { - "order": 6, + "order": 7, "icon": "angular", "docsAlias": "angular", "packageDirname": "angular", diff --git a/docs/.vitepress/lib/SvgPreview/index.tsx b/docs/.vitepress/lib/SvgPreview/index.tsx index 60643fa87..f7449c5e8 100644 --- a/docs/.vitepress/lib/SvgPreview/index.tsx +++ b/docs/.vitepress/lib/SvgPreview/index.tsx @@ -397,10 +397,14 @@ interface SvgPreviewProps extends React.SVGProps { children?: React.ReactNode; } -const SvgPreview = ( - { src, children, height = 24, width = 24, showGrid = false, ...props }: SvgPreviewProps, - ref, -) => { +const SvgPreview = ({ + src, + children, + height = 24, + width = 24, + showGrid = false, + ...props +}: SvgPreviewProps) => { const subGridSize = Math.max(height, width) % 3 === 0 ? Math.max(height, width) > 24 @@ -413,7 +417,6 @@ const SvgPreview = ( return ( -import { type FunctionalComponent } from 'vue'; -import { type LucideProps } from '@lucide/vue/src/types'; -import { Sandpack } from 'sandpack-vue3'; +import { Sandpack, type SandpackProps } from 'sandpack-vue3'; -defineProps>(); +const props = defineProps(); + + + Lucide Solid 2 Vite integration + + + {props.children} + + ); +} diff --git a/integrations/lucide-solid-2/vite/src/IconShowcase.tsx b/integrations/lucide-solid-2/vite/src/IconShowcase.tsx new file mode 100644 index 000000000..bd7eefc75 --- /dev/null +++ b/integrations/lucide-solid-2/vite/src/IconShowcase.tsx @@ -0,0 +1,31 @@ +import { Camera, Droplet, Edit2, House, LucideProvider, Pen } from '@lucide/solid'; +import Circle from '@lucide/solid/icons/circle'; + +export default function IconShowcase() { + return ( +
+ + + + + + + + +
+ ); +} diff --git a/integrations/lucide-solid-2/vite/src/router.ts b/integrations/lucide-solid-2/vite/src/router.ts new file mode 100644 index 000000000..006d87ed2 --- /dev/null +++ b/integrations/lucide-solid-2/vite/src/router.ts @@ -0,0 +1,7 @@ +import { createRouter } from '@solidjs/router'; +import { fileRoutes } from '@solidjs/router/fs'; +import { pageRoutes } from 'virtual:file-routes'; + +export const routes = fileRoutes(pageRoutes); + +export const Router = createRouter({ routes }); diff --git a/integrations/lucide-solid-2/vite/src/routes/about.tsx b/integrations/lucide-solid-2/vite/src/routes/about.tsx new file mode 100644 index 000000000..16a3ab3e8 --- /dev/null +++ b/integrations/lucide-solid-2/vite/src/routes/about.tsx @@ -0,0 +1,10 @@ +import { ArrowLeft } from '@lucide/solid'; + +export default function About() { + return ( +
+ + Home +
+ ); +} diff --git a/integrations/lucide-solid-2/vite/src/routes/index.tsx b/integrations/lucide-solid-2/vite/src/routes/index.tsx new file mode 100644 index 000000000..5a572403e --- /dev/null +++ b/integrations/lucide-solid-2/vite/src/routes/index.tsx @@ -0,0 +1,10 @@ +import IconShowcase from '../IconShowcase'; + +export default function Home() { + return ( + <> + + About + + ); +} diff --git a/integrations/lucide-solid-2/vite/src/vite-env.d.ts b/integrations/lucide-solid-2/vite/src/vite-env.d.ts new file mode 100644 index 000000000..56c779452 --- /dev/null +++ b/integrations/lucide-solid-2/vite/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/integrations/lucide-solid-2/vite/tests/icons.browser.spec.tsx b/integrations/lucide-solid-2/vite/tests/icons.browser.spec.tsx new file mode 100644 index 000000000..f767d2261 --- /dev/null +++ b/integrations/lucide-solid-2/vite/tests/icons.browser.spec.tsx @@ -0,0 +1,46 @@ +import { createRouter, memoryHistory } from '@solidjs/router'; +import { render } from '@solidjs/testing-library'; +import { Loading } from 'solid-js'; +import { expect, test } from 'vitest'; +import { page } from 'vitest/browser'; +import { routes } from '../src/router'; + +test('renders Lucide public APIs and survives router navigation', async () => { + const Router = createRouter({ routes, history: memoryHistory('/') }); + + render(() => {(props) => {props.children}}); + + const staticIcon = page.getByTestId('static-icon'); + await expect.element(staticIcon).toBeVisible(); + await expect.element(staticIcon).toHaveAttribute('width', '24'); + await expect.element(staticIcon).toHaveAttribute('height', '24'); + await expect.element(staticIcon).toHaveAttribute('viewBox', '0 0 24 24'); + await expect.element(staticIcon).toHaveAttribute('aria-hidden', 'true'); + + const customIcon = page.getByTestId('custom-icon'); + await expect.element(customIcon).toBeVisible(); + await expect.element(customIcon).toHaveAttribute('width', '48'); + await expect.element(customIcon).toHaveAttribute('height', '48'); + await expect.element(customIcon).toHaveAttribute('stroke', 'red'); + await expect.element(customIcon).toHaveAttribute('stroke-width', '2'); + await expect.element(customIcon).toHaveClass('consumer-icon'); + + const providerIcon = page.getByTestId('provider-icon'); + await expect.element(providerIcon).toHaveAttribute('width', '32'); + await expect.element(providerIcon).toHaveAttribute('stroke', 'purple'); + await expect.element(providerIcon).toHaveAttribute('stroke-width', '3'); + + const aliasIcon = page.getByTestId('alias-icon'); + const canonicalIcon = page.getByTestId('canonical-icon'); + await expect.element(aliasIcon).toBeVisible(); + await expect.element(canonicalIcon).toBeVisible(); + expect(aliasIcon.element().innerHTML).toBe(canonicalIcon.element().innerHTML); + + const deepImportIcon = page.getByTestId('deep-import-icon'); + await expect.element(deepImportIcon).toBeVisible(); + await expect.element(deepImportIcon).toHaveAttribute('aria-label', 'Deep import circle'); + await expect.element(deepImportIcon).not.toHaveAttribute('aria-hidden'); + + await page.getByRole('link', { name: 'About' }).click(); + await expect.element(page.getByTestId('route-icon')).toBeVisible(); +}); diff --git a/integrations/lucide-solid-2/vite/tsconfig.declarations.json b/integrations/lucide-solid-2/vite/tsconfig.declarations.json new file mode 100644 index 000000000..3b3bdf14e --- /dev/null +++ b/integrations/lucide-solid-2/vite/tsconfig.declarations.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "skipLibCheck": false, + "types": [] + }, + "include": ["src/IconShowcase.tsx"] +} diff --git a/integrations/lucide-solid-2/vite/tsconfig.json b/integrations/lucide-solid-2/vite/tsconfig.json new file mode 100644 index 000000000..afb79d079 --- /dev/null +++ b/integrations/lucide-solid-2/vite/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ESNext", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "jsx": "preserve", + "jsxImportSource": "@solidjs/web", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "isolatedModules": true, + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "types": ["vite/client"] + }, + "include": ["src", "tests", "file-routes.d.ts", "vite.config.ts"] +} diff --git a/integrations/lucide-solid-2/vite/vite.config.ts b/integrations/lucide-solid-2/vite/vite.config.ts new file mode 100644 index 000000000..65025e63d --- /dev/null +++ b/integrations/lucide-solid-2/vite/vite.config.ts @@ -0,0 +1,22 @@ +import solid from '@solidjs/vite-plugin'; +import { playwright } from '@vitest/browser-playwright'; +import { fileRoutes } from 'filesystem-routing/vite'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + // Scaffolded with `npm create solid@latest -- --solid -t basic`: turnkey client + // mode generates the entries around src/App.tsx (wrapped in src/Document.tsx) + // and `vite build` prerenders the shell into dist/client. + plugins: [solid({ start: true, extensions: ['.jsx', '.tsx'] }), fileRoutes({ types: true })], + test: { + browser: { + enabled: true, + headless: true, + provider: playwright(), + instances: [{ browser: 'chromium' }], + }, + }, + build: { + target: 'esnext', + }, +}); diff --git a/package.json b/package.json index a57f38d5e..01edd3d77 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "test:update": "pnpm -r --filter './packages/**' --filter !'./packages/lucide-angular' test -- -u", "test:integrations:react": "pnpm --filter lucide-react build && pnpm -r --workspace-concurrency=1 --filter './integrations/lucide-react/**' check", "test:integrations:solid": "pnpm --filter lucide-solid build && pnpm -r --workspace-concurrency=1 --filter './integrations/lucide-solid/**' check", + "test:integrations:solid-2": "pnpm --filter @lucide/solid build && pnpm -r --workspace-concurrency=1 --filter './integrations/lucide-solid-2/**' check", "test:integrations:vue": "pnpm --filter @lucide/vue build && pnpm -r --workspace-concurrency=1 --filter './integrations/lucide-vue/**' check", "test:font": "pnpm --filter build-font test", "lucide": "pnpm --filter lucide", diff --git a/packages/solid/README.md b/packages/solid/README.md new file mode 100644 index 000000000..242f974b8 --- /dev/null +++ b/packages/solid/README.md @@ -0,0 +1,89 @@ +

+ + Lucide icon library for Solid 2 applications. + +

+ +

+Lucide icon library for Solid 2 applications. +

+ +
+ + [![npm](https://img.shields.io/npm/v/%40lucide%2Fsolid?color=blue)](https://www.npmjs.com/package/@lucide/solid) + ![NPM Downloads](https://img.shields.io/npm/dw/%40lucide%2Fsolid) + [![License](https://img.shields.io/badge/license-ISC-green)](https://lucide.dev/license) +
+ +

+ About + · + Icons + · + Documentation + · + License +

+ +# Lucide Solid + +Implementation of the Lucide icon library for Solid 2 applications. + +## Installation + +```sh +pnpm add @lucide/solid +``` + +```sh +npm install @lucide/solid +``` + +```sh +yarn add @lucide/solid +``` + +```sh +bun add @lucide/solid +``` + +> `@lucide/solid` is only for Solid 2, for Solid 1 use the [`lucide-solid`](https://www.npmjs.com/package/lucide-solid) package. Solid 2 is still a release candidate. + +## Documentation + +For full documentation, visit [lucide.dev](https://lucide.dev/guide/solid) + +## Community + +Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintainers and other users. + +## License + +Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license). + +[//]: <> (Sponsors) + +## Sponsors + + + Powered by Vercel + + +DigitalOcean Referral Badge + +### Hero backers 🦸 + +Zephyr Cloud – From idea to prod: fast micro-frontend delivery! + +### Awesome backers 🍺 + +pdfme – Open-source PDF generation library built with TypeScript and React. +Pax Historia – An alternate history sandbox game + +### Backers ☕ + +Fina Money – Modular Finance Tracker + +### Other contributors 💸 + +You can find all our past and non-recurring financial contributors at [our Open Collective page](https://opencollective.com/lucide-icons). diff --git a/packages/solid/package.json b/packages/solid/package.json new file mode 100644 index 000000000..44e6dcd0c --- /dev/null +++ b/packages/solid/package.json @@ -0,0 +1,94 @@ +{ + "name": "@lucide/solid", + "description": "A Lucide icon library package for Solid 2 applications.", + "version": "0.0.1", + "license": "ISC", + "homepage": "https://lucide.dev", + "bugs": "https://github.com/lucide-icons/lucide/issues", + "repository": { + "type": "git", + "url": "https://github.com/lucide-icons/lucide.git", + "directory": "packages/solid" + }, + "keywords": [ + "Lucide", + "Solid", + "SolidJS", + "Feather", + "Icons", + "Icon", + "SVG", + "Feather Icons", + "Fontawesome", + "Font Awesome" + ], + "author": "Eric Fennis", + "source": "src/lucide-solid.ts", + "main": "dist/cjs/lucide-solid.js", + "module": "dist/esm/lucide-solid.mjs", + "types": "dist/types/lucide-solid.d.ts", + "files": [ + "dist" + ], + "exports": { + ".": { + "types": "./dist/types/lucide-solid.d.ts", + "solid": "./dist/source/lucide-solid.jsx", + "import": "./dist/esm/lucide-solid.mjs", + "browser": "./dist/esm/lucide-solid.mjs", + "require": "./dist/cjs/lucide-solid.js" + }, + "./icons": { + "types": "./dist/types/lucide-solid.d.ts", + "solid": "./dist/source/lucide-solid.jsx", + "import": "./dist/esm/lucide-solid.mjs", + "browser": "./dist/esm/lucide-solid.mjs", + "require": "./dist/cjs/lucide-solid.js" + }, + "./icons/*": { + "types": "./dist/types/icons/*.d.ts", + "solid": "./dist/source/icons/*.jsx", + "import": "./dist/esm/icons/*.mjs", + "browser": "./dist/esm/icons/*.mjs", + "require": "./dist/cjs/icons/*.js" + } + }, + "sideEffects": false, + "scripts": { + "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundle", + "copy:license": "cp ../../LICENSE ./LICENSE", + "clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.ts", + "build:transpile": "tsc --jsx preserve -t es2020 --rootDir src --outDir dist --noEmit false", + "build:version": "node ./scripts/replaceVersion.mjs", + "build:bundle": "rollup -c rollup.config.mjs", + "build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mts --renderUniqueKey --withAliases --separateAliasesFile --separateAliasesFileIgnore=fingerprint --aliasesFileExtension=.ts --iconFileExtension=.tsx --exportFileName=index.ts", + "typecheck": "tsc", + "typecheck:watch": "tsc -w", + "test": "pnpm build:icons && vitest run", + "test:watch": "vitest watch" + }, + "devDependencies": { + "@babel/core": "^7.29.7", + "@babel/preset-env": "^7.29.7", + "@babel/preset-typescript": "^7.29.7", + "@lucide/build-icons": "workspace:*", + "@lucide/rollup-plugins": "workspace:*", + "@lucide/shared": "workspace:*", + "@rollup/plugin-babel": "^6.1.0", + "@solidjs/testing-library": "next", + "@solidjs/vite-plugin": "next", + "@solidjs/web": "next", + "@testing-library/jest-dom": "^7.0.1", + "babel-preset-solid": "next", + "esbuild": "^0.28.2", + "jest-serializer-html": "^7.1.0", + "rollup-plugin-dts": "^6.5.1", + "rollup": "^4.63.1", + "solid-js": "next", + "typescript": "^6.0.3", + "vite": "^7.3.6" + }, + "peerDependencies": { + "solid-js": "^2.0.0-rc.0" + } +} diff --git a/packages/solid/rollup.config.mjs b/packages/solid/rollup.config.mjs new file mode 100644 index 000000000..1e82f7cee --- /dev/null +++ b/packages/solid/rollup.config.mjs @@ -0,0 +1,137 @@ +import path from 'path'; +import { babel } from '@rollup/plugin-babel'; +import esbuild from 'esbuild'; +import plugins from '@lucide/rollup-plugins'; +import dts from 'rollup-plugin-dts'; + +import pkg from './package.json' with { type: 'json' }; + +const dtsOptions = { + includeExternal: ['@lucide/shared/types'], + tsconfig: './tsconfig.json', +}; + +const packageName = '@lucide/solid'; +const outputFileName = 'lucide-solid'; +const outputDir = 'dist'; +const inputs = ['src/lucide-solid.ts']; + +const bundles = [ + { + format: 'cjs', + inputs, + outputDir, + preserveModules: true, + }, + { + format: 'esm', + inputs, + outputDir, + preserveModules: true, + extension: 'mjs', + }, +]; + +const configs = bundles + .map(({ inputs, outputDir, format, preserveModules, extension = 'js' }) => + inputs.map((input) => ({ + input, + plugins: [ + babel({ + extensions: ['.ts', '.tsx', '.js', '.jsx'], + babelHelpers: 'bundled', + presets: [ + 'babel-preset-solid', + '@babel/preset-typescript', + ['@babel/preset-env', { bugfixes: true, targets: 'last 2 years' }], + ], + }), + ...plugins({ + pkg, + withEsbuild: false, + }), + format === 'esm' + ? { + name: 'ts', + buildEnd() { + // Transpile typescript to './dist/source' + esbuild.build({ + entryPoints: ['./src/**/*.tsx', './src/**/*.ts'], + outdir: './dist/source', + outExtension: { + '.js': '.jsx', + }, + loader: { + '.js': 'jsx', + }, + jsx: 'preserve', + jsxImportSource: '@solidjs/web', + bundle: true, + format: 'esm', + sourcemap: true, + target: ['esnext'], + banner: { + js: `/** +* @license ${pkg.name} v${pkg.version} - ${pkg.license} +* +* This source code is licensed under the ${pkg.license} license. +* See the LICENSE file in the root directory of this source tree. +*/`, + }, + plugins: [ + { + name: 'externalize-everything-except-own-dependencies', + setup(build) { + build.onResolve({ filter: /(.*)/ }, (args) => { + const modulePath = path.join(args.resolveDir, args.path); + if ( + args.kind === 'import-statement' && + args.path !== '@lucide/shared' && + !modulePath.includes('packages/shared') + ) { + return { path: args.path, external: true }; + } + }); + }, + }, + ], + external: ['solid-js', '@solidjs/web'], + }); + }, + } + : null, + ], + external: ['solid-js', '@solidjs/web'], + output: { + name: packageName, + ...(preserveModules + ? { + dir: `${outputDir}/${format}`, + exports: 'auto', + entryFileNames: `[name].${extension}`, + } + : { + file: `${outputDir}/${format}/${outputFileName}.${extension}`, + }), + format: format === 'source' ? 'esm' : format, + preserveModules, + preserveModulesRoot: 'src', + sourcemap: true, + }, + })), + ) + .flat(); + +const typesConfig = { + input: inputs[0], + output: { + dir: `${outputDir}/types`, + format: 'es', + preserveModules: true, + preserveModulesRoot: 'src', + entryFileNames: '[name].d.ts', + }, + plugins: [dts(dtsOptions)], +}; + +export default [...configs, typesConfig]; diff --git a/packages/solid/scripts/exportTemplate.mts b/packages/solid/scripts/exportTemplate.mts new file mode 100644 index 000000000..c32878174 --- /dev/null +++ b/packages/solid/scripts/exportTemplate.mts @@ -0,0 +1,33 @@ +import base64SVG from '@lucide/build-icons/utils/base64SVG'; +import defineExportTemplate from '@lucide/build-icons/utils/defineExportTemplate'; + +export default defineExportTemplate( + async ({ componentName, iconName, iconData, getSvg, deprecated, deprecationReason }) => { + const svgContents = await getSvg(); + const svgBase64 = base64SVG(svgContents); + + return ` +import Icon from '../Icon'; +import type { LucideIconData, LucideProps } from '../types'; + +const iconData: LucideIconData = ${JSON.stringify(iconData)}; + +/** + * @component @name ${componentName} + * @description Lucide SVG icon component, renders SVG Element with children. + * + * @preview ![img](data:image/svg+xml;base64,${svgBase64}) - https://lucide.dev/icons/${iconName} + * @see https://lucide.dev/guide/solid - Documentation + * + * @param {Object} props - Lucide icons props and any valid SVG attribute + * @returns {JSX.Element} JSX Element + * ${deprecated ? `@deprecated ${deprecationReason}` : ''} + */ +const ${componentName} = (props: LucideProps) => ( + +) + +export default ${componentName}; +`; + }, +); diff --git a/packages/solid/src/Icon.tsx b/packages/solid/src/Icon.tsx new file mode 100644 index 000000000..dd4019c69 --- /dev/null +++ b/packages/solid/src/Icon.tsx @@ -0,0 +1,75 @@ +import { createMemo, For, omit, useContext } from 'solid-js'; +import { Dynamic } from '@solidjs/web'; +import { buildLucideIconNode, hasA11yProp, mergeClasses } from '@lucide/shared'; +import { LucideIconData, LucideIconNode, LucideProps } from './types'; +import { LucideContext } from './context'; + +type IconProps = + | { + icon: LucideIconData; + iconNode?: never; + } + | { + icon?: never; + iconNode?: LucideIconNode[]; + }; + +const LOCAL_PROP_KEYS = [ + 'color', + 'size', + 'width', + 'height', + 'strokeWidth', + 'children', + 'class', + 'icon', + 'iconNode', + 'absoluteStrokeWidth', + 'nonScalingStroke', +] as const; + +const Icon = (props: LucideProps & IconProps) => { + const globalProps = useContext(LucideContext); + + const rest = () => omit(props, ...LOCAL_PROP_KEYS); + + const icon = createMemo( + () => + props.icon ?? { + node: props.iconNode ?? ([] as LucideIconNode[]), + size: 24, + aliases: [], + }, + ); + + const builtIcon = createMemo(() => + buildLucideIconNode(icon(), { + color: props.color ?? globalProps.color, + width: props.width ?? props.size ?? globalProps.size, + height: props.height ?? props.size ?? globalProps.size, + strokeWidth: props.strokeWidth ?? globalProps.strokeWidth, + absoluteStrokeWidth: props.absoluteStrokeWidth ?? globalProps.absoluteStrokeWidth, + nonScalingStroke: props.nonScalingStroke ?? globalProps.nonScalingStroke, + className: mergeClasses('lucide-icon', globalProps.class, props.class), + hasA11yProp: Boolean(props.children) || hasA11yProp(rest()), + attributes: rest(), + }), + ); + + return ( + + + {([elementName, attrs]) => { + return ( + + ); + }} + + + ); +}; + +export default Icon; diff --git a/packages/solid/src/aliases/index.ts b/packages/solid/src/aliases/index.ts new file mode 100644 index 000000000..bbe66d0a2 --- /dev/null +++ b/packages/solid/src/aliases/index.ts @@ -0,0 +1,3 @@ +export * from './aliases'; +export * from './prefixed'; +export * from './suffixed'; diff --git a/packages/solid/src/context.tsx b/packages/solid/src/context.tsx new file mode 100644 index 000000000..fd9064f5b --- /dev/null +++ b/packages/solid/src/context.tsx @@ -0,0 +1,37 @@ +import { createContext, omit, type Element } from 'solid-js'; + +export const LucideContext = createContext<{ + size?: number; + color?: string; + strokeWidth?: number; + /** + * @deprecated Use `nonScalingStroke` instead. + */ + absoluteStrokeWidth?: boolean; + nonScalingStroke?: boolean; + class?: string; +}>({ + size: 24, + color: 'currentColor', + strokeWidth: 2, + absoluteStrokeWidth: false, + nonScalingStroke: false, + class: '', +}); + +interface LucideProviderProps { + children: Element; + size?: number; + color?: string; + strokeWidth?: number; + /** + * @deprecated Use `nonScalingStroke` instead. + */ + absoluteStrokeWidth?: boolean; + nonScalingStroke?: boolean; + class?: string; +} + +export function LucideProvider(props: LucideProviderProps) { + return {props.children}; +} diff --git a/packages/solid/src/defaultAttributes.ts b/packages/solid/src/defaultAttributes.ts new file mode 100644 index 000000000..cc4036fbd --- /dev/null +++ b/packages/solid/src/defaultAttributes.ts @@ -0,0 +1 @@ +export { defaultAttributes as default } from '@lucide/shared'; diff --git a/packages/solid/src/icons/.gitkeep b/packages/solid/src/icons/.gitkeep new file mode 100644 index 000000000..e3d85f774 --- /dev/null +++ b/packages/solid/src/icons/.gitkeep @@ -0,0 +1 @@ +Folder for generated icons diff --git a/packages/solid/src/lucide-solid.ts b/packages/solid/src/lucide-solid.ts new file mode 100644 index 000000000..6242889b9 --- /dev/null +++ b/packages/solid/src/lucide-solid.ts @@ -0,0 +1,7 @@ +export * from './icons'; +export * as icons from './icons'; +export * from './aliases'; +export * from './types'; +export * from './context'; + +export { default as Icon } from './Icon'; diff --git a/packages/solid/src/types.ts b/packages/solid/src/types.ts new file mode 100644 index 000000000..e99220569 --- /dev/null +++ b/packages/solid/src/types.ts @@ -0,0 +1,33 @@ +import type { JSX } from '@solidjs/web'; +import type { + LucideIconData as SharedLucideIconData, + LucideIconNode as SharedLucideIconNode, +} from '@lucide/shared/types'; + +export type SVGAttributes = Partial>; + +export type LucideIconNode = SharedLucideIconNode; + +export type LucideIconData = SharedLucideIconData; + +/** + * @deprecated Use LucideIconNode instead. + */ +export type IconNode = LucideIconNode[]; + +export interface LucideProps extends SVGAttributes { + key?: string | number; + class?: string; + size?: string | number; + width?: string | number; + height?: string | number; + color?: string; + strokeWidth?: string | number; + /** + * @deprecated Use `nonScalingStroke` instead. + */ + absoluteStrokeWidth?: boolean; + nonScalingStroke?: boolean; +} + +export type LucideIcon = (props: LucideProps) => JSX.Element; diff --git a/packages/solid/tests/Icon.spec.tsx b/packages/solid/tests/Icon.spec.tsx new file mode 100644 index 000000000..500bcff23 --- /dev/null +++ b/packages/solid/tests/Icon.spec.tsx @@ -0,0 +1,154 @@ +import { describe, it, expect } from 'vitest'; +import { render } from '@solidjs/testing-library'; +import { createSignal, flush } from 'solid-js'; + +import { airVent } from './testIconNodes'; +import { Icon } from '../src/lucide-solid'; + +describe('Using Icon Component', () => { + const airVentIcon = { name: 'air-vent', node: airVent }; + + it('should render icon based on a iconNode', async () => { + const { container } = render(() => ( + + )); + + expect(container.firstChild).toBeDefined(); + }); + + it('should render icon and match snapshot', async () => { + const { container } = render(() => ( + + )); + + expect(container.firstChild).toMatchSnapshot(); + }); + + it('should render icon based on icon data', async () => { + const { container } = render(() => ( + + )); + + expect(container.firstChild).toBeDefined(); + }); + + it('should support nonScalingStroke', async () => { + const { container } = render(() => ( + + )); + + expect(container.firstChild?.firstChild).toHaveAttribute('vector-effect', 'non-scaling-stroke'); + }); + + it('should update when reactive props change', async () => { + const [size, setSize] = createSignal(24); + const { container } = render(() => ( + + )); + + expect(container.firstChild).toHaveAttribute('width', '24'); + expect(container.firstChild).toHaveAttribute('height', '24'); + + setSize(48); + flush(); + + expect(container.firstChild).toHaveAttribute('width', '48'); + expect(container.firstChild).toHaveAttribute('height', '48'); + }); +}); + +describe('Icon Component Accessibility', () => { + it('should have aria-hidden prop when no aria prop is present', async () => { + const { container } = render(() => ( + + )); + + expect(container.firstChild).toHaveAttribute('aria-hidden', 'true'); + }); + + it('should not have aria-hidden prop when aria prop is present', async () => { + const { container } = render(() => ( + + )); + + expect(container.firstChild).not.toHaveAttribute('aria-hidden'); + }); + + it('should not have aria-hidden prop when title prop is present', async () => { + const { container } = render(() => ( + + )); + + expect(container.firstChild).not.toHaveAttribute('aria-hidden'); + }); + + it('should not have aria-hidden prop when there are children that could be a element', async () => { + const { container } = render(() => ( + <Icon + iconNode={airVent} + size={48} + stroke="red" + absoluteStrokeWidth + > + <title>Some title + + )); + + expect(container.firstChild).not.toHaveAttribute('aria-hidden'); + }); + + it('should never override aria-hidden prop', async () => { + const { container } = render(() => ( + + )); + + expect(container.firstChild).toHaveAttribute('aria-hidden', 'false'); + }); +}); diff --git a/packages/solid/tests/__snapshots__/Icon.spec.tsx.snap b/packages/solid/tests/__snapshots__/Icon.spec.tsx.snap new file mode 100644 index 000000000..5a783f6e1 --- /dev/null +++ b/packages/solid/tests/__snapshots__/Icon.spec.tsx.snap @@ -0,0 +1,34 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Using Icon Component > should render icon and match snapshot 1`] = ` + +`; diff --git a/packages/solid/tests/__snapshots__/context.spec.tsx.snap b/packages/solid/tests/__snapshots__/context.spec.tsx.snap new file mode 100644 index 000000000..723407f5f --- /dev/null +++ b/packages/solid/tests/__snapshots__/context.spec.tsx.snap @@ -0,0 +1,26 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Using LucideProvider > should render the icon with LucideProvider 1`] = ` + +`; diff --git a/packages/solid/tests/__snapshots__/lucide-solid.spec.tsx.snap b/packages/solid/tests/__snapshots__/lucide-solid.spec.tsx.snap new file mode 100644 index 000000000..22743b33f --- /dev/null +++ b/packages/solid/tests/__snapshots__/lucide-solid.spec.tsx.snap @@ -0,0 +1,123 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Using lucide icon components > should adjust the size, stroke color and stroke width 1`] = ` + +`; + +exports[`Using lucide icon components > should render a component 1`] = ` + +`; + +exports[`Using lucide icon components > should scale the strokeWidth when absoluteStrokeWidth is set 1`] = ` + +`; diff --git a/packages/solid/tests/context.spec.tsx b/packages/solid/tests/context.spec.tsx new file mode 100644 index 000000000..74991a9c4 --- /dev/null +++ b/packages/solid/tests/context.spec.tsx @@ -0,0 +1,121 @@ +import { render } from '@solidjs/testing-library'; +import { createSignal, flush } from 'solid-js'; +import { describe, expect, it } from 'vitest'; +import { House, LucideProvider } from '../src/lucide-solid'; + +describe('Using LucideProvider', () => { + it('should render the icon with LucideProvider', () => { + const { container } = render(() => ( + + + + )); + + expect(container.firstChild).toMatchSnapshot(); + }); + + it('should render the icon with default props when no provider is used', () => { + const { container } = render(() => ); + + const IconComponent = container.firstElementChild; + + expect(IconComponent).toHaveAttribute('width', '24'); + expect(IconComponent).toHaveAttribute('height', '24'); + expect(IconComponent).toHaveAttribute('stroke', 'currentColor'); + expect(IconComponent).toHaveAttribute('stroke-width', '2'); + }); + + it('should render the icon with LucideProvider and custom strokeWidth', () => { + const { container } = render(() => ( + + + + )); + + const IconComponent = container.firstElementChild; + + expect(IconComponent).toHaveAttribute('width', '48'); + expect(IconComponent).toHaveAttribute('height', '48'); + expect(IconComponent).toHaveAttribute('stroke', 'red'); + expect(IconComponent).toHaveAttribute('stroke-width', '4'); + }); + + it('should update when reactive LucideProvider props change', () => { + const [size, setSize] = createSignal(24); + const { container } = render(() => ( + + + + )); + + expect(container.firstElementChild).toHaveAttribute('width', '24'); + expect(container.firstElementChild).toHaveAttribute('height', '24'); + + setSize(48); + flush(); + + expect(container.firstElementChild).toHaveAttribute('width', '48'); + expect(container.firstElementChild).toHaveAttribute('height', '48'); + }); + + it('should render the icon with LucideProvider and custom absoluteStrokeWidth', () => { + const { container } = render(() => ( + + + + )); + + const IconComponent = container.firstElementChild; + + expect(IconComponent).toHaveAttribute('stroke-width', '1'); + }); + + it("should override the provider's global props when passing props to the icon", () => { + const { container } = render(() => ( + + + + )); + + const IconComponent = container.firstElementChild; + + expect(IconComponent).toHaveAttribute('width', '24'); + expect(IconComponent).toHaveAttribute('height', '24'); + expect(IconComponent).toHaveAttribute('stroke', 'blue'); + expect(IconComponent).toHaveAttribute('stroke-width', '2'); + }); + + it('should merge className from provider and icon', () => { + const { container } = render(() => ( + + + + )); + + const IconComponent = container.firstElementChild; + + expect(IconComponent).toHaveAttribute( + 'class', + 'lucide lucide-house lucide-home lucide-icon provider-class icon-class', + ); + }); +}); diff --git a/packages/solid/tests/lucide-solid.spec.tsx b/packages/solid/tests/lucide-solid.spec.tsx new file mode 100644 index 000000000..1421dd034 --- /dev/null +++ b/packages/solid/tests/lucide-solid.spec.tsx @@ -0,0 +1,90 @@ +import { describe, it, expect } from 'vitest'; +import { render, cleanup } from '@solidjs/testing-library'; +import { Edit2, Grid, Pen, Droplet } from '../src/lucide-solid'; + +describe('Using lucide icon components', () => { + it('should render a component', () => { + const { container } = render(() => ); + + expect(container.innerHTML).toMatchSnapshot(); + }); + + it('should adjust the size, stroke color and stroke width', async () => { + const testId = 'grid-icon'; + const { container, getByTestId } = render(() => ( + + )); + + const { attributes } = (await getByTestId(testId)) as unknown as { + attributes: Record; + }; + expect(attributes.stroke.value).toBe('red'); + expect(attributes.width.value).toBe('48'); + expect(attributes.height.value).toBe('48'); + expect(attributes['stroke-width'].value).toBe('4'); + expect(container.innerHTML).toMatchSnapshot(); + }); + + it('should render the alias icon', () => { + const testId = 'pen-icon'; + const { container } = render(() => ( + + )); + + const PenIconRenderedHTML = container.innerHTML; + + cleanup(); + + const { container: Edit2Container } = render(() => ( + + )); + + expect(PenIconRenderedHTML).toBe(Edit2Container.innerHTML); + }); + + it('should scale the strokeWidth when absoluteStrokeWidth is set', () => { + const testId = 'grid-icon'; + const { container, getByTestId } = render(() => ( + + )); + + const { attributes } = getByTestId(testId) as unknown as { + attributes: Record; + }; + expect(attributes.stroke.value).toBe('red'); + expect(attributes.width.value).toBe('48'); + expect(attributes.height.value).toBe('48'); + expect(attributes['stroke-width'].value).toBe('1'); + + expect(container.innerHTML).toMatchSnapshot(); + }); + + it('should add all classes to the element', () => { + const testClass = 'my-class'; + const { container } = render(() => ); + + expect(container.firstChild).toHaveClass(testClass); + expect(container.firstChild).toHaveClass('lucide'); + expect(container.firstChild).toHaveClass('lucide-droplet'); + }); +}); diff --git a/packages/solid/tests/setupVitest.js b/packages/solid/tests/setupVitest.js new file mode 100644 index 000000000..eee9d60f6 --- /dev/null +++ b/packages/solid/tests/setupVitest.js @@ -0,0 +1,10 @@ +import { expect, afterEach } from 'vitest'; +import { cleanup } from '@solidjs/testing-library'; +import '@testing-library/jest-dom/vitest'; +import htmlSerializer from 'jest-serializer-html'; + +expect.addSnapshotSerializer(htmlSerializer); + +afterEach(() => { + cleanup(); +}); diff --git a/packages/solid/tests/testIconNodes.ts b/packages/solid/tests/testIconNodes.ts new file mode 100644 index 000000000..c93721961 --- /dev/null +++ b/packages/solid/tests/testIconNodes.ts @@ -0,0 +1,22 @@ +import { IconNode } from '../src/types'; + +export const airVent: IconNode = [ + [ + 'path', + { + d: 'M6 12H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2', + key: 'larmp2', + }, + ], + ['path', { d: 'M6 8h12', key: '6g4wlu' }], + ['path', { d: 'M18.3 17.7a2.5 2.5 0 0 1-3.16 3.83 2.53 2.53 0 0 1-1.14-2V12', key: '1bo8pg' }], + ['path', { d: 'M6.6 15.6A2 2 0 1 0 10 17v-5', key: 't9h90c' }], +]; + +export const coffee: IconNode = [ + ['path', { d: 'M17 8h1a4 4 0 1 1 0 8h-1', key: 'jx4kbh' }], + ['path', { d: 'M3 8h14v9a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4Z', key: '1bxrl0' }], + ['line', { x1: '6', x2: '6', y1: '2', y2: '4', key: '1cr9l3' }], + ['line', { x1: '10', x2: '10', y1: '2', y2: '4', key: '170wym' }], + ['line', { x1: '14', x2: '14', y1: '2', y2: '4', key: '1c5f70' }], +]; diff --git a/packages/solid/tsconfig.json b/packages/solid/tsconfig.json new file mode 100644 index 000000000..4b177df3b --- /dev/null +++ b/packages/solid/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "strict": true, + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "paths": { + "@lucide/shared": ["../shared/src/index.ts"], + "@lucide/shared/types": ["../shared/src/build/types.ts"] + }, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "@solidjs/web", + "types": ["vite/client", "@testing-library/jest-dom/vitest"], + "noEmit": true, + "isolatedModules": true, + "outDir": "./dist", + "declarationDir": "./dist", + "declaration": true + } +} diff --git a/packages/solid/vitest.config.mts b/packages/solid/vitest.config.mts new file mode 100644 index 000000000..bc9e80315 --- /dev/null +++ b/packages/solid/vitest.config.mts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vitest/config' +import solidPlugin from '@solidjs/vite-plugin'; + +export default defineConfig({ + plugins: [solidPlugin()], + test: { + globals: true, + environment: 'jsdom', + setupFiles: './tests/setupVitest.js', + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f13142e2a..e23e37953 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -195,6 +195,12 @@ importers: '@rollup/plugin-replace': specifier: ^6.0.3 version: 6.0.3(rollup@4.63.1) + '@types/react': + specifier: ^19.3.0 + version: 19.3.0 + '@types/react-dom': + specifier: ^19.3.0 + version: 19.3.0(@types/react@19.3.0) '@types/semver': specifier: ^7.8.0 version: 7.8.0 @@ -242,7 +248,7 @@ importers: version: 6.0.3 vitepress: specifier: ^1.6.4 - version: 1.6.4(@algolia/client-search@5.57.0)(@types/node@26.4.1)(@types/react@18.3.31)(esbuild@0.28.2)(fuse.js@7.5.0)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(postcss@8.5.28)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(sass@1.103.1)(search-insights@2.8.2)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(typescript@6.0.3)(yaml@2.9.0) + version: 1.6.4(@algolia/client-search@5.57.0)(@types/node@26.4.1)(@types/react@19.3.0)(esbuild@0.28.2)(fuse.js@7.5.0)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(postcss@8.5.28)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(sass@1.103.1)(search-insights@2.8.2)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(typescript@6.0.3)(yaml@2.9.0) vitepress-plugin-group-icons: specifier: ^1.7.6 version: 1.7.6(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)) @@ -477,6 +483,49 @@ importers: specifier: 2.3.0 version: 2.3.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(vitest@5.0.3) + integrations/lucide-solid-2/vite: + dependencies: + '@lucide/solid': + specifier: workspace:* + version: link:../../../packages/solid + '@solidjs/meta': + specifier: 1.0.0-next.2 + version: 1.0.0-next.2(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(solid-js@2.0.0-rc.13) + '@solidjs/router': + specifier: 2.0.0-next.34 + version: 2.0.0-next.34(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(filesystem-routing@0.4.0(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)))(solid-js@2.0.0-rc.13) + '@solidjs/web': + specifier: 2.0.0-rc.13 + version: 2.0.0-rc.13(solid-js@2.0.0-rc.13) + solid-js: + specifier: 2.0.0-rc.13 + version: 2.0.0-rc.13 + devDependencies: + '@solidjs/testing-library': + specifier: 1.0.0-beta.3 + version: 1.0.0-beta.3(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(solid-js@2.0.0-rc.13) + '@solidjs/vite-plugin': + specifier: 3.0.0-next.47 + version: 3.0.0-next.47(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.3))(solid-js@2.0.0-rc.13)(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)) + '@vitest/browser-playwright': + specifier: 5.0.3 + version: 5.0.3(playwright@1.58.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0))(vitest@5.0.3) + filesystem-routing: + specifier: 0.4.0 + version: 0.4.0(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)) + playwright: + specifier: 1.58.2 + version: 1.58.2 + typescript: + specifier: ^6.0.3 + version: 6.0.3 + vite: + specifier: ^8.3.2 + version: 8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0) + vitest: + specifier: 5.0.3 + version: 5.0.3(@types/node@26.4.1)(@vitest/browser-playwright@5.0.3)(@vitest/coverage-v8@5.0.3)(@vitest/ui@5.0.3)(jsdom@30.0.1)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)) + integrations/lucide-solid/solid-start: dependencies: '@solidjs/meta': @@ -1116,6 +1165,66 @@ importers: specifier: ^8.3.2 version: 8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0) + packages/solid: + devDependencies: + '@babel/core': + specifier: ^7.29.7 + version: 7.29.7(supports-color@10.2.2) + '@babel/preset-env': + specifier: ^7.29.7 + version: 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@babel/preset-typescript': + specifier: ^7.29.7 + version: 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) + '@lucide/build-icons': + specifier: workspace:* + version: link:../../tools/build-icons + '@lucide/rollup-plugins': + specifier: workspace:* + version: link:../../tools/rollup-plugins + '@lucide/shared': + specifier: workspace:* + version: link:../shared + '@rollup/plugin-babel': + specifier: ^6.1.0 + version: 6.1.0(@babel/core@7.29.7(supports-color@10.2.2))(@types/babel__core@7.20.5)(rollup@4.63.1)(supports-color@10.2.2) + '@solidjs/testing-library': + specifier: next + version: 1.0.0-beta.3(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(solid-js@2.0.0-rc.13) + '@solidjs/vite-plugin': + specifier: next + version: 3.0.0-next.35(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.3))(solid-js@2.0.0-rc.13)(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)) + '@solidjs/web': + specifier: next + version: 2.0.0-rc.13(solid-js@2.0.0-rc.13) + '@testing-library/jest-dom': + specifier: ^7.0.1 + version: 7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.3) + babel-preset-solid: + specifier: next + version: 2.0.0-rc.2(@babel/core@7.29.7(supports-color@10.2.2))(solid-js@2.0.0-rc.13) + esbuild: + specifier: ^0.28.2 + version: 0.28.2 + jest-serializer-html: + specifier: ^7.1.0 + version: 7.1.0 + rollup: + specifier: ^4.63.1 + version: 4.63.1 + rollup-plugin-dts: + specifier: ^6.5.1 + version: 6.5.1(rollup@4.63.1)(typescript@6.0.3) + solid-js: + specifier: next + version: 2.0.0-rc.13 + typescript: + specifier: ^6.0.3 + version: 6.0.3 + vite: + specifier: ^8.3.2 + version: 8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0) + packages/svelte: devDependencies: '@lucide/build-icons': @@ -2771,6 +2880,11 @@ packages: search-insights: optional: true + '@dom-expressions/babel-plugin-jsx@0.50.0-next.44': + resolution: {integrity: sha512-f1kx6TeMQgaLVkGfuxMn0BkH0+HvsycFf1qPHbYoBqmBQd6Ag/EXOxkSpfcaC+UOBMSaF4BKXegGDchRNTWKrg==} + peerDependencies: + '@babel/core': ^7.20.12 + '@dxup/nuxt@0.4.1': resolution: {integrity: sha512-gtYffW6OfWNvoLW+XD3Mx/K8uUq08PMGLYJoDxc92EzZAWqR0FhcR5iaLm5r/OxyGTKz+P5f5Y7Aoir9+SjYaw==} peerDependencies: @@ -4309,6 +4423,12 @@ packages: cpu: [arm] os: [android] + '@oxc-parser/binding-android-arm-eabi@0.139.0': + resolution: {integrity: sha512-22EsXTA3Vc7OvrF4bfT48PFln2UbxkVgrp/Tm32qLw76Dv7SmcInfClJe6yPYamnli6HiqasnESZ5ezN+X4ybg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + '@oxc-parser/binding-android-arm-eabi@0.141.0': resolution: {integrity: sha512-jk7086MFvR/T4DG9IY7MKBVt1PMxvSZoz/TvnifodvS0pjghVwJHRttnAExhlwdMOgHv1TmLdENnbNpYk2zjvA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4333,6 +4453,12 @@ packages: cpu: [arm64] os: [android] + '@oxc-parser/binding-android-arm64@0.139.0': + resolution: {integrity: sha512-uASQkZV+CUQ6xXvoMzDQyfhd8OMusdv2FyCPfAi5ZDYptesapJlw7erhpGi1Lc+U8QjQV2JUrIh7d/3su2LzmQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@oxc-parser/binding-android-arm64@0.141.0': resolution: {integrity: sha512-a4XDQ27ZT7e7zwAlxJDTiCA7IBGWDuy2+MhFq85Of7XlBSmpkfcBFml11q0Zx6f7RMuI0B4xCtt2ytBS4yOptg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4357,6 +4483,12 @@ packages: cpu: [arm64] os: [darwin] + '@oxc-parser/binding-darwin-arm64@0.139.0': + resolution: {integrity: sha512-vuQOv2WF5pZCkdSPEExul98o853M3MCR24DpWsGrUoPJu5KcnGE34kLXY2yFwBwZwT+eN1x40Tt4q6ZzlEdNUA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@oxc-parser/binding-darwin-arm64@0.141.0': resolution: {integrity: sha512-m/kVk6rzYmBeHYnz+1Y5fod00AVTTxMbC71azFfm/zjx1j9XxwKtA0+VfkKuVMC8rbghb9TtfevnuWZa9OuPEg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4381,6 +4513,12 @@ packages: cpu: [x64] os: [darwin] + '@oxc-parser/binding-darwin-x64@0.139.0': + resolution: {integrity: sha512-zxZB8ChS+7XactZhcyxQ292P/DNiiBaPPKYiVUlb3RC0V/hme5bokNubjcmEmbW9uTfmqLTpveAdkbe66H3pGg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@oxc-parser/binding-darwin-x64@0.141.0': resolution: {integrity: sha512-o0X+6KZlfucWU/v5oKRQPwdFXsXAjW8jmpo/Gpw/qyKsbKtlfkHoeH9Bjp/m13TwjewvJnCkwF0DWzgpC4HjTQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4405,6 +4543,12 @@ packages: cpu: [x64] os: [freebsd] + '@oxc-parser/binding-freebsd-x64@0.139.0': + resolution: {integrity: sha512-iw2MsoCPBQwdJqywRAGsF1jEAcGoZ+DeG2LVzt5pdUvRHqajsMF46BH0rHiWoWtMwcMSia+oQYga7fHo7u7Bcw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@oxc-parser/binding-freebsd-x64@0.141.0': resolution: {integrity: sha512-W5KbTnNkTMMMylqj6dYqnsXvkmESVPodPKYLJ5zdzIPdl9fUJtolkpUeSzYEbGGYB4a4A4avl3EePnZ/wLIdJg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4429,6 +4573,12 @@ packages: cpu: [arm] os: [linux] + '@oxc-parser/binding-linux-arm-gnueabihf@0.139.0': + resolution: {integrity: sha512-SwjD/k3Y5bwGJWOH313VyaDrAuaYg1Pe+4AAXCgUKvSO5IHkj+mZ0oFcOWmB5nTuOM3uwdT+leL8h4OnFlI5hw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxc-parser/binding-linux-arm-gnueabihf@0.141.0': resolution: {integrity: sha512-g3dtbJa8zeOGK36Sr9cQavsdi5H/ie2hVjrSjIxsNAR1qZA40ZYVXnfdfoMAlq8CmB9qFL1yhsSCUHeNmdmt8w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4447,6 +4597,12 @@ packages: cpu: [arm] os: [linux] + '@oxc-parser/binding-linux-arm-musleabihf@0.139.0': + resolution: {integrity: sha512-qbeygDkcvailKFhphb2YGMMXsaZIynHlPtoOrcx4NZB/tRbUKraCCMbw8dPeFtEKasfS2qWh1VnReY+Lcys1zA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@oxc-parser/binding-linux-arm-musleabihf@0.141.0': resolution: {integrity: sha512-e6hwQqd+3lvP13G2jxvFpoA7dzHcFLN+Mq47JCVMtdNHbbyBRo756JCtbbJH6ca8inTfyqZoqBmS3vhQlzAK2w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4473,6 +4629,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-arm64-gnu@0.139.0': + resolution: {integrity: sha512-SrlL02KeImKlvx/9rCeopOLH7qKI3rqKKEguK6KBwVwEGLhV/A47dW4DNigf6/LFhrwoovaiayEQryjYAI86dQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-arm64-gnu@0.141.0': resolution: {integrity: sha512-vXz2BLAuypA+4MLyBg94pzEo6THVnzYnCtAjXoihIIQo0t2pnp/AmW+SH1EI+4VbuJnC//KplIJ5yyaCGua4jA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4501,6 +4664,13 @@ packages: os: [linux] libc: [musl] + '@oxc-parser/binding-linux-arm64-musl@0.139.0': + resolution: {integrity: sha512-u9e884ChAVRmIZ1jr/m46S96FoDQnruFjISLi4Y0i6Wu/JUUmIiw7+umLyXILJsPfUuqnN5BJLe23t07+Y6+IA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@oxc-parser/binding-linux-arm64-musl@0.141.0': resolution: {integrity: sha512-jMkS/EztNW34HKsXIaT/SoHcmtocq/vWhwFOVduF9kduuuRIVwfwQ6uxzIO+qPKSXdd2TXt54of0BJ2zFMXnmw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4522,6 +4692,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-ppc64-gnu@0.139.0': + resolution: {integrity: sha512-Z9tU2b3GJfAXOdirQmz4gZQkQkVjy53i77gf91l0733MQKa/qtk73KQQE2GzDtMqim+HyjpzvemmqzBtH2IJUA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-ppc64-gnu@0.141.0': resolution: {integrity: sha512-vo+MR+n3zQJ6Mq92hiP084NZcgDv5iJlVR02gMf28neMvVT1tKVm7VeiW/DxhdqOi3QLeaXIk9cUcLL1qrkngw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4550,6 +4727,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-riscv64-gnu@0.139.0': + resolution: {integrity: sha512-RyUbr7hzPK84YDWKs77PRYk9VBwWbsbuYsQzQWiSmLnARXTg2zntLPGfCH/1wpfUYdmGkp/6SsqTXSsYdw9Jgw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-riscv64-gnu@0.141.0': resolution: {integrity: sha512-oh80w+7RuiO5gBp9Jnoa/H8Qlt3JsHL2MkW+0dwEdlDMdslVZX/YsekSK6EeyEenY66/mhCfypsNATQ7Ph3qlQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4571,6 +4755,13 @@ packages: os: [linux] libc: [musl] + '@oxc-parser/binding-linux-riscv64-musl@0.139.0': + resolution: {integrity: sha512-dcQhjtcDvtR8BgkUpt03Yz5SzxdzYvTigenIJOEsiSX6G2t6yybEMxGWjp0dOuYGror0BaqcZfTyXR58amCEig==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + '@oxc-parser/binding-linux-riscv64-musl@0.141.0': resolution: {integrity: sha512-LOyEmFA8sCnYbEXP1+iQvCC/P1YXHMA/t6x1Ksp0Y9VwhLFsiBJFzV1zIxrOIE2LKaGGhDjQ29xq9cbq6omDXA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4599,6 +4790,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-s390x-gnu@0.139.0': + resolution: {integrity: sha512-iuGrxysV4rGUymdKpn7bgZQ6Vix8Bi/6D/rp71HYIzphq6NKrsBhsGOYsSZte+uBFL43tXh7Xr7TM72sGliJNA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-s390x-gnu@0.141.0': resolution: {integrity: sha512-3wnwk/l1CvszVE5TJR1wSl/zSEfydRqrNhn6s7Vr9IzSJpUQIroqVsIoPARHRFA+FQwkxAFDAHDAasa7v8OobQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4627,6 +4825,13 @@ packages: os: [linux] libc: [glibc] + '@oxc-parser/binding-linux-x64-gnu@0.139.0': + resolution: {integrity: sha512-NxJdZZyaa2JLLvNfH/iJQXfCNfKcPMylwY4ObMpBVmW4Nq+RyUpVVQXrMMelcQ6rwx3nuhF1Iga8n+eoAKGCIA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@oxc-parser/binding-linux-x64-gnu@0.141.0': resolution: {integrity: sha512-qtyQVAAebFq57B2tifTlel3TgGqUtsYNI/e+p6aya9rN9lOZVTDvr215fGYSA9XWooxzMxDiVxkBLk2jQHbsOQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4655,6 +4860,13 @@ packages: os: [linux] libc: [musl] + '@oxc-parser/binding-linux-x64-musl@0.139.0': + resolution: {integrity: sha512-ePxBvvtzISmSsJ0RIj8FNikSCn58i1jtccj7XR4U9Li4iSzhkFyYlnJ51cQTUwkairz8WMTD4SpKoot8RyTnQA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@oxc-parser/binding-linux-x64-musl@0.141.0': resolution: {integrity: sha512-SkGV1nKw40roEc94pv5EaaeH2ay14G6+roe8Q0wIUC1LcEKxzKW921h7+ZuZX0D3q2Mb/7aSFmxEVqnko3lPRw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4681,6 +4893,12 @@ packages: cpu: [arm64] os: [openharmony] + '@oxc-parser/binding-openharmony-arm64@0.139.0': + resolution: {integrity: sha512-b/c2+mPXMOxG5x16n8yf9cjor/ntQQScmYnSmLEWIWJ4rfXd5dokMxx0kliSLA+YAGq6DD3K9BWi+aFXHiiV1w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@oxc-parser/binding-openharmony-arm64@0.141.0': resolution: {integrity: sha512-cVgDM7n8QziQqOaP5hNgUYfMG7S/ZeuPxFWXnnHRv7rh025COk0rfQ6eEdKG3j/GaUuyvNZN4ifF1J8KmuXLLA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4703,6 +4921,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] + '@oxc-parser/binding-wasm32-wasi@0.139.0': + resolution: {integrity: sha512-rNU0pO+/CVPC2qZ+xtX5R2cOje9Q75q3UkfgwUCPlplqxMv6Iffd5tMPGVMCLGnPINxPlmi0WPsW94HltbYvfQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + '@oxc-parser/binding-wasm32-wasi@0.141.0': resolution: {integrity: sha512-HggH++Fkn3OilBn+bs3jpgIFQa34oMAyUUHy0vpGum+gt1Eb5nyLc8dNU/RAPSw6lsLrx7ncKtHSZE+3Sp0l2g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4725,6 +4948,12 @@ packages: cpu: [arm64] os: [win32] + '@oxc-parser/binding-win32-arm64-msvc@0.139.0': + resolution: {integrity: sha512-JPEmfncZfqAFiGsAN6UZSMIBqnG8wn8buywRacFOWjP+9dZwcs03SsBp4tmyjM/4l/VoH/IuThrW1Jof3OyQUw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@oxc-parser/binding-win32-arm64-msvc@0.141.0': resolution: {integrity: sha512-KLSEH9GwgbrqbJOjtGHt9STw96s+78yDzp7IDN8Lno+7Ut9sNBfZ4jYZIz4mD50qmWUjoOI7i9I6UENbhNbMZQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4743,6 +4972,12 @@ packages: cpu: [ia32] os: [win32] + '@oxc-parser/binding-win32-ia32-msvc@0.139.0': + resolution: {integrity: sha512-c06dWBwEnFHof5JN7T9/ts23uATXS9czPEBO60d4xnjH2Am29Bo7OGKdVHRmcWQnw0OBxlTg9fIEXAvtcwOBfw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + '@oxc-parser/binding-win32-ia32-msvc@0.141.0': resolution: {integrity: sha512-9UVWUOOCI/1YkiSSNjg2zyBJYM9E/t1A/8GNobd48JDn/fQ6mzxcVO3H08jb3rAaW/B1VBf8eCORTvSsO9T08g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4767,6 +5002,12 @@ packages: cpu: [x64] os: [win32] + '@oxc-parser/binding-win32-x64-msvc@0.139.0': + resolution: {integrity: sha512-bI3/44urQjW/D495JPXe+c9d+4Q+ONi3DvDNnzwRZYTWHZ3hAlFdmirYK4mzhTfCZiAly02EbMYir7QGU+9O2Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@oxc-parser/binding-win32-x64-msvc@0.141.0': resolution: {integrity: sha512-HI/wsvbWT5RHHw5c37D0fEgeTd8/1Q4OJs5jUmEBc17VZFG6SsCIe4barq7NsAPPks/JW+3ayi3Rp+PQI5h4Kg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4785,6 +5026,9 @@ packages: '@oxc-project/types@0.133.0': resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + '@oxc-project/types@0.139.0': + resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxc-project/types@0.140.0': resolution: {integrity: sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==} @@ -5740,16 +5984,79 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} + '@solidjs/babel-plugin@2.0.0-rc.13': + resolution: {integrity: sha512-VaNysg2V5gu1leatjxBeRPvj1wTEB1LQ1bKuPABKBGztz/Vjr6bHUYEV2cC1mFuEyNJBaNrAiGv0+5Vpbl8Pug==} + peerDependencies: + '@babel/core': ^7.20.12 + '@tsrx/core': 0.1.63 + peerDependenciesMeta: + '@tsrx/core': + optional: true + + '@solidjs/compiler-darwin-arm64@2.0.0-rc.13': + resolution: {integrity: sha512-uG3Sa/2jNZNxoKkcHjHw3KZEEuwDrRAk9aqUU2qqJZl9GDLLI0HVW7i/Lvq9b17f5yN+fNTdNyojO8rLgHnQuQ==} + cpu: [arm64] + os: [darwin] + + '@solidjs/compiler-darwin-x64@2.0.0-rc.13': + resolution: {integrity: sha512-jIyzyn/fYHmzikOaskiqmkc8FusXMaxl1Z6huh7lEeHaZsl9NIdzzAIxq8j/EJFByvoCyfQitggRTuubGNblpA==} + cpu: [x64] + os: [darwin] + + '@solidjs/compiler-linux-arm64-gnu@2.0.0-rc.13': + resolution: {integrity: sha512-cGIX7ZWTyw3Qdpd5ZqJtHdb2vQkAtZlkTgy919dMldjoRqDwQIRlqCmH35kaH/IUBlhuG224BoP4twqK9GYyGw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@solidjs/compiler-linux-x64-gnu@2.0.0-rc.13': + resolution: {integrity: sha512-Dnft4iic4zHsemNSBGMwOMjN4fP0DEoyfeSUWbqBk1CMsXRarLTcMKhjNQmJvL0opzjOUq0/m7/17LTe6AKpvg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@solidjs/compiler-wasm32-wasi@2.0.0-rc.13': + resolution: {integrity: sha512-nNOMOFxanzfM2wNbSXyekMtGazyOcM3ja+P7tk0NJYTAo2MYmRTY/HUDdFRDluk6Nc5aehu87I7AVMRj5l1WXw==} + engines: {node: '>=14.0.0'} + + '@solidjs/compiler-win32-x64-msvc@2.0.0-rc.13': + resolution: {integrity: sha512-1DT+5TgIFV5L8GdrGb+uD9ruHFVq6kJ4A/cb9amUU574TGM88B4nwy//dM57zmT99u7mej7JF91glQBnHOGhHQ==} + cpu: [x64] + os: [win32] + + '@solidjs/compiler@2.0.0-rc.13': + resolution: {integrity: sha512-OveR/xhLKo8MTJO/53jgjHuBW54c6/a9B/jiSjDrBeQ3JSbODUxQ8t58WBSlHaxyowPd27TwhVkLo3zeT1YqMQ==} + '@solidjs/meta@0.29.4': resolution: {integrity: sha512-zdIWBGpR9zGx1p1bzIPqF5Gs+Ks/BH8R6fWhmUa/dcK1L2rUC8BAcZJzNRYBQv74kScf1TSOs0EY//Vd/I0V8g==} peerDependencies: solid-js: '>=1.8.4' + '@solidjs/meta@1.0.0-next.2': + resolution: {integrity: sha512-4aqPczFqDdep4JTAUXfh4nyfq7InbTgimd7NuN6ZWWE29UPv0uR5dyr53yFcf2YgVXjFdX+JGhXtsE0njGL+fA==} + peerDependencies: + '@solidjs/web': ^2.0.0-rc.0 + solid-js: ^2.0.0-rc.0 + '@solidjs/router@1.0.0': resolution: {integrity: sha512-cCSk1hvgCowiMa9bzzYWHiLu1U4E22+DfJe6/rOwAyECKrxc3jrd5QnoW3sDDJtW+e077cz/M67bPl3DqOBw1Q==} peerDependencies: solid-js: ^1.8.6 + '@solidjs/router@2.0.0-next.34': + resolution: {integrity: sha512-XRmCQUOPpz6EYp6MyDqtC4KdToXayk/hYv0/jFdSjnmUDjYAi9l6HpTMxADnz1Sv1kX8Jn6DVbsDJTrxC+fU5Q==} + peerDependencies: + '@solidjs/web': ^2.0.0-rc.13 + filesystem-routing: '>=0.4.0' + solid-js: ^2.0.0-rc.13 + peerDependenciesMeta: + filesystem-routing: + optional: true + + '@solidjs/signals@2.0.0-rc.13': + resolution: {integrity: sha512-4+pRdrAHtfyE9BUJWBup3TpzJojJjgW2mV1vm/Jik4tWa5epxXB/YrLkwqP1v8+S9XjyKKZu5BSLqmcpswMYeQ==} + engines: {node: '>=22.12.0'} + '@solidjs/start@2.0.5': resolution: {integrity: sha512-Kji79Kan867rKAx8iG0W4BXzj/J2nXyGwgS6+mNA4vqLabqLMeXfY/O910JnMLHRKMZZ9Xfr4hh+DYUDuSSPCw==} engines: {node: '>=24'} @@ -5770,6 +6077,49 @@ packages: '@solidjs/router': optional: true + '@solidjs/testing-library@1.0.0-beta.3': + resolution: {integrity: sha512-yJtAa6H76xr5lSkT7LVmaaTFCZZzxcwejzQ4UBV/+koZFByVZ5J0XMDVHZ539PGso+fyncI5iRxWyDWFqhtcLg==} + engines: {node: '>= 14'} + peerDependencies: + '@solidjs/web': '>=2.0.0-0' + solid-js: '>=2.0.0-0' + + '@solidjs/vite-plugin@3.0.0-next.35': + resolution: {integrity: sha512-8Mlftd+WfZkwOoCZRyMxA8innT8b2D/qawTu+28RW/Hj4eSmStSLx4dHjYeH9MxyOwo7DQStAyHAADk5LFQVRw==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@solidjs/start-devtools': ^1.0.0-next.2 + '@solidjs/web': ^2.0.0-rc.0 + '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* + solid-js: ^2.0.0-rc.0 + vite: ^8.3.2 + peerDependenciesMeta: + '@solidjs/start-devtools': + optional: true + '@testing-library/jest-dom': + optional: true + + '@solidjs/vite-plugin@3.0.0-next.47': + resolution: {integrity: sha512-vcsZbXkTCt2RalJmUPp25iz+7KYGriP9w54BLf5uIJ0xDf5woTN92WdlDCh0udZV/Zb2xw2qrWQA977QeuScJw==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@solidjs/start-devtools': ^1.0.0-next.2 + '@solidjs/web': ^2.0.0-rc.13 + '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.0.0 || ^7.0.0 + solid-js: ^2.0.0-rc.13 + vite: ^8.3.2 + peerDependenciesMeta: + '@solidjs/start-devtools': + optional: true + '@testing-library/jest-dom': + optional: true + + '@solidjs/web@2.0.0-rc.13': + resolution: {integrity: sha512-vI/7v/XM8B/3U/oKAzCW2VjTLFkM5IArB2DFnrjxyPRYD3FX9KAXg9QuAnPIPQHC/xvg/LgxmvoVfZUfJ96gOQ==} + engines: {node: '>=22.12.0'} + peerDependencies: + solid-js: ^2.0.0-rc.13 + '@speed-highlight/core@1.2.24': resolution: {integrity: sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==} @@ -6297,9 +6647,6 @@ packages: peerDependencies: '@types/react': ^19.3.0 - '@types/react@18.3.31': - resolution: {integrity: sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==} - '@types/react@19.3.0': resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==} @@ -7308,6 +7655,15 @@ packages: solid-js: optional: true + babel-preset-solid@2.0.0-rc.2: + resolution: {integrity: sha512-Venq++Aa6+RzGIAyS5vSo3kX1fE8zRreEPCh1eTh5DTjlTft9qZGIG14RSZDv/sjVxT8x5Gs9+21PzxuLe8U+g==} + peerDependencies: + '@babel/core': ^7.0.0 + solid-js: ^2.0.0-rc.2 + peerDependenciesMeta: + solid-js: + optional: true + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -8695,6 +9051,17 @@ packages: resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} engines: {node: '>= 10.4.0'} + filesystem-routing@0.4.0: + resolution: {integrity: sha512-HSGdLhrkYgF4/E0IKxirCShkrGUfvavQuOOP2Nio0dCxp/PrhiATGWQPUODUJuDavD+N6hIp1K7e/rh347o9nw==} + peerDependencies: + '@tsrx/oxc': '>=0.9.0' + vite: ^8.3.2 + peerDependenciesMeta: + '@tsrx/oxc': + optional: true + vite: + optional: true + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -10668,6 +11035,10 @@ packages: resolution: {integrity: sha512-661RSx+ZcjBmjBYid+Fpp/2F5EbtildpeoZh5HdgnGs+jZ03nqQEQW8yGkt4BGyOC3OMPDQQRl8M5kqD2/g6jw==} engines: {node: ^20.19.0 || >=22.12.0} + oxc-parser@0.139.0: + resolution: {integrity: sha512-cf1TKZN+zc0lwqigeyXKzKVk5+vNRe99Or2+wVJsXLdlhJgC+gsIniYDfj/ZEBzCJ8Xm21ZG6YtMbR262CcS2w==} + engines: {node: ^20.19.0 || >=22.12.0} + oxc-parser@0.141.0: resolution: {integrity: sha512-uFkGGr1KMWd6aWv9UAqooYrN78trw8MWWmoPvgWokfBEUq1+eiIQ+qfj3wokhy0fxtZWZk+0dHoS7/yRTJtd6w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -11832,6 +12203,10 @@ packages: solid-js@1.9.15: resolution: {integrity: sha512-EeiY2xfpZJqPLjXspVEKjAII4yv8NyG//NxZ3IpOFHdUNnnTyL0uJOeS9LWGvA7cFCz5y94cjFwYlmw5Luncsg==} + solid-js@2.0.0-rc.13: + resolution: {integrity: sha512-62bYOI4JZ15KOqL5eReKyWSwAXrGb0fbX8SDnHsbJk2UX+SzSyy1gobas2cxW/0BXcobGfQ1V6ffPyQkMIBdoQ==} + engines: {node: '>=22.12.0'} + solid-refresh@0.6.3: resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} peerDependencies: @@ -12755,6 +13130,9 @@ packages: typescript: optional: true + validate-html-nesting@1.2.4: + resolution: {integrity: sha512-doQi7e8EJ2OWneSG1aZpJluS6A49aZM0+EICXWKm1i6WvqTLmq0tpUcImc4KTWG50mORO0C4YDBtOCSYvElftw==} + validate-npm-package-name@8.0.0: resolution: {integrity: sha512-SCv6OOV6Xj2/3cXy3dGmADluJTNcL3o7hZAglNPTe+WYuEuvxgJzxPrSDLZhF+CwyQOubqgecjMmTJGMVLWjYQ==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} @@ -15304,9 +15682,9 @@ snapshots: '@docsearch/css@3.8.2': {} - '@docsearch/js@3.8.2(@algolia/client-search@5.57.0)(@types/react@18.3.31)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.8.2)': + '@docsearch/js@3.8.2(@algolia/client-search@5.57.0)(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.8.2)': dependencies: - '@docsearch/react': 3.8.2(@algolia/client-search@5.57.0)(@types/react@18.3.31)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.8.2) + '@docsearch/react': 3.8.2(@algolia/client-search@5.57.0)(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.8.2) preact: 10.29.8 transitivePeerDependencies: - '@algolia/client-search' @@ -15316,20 +15694,30 @@ snapshots: - react-dom - search-insights - '@docsearch/react@3.8.2(@algolia/client-search@5.57.0)(@types/react@18.3.31)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.8.2)': + '@docsearch/react@3.8.2(@algolia/client-search@5.57.0)(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.8.2)': dependencies: '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.57.0)(algoliasearch@5.57.0)(search-insights@2.8.2) '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.57.0)(algoliasearch@5.57.0) '@docsearch/css': 3.8.2 algoliasearch: 5.57.0 optionalDependencies: - '@types/react': 18.3.31 + '@types/react': 19.3.0 react: 19.3.0 react-dom: 19.3.0(react@19.3.0) search-insights: 2.8.2 transitivePeerDependencies: - '@algolia/client-search' + '@dom-expressions/babel-plugin-jsx@0.50.0-next.44(@babel/core@7.29.7(supports-color@10.2.2))': + dependencies: + '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/helper-module-imports': 7.18.6 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/types': 7.29.8 + html-entities: 2.3.3 + parse5: 7.3.0 + validate-html-nesting: 1.2.4 + '@dxup/nuxt@0.4.1(magicast@0.5.4)(typescript@6.0.3)': dependencies: '@dxup/unimport': 0.1.2 @@ -16788,7 +17176,7 @@ snapshots: pathe: 2.0.3 pkg-types: 2.3.2 postcss: 8.5.28 - seroval: 1.6.4 + seroval: 1.6.7 std-env: 4.2.0 ufo: 1.6.4 unenv: 2.0.0-rc.24 @@ -16985,6 +17373,9 @@ snapshots: '@oxc-parser/binding-android-arm-eabi@0.133.0': optional: true + '@oxc-parser/binding-android-arm-eabi@0.139.0': + optional: true + '@oxc-parser/binding-android-arm-eabi@0.141.0': optional: true @@ -16997,6 +17388,9 @@ snapshots: '@oxc-parser/binding-android-arm64@0.133.0': optional: true + '@oxc-parser/binding-android-arm64@0.139.0': + optional: true + '@oxc-parser/binding-android-arm64@0.141.0': optional: true @@ -17009,6 +17403,9 @@ snapshots: '@oxc-parser/binding-darwin-arm64@0.133.0': optional: true + '@oxc-parser/binding-darwin-arm64@0.139.0': + optional: true + '@oxc-parser/binding-darwin-arm64@0.141.0': optional: true @@ -17021,6 +17418,9 @@ snapshots: '@oxc-parser/binding-darwin-x64@0.133.0': optional: true + '@oxc-parser/binding-darwin-x64@0.139.0': + optional: true + '@oxc-parser/binding-darwin-x64@0.141.0': optional: true @@ -17033,6 +17433,9 @@ snapshots: '@oxc-parser/binding-freebsd-x64@0.133.0': optional: true + '@oxc-parser/binding-freebsd-x64@0.139.0': + optional: true + '@oxc-parser/binding-freebsd-x64@0.141.0': optional: true @@ -17045,6 +17448,9 @@ snapshots: '@oxc-parser/binding-linux-arm-gnueabihf@0.133.0': optional: true + '@oxc-parser/binding-linux-arm-gnueabihf@0.139.0': + optional: true + '@oxc-parser/binding-linux-arm-gnueabihf@0.141.0': optional: true @@ -17054,6 +17460,9 @@ snapshots: '@oxc-parser/binding-linux-arm-musleabihf@0.133.0': optional: true + '@oxc-parser/binding-linux-arm-musleabihf@0.139.0': + optional: true + '@oxc-parser/binding-linux-arm-musleabihf@0.141.0': optional: true @@ -17066,6 +17475,9 @@ snapshots: '@oxc-parser/binding-linux-arm64-gnu@0.133.0': optional: true + '@oxc-parser/binding-linux-arm64-gnu@0.139.0': + optional: true + '@oxc-parser/binding-linux-arm64-gnu@0.141.0': optional: true @@ -17078,6 +17490,9 @@ snapshots: '@oxc-parser/binding-linux-arm64-musl@0.133.0': optional: true + '@oxc-parser/binding-linux-arm64-musl@0.139.0': + optional: true + '@oxc-parser/binding-linux-arm64-musl@0.141.0': optional: true @@ -17087,6 +17502,9 @@ snapshots: '@oxc-parser/binding-linux-ppc64-gnu@0.133.0': optional: true + '@oxc-parser/binding-linux-ppc64-gnu@0.139.0': + optional: true + '@oxc-parser/binding-linux-ppc64-gnu@0.141.0': optional: true @@ -17099,6 +17517,9 @@ snapshots: '@oxc-parser/binding-linux-riscv64-gnu@0.133.0': optional: true + '@oxc-parser/binding-linux-riscv64-gnu@0.139.0': + optional: true + '@oxc-parser/binding-linux-riscv64-gnu@0.141.0': optional: true @@ -17108,6 +17529,9 @@ snapshots: '@oxc-parser/binding-linux-riscv64-musl@0.133.0': optional: true + '@oxc-parser/binding-linux-riscv64-musl@0.139.0': + optional: true + '@oxc-parser/binding-linux-riscv64-musl@0.141.0': optional: true @@ -17120,6 +17544,9 @@ snapshots: '@oxc-parser/binding-linux-s390x-gnu@0.133.0': optional: true + '@oxc-parser/binding-linux-s390x-gnu@0.139.0': + optional: true + '@oxc-parser/binding-linux-s390x-gnu@0.141.0': optional: true @@ -17132,6 +17559,9 @@ snapshots: '@oxc-parser/binding-linux-x64-gnu@0.133.0': optional: true + '@oxc-parser/binding-linux-x64-gnu@0.139.0': + optional: true + '@oxc-parser/binding-linux-x64-gnu@0.141.0': optional: true @@ -17144,6 +17574,9 @@ snapshots: '@oxc-parser/binding-linux-x64-musl@0.133.0': optional: true + '@oxc-parser/binding-linux-x64-musl@0.139.0': + optional: true + '@oxc-parser/binding-linux-x64-musl@0.141.0': optional: true @@ -17156,6 +17589,9 @@ snapshots: '@oxc-parser/binding-openharmony-arm64@0.133.0': optional: true + '@oxc-parser/binding-openharmony-arm64@0.139.0': + optional: true + '@oxc-parser/binding-openharmony-arm64@0.141.0': optional: true @@ -17177,6 +17613,13 @@ snapshots: '@napi-rs/wasm-runtime': 1.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true + '@oxc-parser/binding-wasm32-wasi@0.139.0': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.2.4(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + '@oxc-parser/binding-wasm32-wasi@0.141.0': dependencies: '@emnapi/core': 1.11.2 @@ -17197,6 +17640,9 @@ snapshots: '@oxc-parser/binding-win32-arm64-msvc@0.133.0': optional: true + '@oxc-parser/binding-win32-arm64-msvc@0.139.0': + optional: true + '@oxc-parser/binding-win32-arm64-msvc@0.141.0': optional: true @@ -17206,6 +17652,9 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc@0.133.0': optional: true + '@oxc-parser/binding-win32-ia32-msvc@0.139.0': + optional: true + '@oxc-parser/binding-win32-ia32-msvc@0.141.0': optional: true @@ -17218,6 +17667,9 @@ snapshots: '@oxc-parser/binding-win32-x64-msvc@0.133.0': optional: true + '@oxc-parser/binding-win32-x64-msvc@0.139.0': + optional: true + '@oxc-parser/binding-win32-x64-msvc@0.141.0': optional: true @@ -17228,6 +17680,8 @@ snapshots: '@oxc-project/types@0.133.0': {} + '@oxc-project/types@0.139.0': {} + '@oxc-project/types@0.140.0': {} '@oxc-project/types@0.141.0': {} @@ -17959,14 +18413,68 @@ snapshots: '@sindresorhus/merge-streams@4.0.0': {} + '@solidjs/babel-plugin@2.0.0-rc.13(@babel/core@7.29.7(supports-color@10.2.2))': + dependencies: + '@babel/core': 7.29.7(supports-color@10.2.2) + '@babel/helper-module-imports': 7.18.6 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2)) + '@babel/types': 7.29.8 + html-entities: 2.3.3 + parse5: 7.3.0 + + '@solidjs/compiler-darwin-arm64@2.0.0-rc.13': + optional: true + + '@solidjs/compiler-darwin-x64@2.0.0-rc.13': + optional: true + + '@solidjs/compiler-linux-arm64-gnu@2.0.0-rc.13': + optional: true + + '@solidjs/compiler-linux-x64-gnu@2.0.0-rc.13': + optional: true + + '@solidjs/compiler-wasm32-wasi@2.0.0-rc.13': + dependencies: + '@emnapi/core': 1.11.3 + '@emnapi/runtime': 1.11.3 + '@napi-rs/wasm-runtime': 1.2.4(@emnapi/core@1.11.3)(@emnapi/runtime@1.11.3) + optional: true + + '@solidjs/compiler-win32-x64-msvc@2.0.0-rc.13': + optional: true + + '@solidjs/compiler@2.0.0-rc.13': + optionalDependencies: + '@solidjs/compiler-darwin-arm64': 2.0.0-rc.13 + '@solidjs/compiler-darwin-x64': 2.0.0-rc.13 + '@solidjs/compiler-linux-arm64-gnu': 2.0.0-rc.13 + '@solidjs/compiler-linux-x64-gnu': 2.0.0-rc.13 + '@solidjs/compiler-wasm32-wasi': 2.0.0-rc.13 + '@solidjs/compiler-win32-x64-msvc': 2.0.0-rc.13 + '@solidjs/meta@0.29.4(solid-js@1.9.15)': dependencies: solid-js: 1.9.15 + '@solidjs/meta@1.0.0-next.2(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(solid-js@2.0.0-rc.13)': + dependencies: + '@solidjs/web': 2.0.0-rc.13(solid-js@2.0.0-rc.13) + solid-js: 2.0.0-rc.13 + '@solidjs/router@1.0.0(solid-js@1.9.15)': dependencies: solid-js: 1.9.15 + '@solidjs/router@2.0.0-next.34(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(filesystem-routing@0.4.0(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)))(solid-js@2.0.0-rc.13)': + dependencies: + '@solidjs/web': 2.0.0-rc.13(solid-js@2.0.0-rc.13) + solid-js: 2.0.0-rc.13 + optionalDependencies: + filesystem-routing: 0.4.0(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)) + + '@solidjs/signals@2.0.0-rc.13': {} + '@solidjs/start@2.0.5(@solidjs/router@1.0.0(solid-js@1.9.15))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.3))(crossws@0.4.12(srvx@1.0.5))(ocache@0.3.0)(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) @@ -18010,6 +18518,54 @@ snapshots: optionalDependencies: '@solidjs/router': 1.0.0(solid-js@1.9.15) + '@solidjs/testing-library@1.0.0-beta.3(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(solid-js@2.0.0-rc.13)': + dependencies: + '@solidjs/web': 2.0.0-rc.13(solid-js@2.0.0-rc.13) + '@testing-library/dom': 10.4.1 + solid-js: 2.0.0-rc.13 + + '@solidjs/vite-plugin@3.0.0-next.35(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.3))(solid-js@2.0.0-rc.13)(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/core': 7.29.7(supports-color@10.2.2) + '@solidjs/babel-plugin': 2.0.0-rc.13(@babel/core@7.29.7(supports-color@10.2.2)) + '@solidjs/compiler': 2.0.0-rc.13 + '@solidjs/web': 2.0.0-rc.13(solid-js@2.0.0-rc.13) + '@types/babel__core': 7.20.5 + merge-anything: 5.1.7 + solid-js: 2.0.0-rc.13 + vite: 8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0) + vitefu: 1.1.3(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)) + optionalDependencies: + '@testing-library/jest-dom': 7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.3) + transitivePeerDependencies: + - '@tsrx/core' + - supports-color + + '@solidjs/vite-plugin@3.0.0-next.47(@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.3))(solid-js@2.0.0-rc.13)(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/core': 7.29.7(supports-color@10.2.2) + '@solidjs/babel-plugin': 2.0.0-rc.13(@babel/core@7.29.7(supports-color@10.2.2)) + '@solidjs/compiler': 2.0.0-rc.13 + '@solidjs/web': 2.0.0-rc.13(solid-js@2.0.0-rc.13) + '@types/babel__core': 7.20.5 + merge-anything: 5.1.7 + solid-js: 2.0.0-rc.13 + vite: 8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0) + vitefu: 1.1.3(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)) + optionalDependencies: + '@testing-library/jest-dom': 7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.3) + transitivePeerDependencies: + - '@tsrx/core' + - supports-color + + '@solidjs/web@2.0.0-rc.13(solid-js@2.0.0-rc.13)': + dependencies: + seroval: 1.6.7 + seroval-plugins: 1.6.7(seroval@1.6.7) + solid-js: 2.0.0-rc.13 + '@speed-highlight/core@1.2.24': {} '@standard-schema/spec@1.1.0': {} @@ -18215,8 +18771,8 @@ snapshots: dependencies: '@tanstack/history': 1.162.1 cookie-es: 3.1.1 - seroval: 1.6.4 - seroval-plugins: 1.6.4(seroval@1.6.4) + seroval: 1.6.7 + seroval-plugins: 1.6.7(seroval@1.6.7) '@tanstack/router-core@1.171.34': dependencies: @@ -18646,12 +19202,6 @@ snapshots: dependencies: '@types/react': 19.3.0 - '@types/react@18.3.31': - dependencies: - '@types/prop-types': 15.7.15 - csstype: 3.2.3 - optional: true - '@types/react@19.3.0': dependencies: csstype: 3.2.3 @@ -19917,6 +20467,13 @@ snapshots: optionalDependencies: solid-js: 1.9.15 + babel-preset-solid@2.0.0-rc.2(@babel/core@7.29.7(supports-color@10.2.2))(solid-js@2.0.0-rc.13): + dependencies: + '@babel/core': 7.29.7(supports-color@10.2.2) + '@dom-expressions/babel-plugin-jsx': 0.50.0-next.44(@babel/core@7.29.7(supports-color@10.2.2)) + optionalDependencies: + solid-js: 2.0.0-rc.13 + bail@2.0.2: {} balanced-match@1.0.2: {} @@ -21486,6 +22043,21 @@ snapshots: filesize@10.1.6: {} + filesystem-routing@0.4.0(supports-color@10.2.2)(vite@8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0)): + dependencies: + '@babel/core': 7.29.7(supports-color@10.2.2) + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.28.0 + '@types/micromatch': 4.0.10 + fast-glob: 3.3.3 + micromatch: 4.0.8 + oxc-parser: 0.139.0 + radix3: 1.1.2 + optionalDependencies: + vite: 8.3.2(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass@1.103.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.0) + transitivePeerDependencies: + - supports-color + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -24252,6 +24824,31 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc': 0.133.0 '@oxc-parser/binding-win32-x64-msvc': 0.133.0 + oxc-parser@0.139.0: + dependencies: + '@oxc-project/types': 0.139.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.139.0 + '@oxc-parser/binding-android-arm64': 0.139.0 + '@oxc-parser/binding-darwin-arm64': 0.139.0 + '@oxc-parser/binding-darwin-x64': 0.139.0 + '@oxc-parser/binding-freebsd-x64': 0.139.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.139.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.139.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.139.0 + '@oxc-parser/binding-linux-arm64-musl': 0.139.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.139.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.139.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.139.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.139.0 + '@oxc-parser/binding-linux-x64-gnu': 0.139.0 + '@oxc-parser/binding-linux-x64-musl': 0.139.0 + '@oxc-parser/binding-openharmony-arm64': 0.139.0 + '@oxc-parser/binding-wasm32-wasi': 0.139.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.139.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.139.0 + '@oxc-parser/binding-win32-x64-msvc': 0.139.0 + oxc-parser@0.141.0: dependencies: '@oxc-project/types': 0.141.0 @@ -25664,6 +26261,13 @@ snapshots: seroval: 1.5.6 seroval-plugins: 1.5.6(seroval@1.5.6) + solid-js@2.0.0-rc.13: + dependencies: + '@solidjs/signals': 2.0.0-rc.13 + csstype: 3.2.3 + seroval: 1.6.7 + seroval-plugins: 1.6.7(seroval@1.6.7) + solid-refresh@0.6.3(solid-js@1.9.15)(supports-color@10.2.2): dependencies: '@babel/generator': 7.29.8 @@ -26645,6 +27249,8 @@ snapshots: optionalDependencies: typescript: 6.0.3 + validate-html-nesting@1.2.4: {} + validate-npm-package-name@8.0.0: {} validator@13.15.35: {} @@ -26899,10 +27505,10 @@ snapshots: transitivePeerDependencies: - supports-color - vitepress@1.6.4(@algolia/client-search@5.57.0)(@types/node@26.4.1)(@types/react@18.3.31)(esbuild@0.28.2)(fuse.js@7.5.0)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(postcss@8.5.28)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(sass@1.103.1)(search-insights@2.8.2)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(typescript@6.0.3)(yaml@2.9.0): + vitepress@1.6.4(@algolia/client-search@5.57.0)(@types/node@26.4.1)(@types/react@19.3.0)(esbuild@0.28.2)(fuse.js@7.5.0)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(postcss@8.5.28)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(sass@1.103.1)(search-insights@2.8.2)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(typescript@6.0.3)(yaml@2.9.0): dependencies: '@docsearch/css': 3.8.2 - '@docsearch/js': 3.8.2(@algolia/client-search@5.57.0)(@types/react@18.3.31)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.8.2) + '@docsearch/js': 3.8.2(@algolia/client-search@5.57.0)(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(search-insights@2.8.2) '@iconify-json/simple-icons': 1.2.94 '@shikijs/core': 2.5.0 '@shikijs/transformers': 2.5.0