Full Code of MIERUNE/svelte-maplibre-gl for AI

main f031cbb0cbc5 cached
294 files
317.6 KB
104.3k tokens
48 symbols
1 requests
Download .txt
Showing preview only (386K chars total). Download the full file or copy to clipboard to get everything.
Repository: MIERUNE/svelte-maplibre-gl
Branch: main
Commit: f031cbb0cbc5
Files: 294
Total size: 317.6 KB

Directory structure:
gitextract_qlcdzk6r/

├── .changeset/
│   ├── README.md
│   └── config.json
├── .github/
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── lint.yml
│       ├── preview.yml
│       └── release.yml
├── .gitignore
├── .node-version
├── .npmrc
├── .prettierignore
├── .prettierrc
├── LICENSE-APACHE.txt
├── LICENSE-MIT.txt
├── README.md
├── components.json
├── e2e/
│   └── demo.test.ts
├── eslint.config.js
├── extensions/
│   ├── contour/
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── app.d.ts
│   │   │   ├── app.html
│   │   │   └── lib/
│   │   │       ├── MapLibreContourSource.svelte
│   │   │       └── index.ts
│   │   ├── svelte.config.js
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── deckgl/
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── app.d.ts
│   │   │   ├── app.html
│   │   │   └── lib/
│   │   │       ├── DeckGLOverlay.svelte
│   │   │       └── index.ts
│   │   ├── svelte.config.js
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── pmtiles/
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── app.d.ts
│   │   │   ├── app.html
│   │   │   └── lib/
│   │   │       ├── PMTilesProtocol.svelte
│   │   │       └── index.ts
│   │   ├── svelte.config.js
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   └── terradraw/
│       ├── CHANGELOG.md
│       ├── package.json
│       ├── src/
│       │   ├── app.d.ts
│       │   ├── app.html
│       │   └── lib/
│       │       ├── TerraDraw.svelte
│       │       └── index.ts
│       ├── svelte.config.js
│       ├── tsconfig.json
│       └── vite.config.ts
├── package.json
├── playwright.config.ts
├── pnpm-workspace.yaml
├── src/
│   ├── app.css
│   ├── app.d.ts
│   ├── app.html
│   ├── content/
│   │   ├── CodeBlock.svelte
│   │   ├── components/
│   │   │   └── toc.ts
│   │   ├── docs/
│   │   │   ├── quickstart/
│   │   │   │   ├── Marker.svelte
│   │   │   │   ├── Simplest.svelte
│   │   │   │   └── content.svelte.md
│   │   │   └── toc.ts
│   │   └── examples/
│   │       ├── 3d-buildings/
│   │       │   ├── Buildings3D.svelte
│   │       │   └── content.svelte.md
│   │       ├── 3d-extrusion-floorplan/
│   │       │   ├── Floorplan.svelte
│   │       │   └── content.svelte.md
│   │       ├── animate-images/
│   │       │   ├── AnimateImages.svelte
│   │       │   └── content.svelte.md
│   │       ├── basestyle/
│   │       │   ├── BaseStyle.svelte
│   │       │   └── content.svelte.md
│   │       ├── canvas-source/
│   │       │   ├── Canvas.svelte
│   │       │   ├── Circle.ts
│   │       │   └── content.svelte.md
│   │       ├── clusters/
│   │       │   ├── Clusters.svelte
│   │       │   └── content.svelte.md
│   │       ├── color-relief/
│   │       │   ├── ColorRelief.svelte
│   │       │   └── content.svelte.md
│   │       ├── complex/
│   │       │   ├── Complex.svelte
│   │       │   └── content.svelte.md
│   │       ├── contour/
│   │       │   ├── Contour.svelte
│   │       │   └── content.svelte.md
│   │       ├── cursor/
│   │       │   ├── Cursor.svelte
│   │       │   └── content.svelte.md
│   │       ├── custom-control/
│   │       │   ├── CustomControl.svelte
│   │       │   ├── MyControl.ts
│   │       │   └── content.svelte.md
│   │       ├── custom-layer/
│   │       │   ├── CustomLayer.svelte
│   │       │   └── content.svelte.md
│   │       ├── custom-protocol/
│   │       │   ├── CustomProtocol.svelte
│   │       │   └── content.svelte.md
│   │       ├── deckgl-overlay/
│   │       │   ├── DeckGL.svelte
│   │       │   └── content.svelte.md
│   │       ├── dynamic-image/
│   │       │   ├── DynamicImage.svelte
│   │       │   └── content.svelte.md
│   │       ├── fullscreen/
│   │       │   ├── Fullscreen.svelte
│   │       │   └── content.svelte.md
│   │       ├── geolocate/
│   │       │   ├── Geolocate.svelte
│   │       │   └── content.svelte.md
│   │       ├── global-state/
│   │       │   ├── Plain.svelte
│   │       │   └── content.svelte.md
│   │       ├── globe-atmosphere/
│   │       │   ├── Globe.svelte
│   │       │   └── content.svelte.md
│   │       ├── hover-styles/
│   │       │   ├── HoverStyles.svelte
│   │       │   └── content.svelte.md
│   │       ├── image-loader/
│   │       │   ├── Images.svelte
│   │       │   └── content.svelte.md
│   │       ├── limit-interaction/
│   │       │   ├── LimitInteraction.svelte
│   │       │   └── content.svelte.md
│   │       ├── marker-popup/
│   │       │   ├── MarkerAndPopup.svelte
│   │       │   └── content.svelte.md
│   │       ├── plain/
│   │       │   ├── Plain.svelte
│   │       │   └── content.svelte.md
│   │       ├── pmtiles/
│   │       │   ├── PMTiles.svelte
│   │       │   └── content.svelte.md
│   │       ├── query-features/
│   │       │   ├── Query.svelte
│   │       │   └── content.svelte.md
│   │       ├── side-by-side/
│   │       │   ├── SideBySide.svelte
│   │       │   └── content.svelte.md
│   │       ├── terradraw/
│   │       │   ├── TerraDraw.svelte
│   │       │   └── content.svelte.md
│   │       ├── terrain/
│   │       │   ├── Terrain.svelte
│   │       │   └── content.svelte.md
│   │       ├── threejs-model/
│   │       │   ├── CustomLayer.svelte
│   │       │   └── content.svelte.md
│   │       ├── toc.ts
│   │       └── video-on-a-map/
│   │           ├── Video.svelte
│   │           └── content.svelte.md
│   ├── demo.spec.ts
│   ├── lib/
│   │   ├── assets/
│   │   │   ├── fonts/
│   │   │   │   ├── LICENSE.txt
│   │   │   │   └── geist.css
│   │   │   └── icons/
│   │   │       └── GitHub.svelte
│   │   ├── components/
│   │   │   ├── Index.svelte
│   │   │   ├── types.ts
│   │   │   └── ui/
│   │   │       ├── badge/
│   │   │       │   ├── badge.svelte
│   │   │       │   └── index.ts
│   │   │       ├── breadcrumb/
│   │   │       │   ├── breadcrumb-ellipsis.svelte
│   │   │       │   ├── breadcrumb-item.svelte
│   │   │       │   ├── breadcrumb-link.svelte
│   │   │       │   ├── breadcrumb-list.svelte
│   │   │       │   ├── breadcrumb-page.svelte
│   │   │       │   ├── breadcrumb-separator.svelte
│   │   │       │   ├── breadcrumb.svelte
│   │   │       │   └── index.ts
│   │   │       ├── button/
│   │   │       │   ├── button.svelte
│   │   │       │   └── index.ts
│   │   │       ├── checkbox/
│   │   │       │   ├── checkbox.svelte
│   │   │       │   └── index.ts
│   │   │       ├── dropdown-menu/
│   │   │       │   ├── dropdown-menu-checkbox-group.svelte
│   │   │       │   ├── dropdown-menu-checkbox-item.svelte
│   │   │       │   ├── dropdown-menu-content.svelte
│   │   │       │   ├── dropdown-menu-group-heading.svelte
│   │   │       │   ├── dropdown-menu-group.svelte
│   │   │       │   ├── dropdown-menu-item.svelte
│   │   │       │   ├── dropdown-menu-label.svelte
│   │   │       │   ├── dropdown-menu-portal.svelte
│   │   │       │   ├── dropdown-menu-radio-group.svelte
│   │   │       │   ├── dropdown-menu-radio-item.svelte
│   │   │       │   ├── dropdown-menu-separator.svelte
│   │   │       │   ├── dropdown-menu-shortcut.svelte
│   │   │       │   ├── dropdown-menu-sub-content.svelte
│   │   │       │   ├── dropdown-menu-sub-trigger.svelte
│   │   │       │   ├── dropdown-menu-sub.svelte
│   │   │       │   ├── dropdown-menu-trigger.svelte
│   │   │       │   ├── dropdown-menu.svelte
│   │   │       │   └── index.ts
│   │   │       ├── label/
│   │   │       │   ├── index.ts
│   │   │       │   └── label.svelte
│   │   │       ├── radio-group/
│   │   │       │   ├── index.ts
│   │   │       │   ├── radio-group-item.svelte
│   │   │       │   └── radio-group.svelte
│   │   │       ├── select/
│   │   │       │   ├── index.ts
│   │   │       │   ├── select-content.svelte
│   │   │       │   ├── select-group-heading.svelte
│   │   │       │   ├── select-group.svelte
│   │   │       │   ├── select-item.svelte
│   │   │       │   ├── select-label.svelte
│   │   │       │   ├── select-portal.svelte
│   │   │       │   ├── select-scroll-down-button.svelte
│   │   │       │   ├── select-scroll-up-button.svelte
│   │   │       │   ├── select-separator.svelte
│   │   │       │   ├── select-trigger.svelte
│   │   │       │   └── select.svelte
│   │   │       ├── separator/
│   │   │       │   ├── index.ts
│   │   │       │   └── separator.svelte
│   │   │       ├── slider/
│   │   │       │   ├── index.ts
│   │   │       │   └── slider.svelte
│   │   │       ├── switch/
│   │   │       │   ├── index.ts
│   │   │       │   └── switch.svelte
│   │   │       ├── table/
│   │   │       │   ├── index.ts
│   │   │       │   ├── table-body.svelte
│   │   │       │   ├── table-caption.svelte
│   │   │       │   ├── table-cell.svelte
│   │   │       │   ├── table-footer.svelte
│   │   │       │   ├── table-head.svelte
│   │   │       │   ├── table-header.svelte
│   │   │       │   ├── table-row.svelte
│   │   │       │   └── table.svelte
│   │   │       └── tabs/
│   │   │           ├── index.ts
│   │   │           ├── tabs-content.svelte
│   │   │           ├── tabs-list.svelte
│   │   │           ├── tabs-trigger.svelte
│   │   │           └── tabs.svelte
│   │   └── utils.ts
│   └── routes/
│       ├── +layout.server.ts
│       ├── +layout.svelte
│       ├── +page.svelte
│       ├── DarkModeSelector.svelte
│       ├── GlobalToc.svelte
│       ├── Header.svelte
│       ├── ViewTransition.svelte
│       ├── docs/
│       │   ├── +layout.ts
│       │   ├── +page.svelte
│       │   ├── [slug]/
│       │   │   ├── +layout.svelte
│       │   │   ├── +page.svelte
│       │   │   └── +page.ts
│       │   └── components/
│       │       ├── +page.svelte
│       │       ├── [slug]/
│       │       │   ├── _+layout.svelte_
│       │       │   ├── _+page.svelte_
│       │       │   ├── _+page.ts_
│       │       │   ├── _Prop.svelte_
│       │       │   └── _utils.ts_
│       │       └── components.json
│       ├── examples/
│       │   ├── +layout.ts
│       │   ├── +page.svelte
│       │   └── [slug]/
│       │       ├── +layout.svelte
│       │       ├── +page.svelte
│       │       └── +page.ts
│       └── sitemap.xml/
│           └── +server.ts
├── svelte-maplibre-gl/
│   ├── CHANGELOG.md
│   ├── package.json
│   ├── src/
│   │   ├── app.d.ts
│   │   ├── app.html
│   │   └── lib/
│   │       ├── contexts.svelte.ts
│   │       ├── controls/
│   │       │   ├── AttributionControl.svelte
│   │       │   ├── CustomControl.svelte
│   │       │   ├── FullScreenControl.svelte
│   │       │   ├── GeolocateControl.svelte
│   │       │   ├── GlobeControl.svelte
│   │       │   ├── Hash.svelte
│   │       │   ├── LogoControl.svelte
│   │       │   ├── NavigationControl.svelte
│   │       │   ├── ScaleControl.svelte
│   │       │   └── TerrainControl.svelte
│   │       ├── global/
│   │       │   └── Protocol.svelte
│   │       ├── index.ts
│   │       ├── layers/
│   │       │   ├── BackgroundLayer.svelte
│   │       │   ├── CircleLayer.svelte
│   │       │   ├── ColorReliefLayer.svelte
│   │       │   ├── CustomLayer.svelte
│   │       │   ├── FillExtrusionLayer.svelte
│   │       │   ├── FillLayer.svelte
│   │       │   ├── HeatmapLayer.svelte
│   │       │   ├── HillshadeLayer.svelte
│   │       │   ├── LineLayer.svelte
│   │       │   ├── RasterLayer.svelte
│   │       │   ├── RawLayer.svelte
│   │       │   ├── SymbolLayer.svelte
│   │       │   └── common.ts
│   │       ├── map/
│   │       │   ├── Image.svelte
│   │       │   ├── Light.svelte
│   │       │   ├── MapLibre.svelte
│   │       │   ├── Projection.svelte
│   │       │   ├── Sky.svelte
│   │       │   ├── Sprite.svelte
│   │       │   └── Terrain.svelte
│   │       ├── markers/
│   │       │   ├── Marker.svelte
│   │       │   └── Popup.svelte
│   │       ├── sources/
│   │       │   ├── CanvasSource.svelte
│   │       │   ├── FeatureState.svelte
│   │       │   ├── GeoJSONSource.svelte
│   │       │   ├── ImageSource.svelte
│   │       │   ├── RasterDEMTileSource.svelte
│   │       │   ├── RasterTileSource.svelte
│   │       │   ├── RawSource.svelte
│   │       │   ├── VectorTileSource.svelte
│   │       │   └── VideoSource.svelte
│   │       ├── types.ts
│   │       ├── utilities/
│   │       │   ├── ImageLoader.svelte
│   │       │   ├── QueryRenderedFeatures.svelte
│   │       │   └── QuerySourceFeatures.svelte
│   │       └── utils.ts
│   ├── svelte.config.js
│   ├── tsconfig.json
│   └── vite.config.ts
├── svelte.config.js
├── tailwind.config.ts
├── tsconfig.json
├── turbo.json
├── vite.config.ts
└── wrangler.jsonc

================================================
FILE CONTENTS
================================================

================================================
FILE: .changeset/README.md
================================================
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)


================================================
FILE: .changeset/config.json
================================================
{
	"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
	"changelog": "@changesets/cli/changelog",
	"commit": false,
	"fixed": [],
	"linked": [["svelte-maplibre-gl", "@svelte-maplibre-gl/*"]],
	"access": "public",
	"baseBranch": "main",
	"updateInternalDependencies": "patch",
	"ignore": ["@svelte-maplibre-gl/docs"],
	"privatePackages": {
		"version": false,
		"tag": false
	}
}


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: 'github-actions'
    directory: '/'
    schedule:
      interval: 'weekly'


================================================
FILE: .github/pull_request_template.md
================================================
<!-- Close or Related Issues -->

Close #0

### What I did
<!-- Please describe the motivation behind this PR and the changes it introduces. -->

-

### Notes
<!-- If manual testing is required, please describe the procedure. -->

None


================================================
FILE: .github/workflows/lint.yml
================================================
name: Lint

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  lint:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6

      - run: npm i -g --force corepack && corepack enable

      - uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: 'pnpm'

      - name: Install dependencies
        run: pnpm install

      - name: Svelte check
        run: pnpm run check:all

      - name: Lint
        run: pnpm run lint


================================================
FILE: .github/workflows/preview.yml
================================================
name: Preview Release

on:
  pull_request:

jobs:
  preview-release:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v6
      - run: npm i -g --force corepack && corepack enable

      - uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: 'pnpm'

      - name: Install dependencies
        run: pnpm install

      - name: Build packages
        run: pnpm build:packages

      - name: Publish packages preview with pkg-pr-new CLI
        run: |
          pnpx pkg-pr-new publish \
            ./svelte-maplibre-gl \
            ./extensions/contour \
            ./extensions/deckgl \
            ./extensions/pmtiles \
            ./extensions/terradraw


================================================
FILE: .github/workflows/release.yml
================================================
name: Release

on:
  push:
    branches:
      - main

concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
      id-token: write
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v6

      - name: Setup pnpm
        run: npm i -g --force corepack@latest && corepack enable

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: 'pnpm'

      - name: Install Dependencies
        run: pnpm install

      - name: Create Release Pull Request or Publish to npm
        id: changesets
        uses: changesets/action@c48e67d110a68bc90ccf1098e9646092baacaa87 # v1.6.0
        with:
          publish: pnpm run release
          version: pnpm run version
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

      # Generate preview releases for PRs
      - name: Publish Preview Packages
        if: steps.changesets.outputs.published != 'true'
        run: |
          pnpm build:packages
          pnpx pkg-pr-new publish \
            ./svelte-maplibre-gl \
            ./extensions/contour \
            ./extensions/deckgl \
            ./extensions/pmtiles \
            ./extensions/terradraw


================================================
FILE: .gitignore
================================================
test-results
node_modules

# Output
.output
.vercel
**/.svelte-kit/
**/dist/
/build
.turbo

# OS
.DS_Store
Thumbs.db

# Env
.env
.env.*
!.env.example
!.env.test

# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*

# ignore npm lockfile
package-lock.json

.wrangler

================================================
FILE: .node-version
================================================
22.17

================================================
FILE: .npmrc
================================================
engine-strict=true

================================================
FILE: .prettierignore
================================================
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock

**/dist/
**/.svelte-kit/

# shadcn-svelte
src/lib/components/ui/**

.github/*.md
/README.md

================================================
FILE: .prettierrc
================================================
{
	"useTabs": true,
	"singleQuote": true,
	"trailingComma": "none",
	"printWidth": 120,
	"plugins": ["prettier-plugin-tailwindcss", "prettier-plugin-svelte"],
	"overrides": [
		{
			"files": "*.svelte",
			"options": {
				"parser": "svelte"
			}
		},
		{
			"files": ["*.svx", "*.svelte.md", "*.md"],
			"options": {
				"parser": "markdown"
			}
		}
	],
	"tailwindStylesheet": "./src/app.css"
}


================================================
FILE: LICENSE-APACHE.txt
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

================================================
FILE: LICENSE-MIT.txt
================================================
MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
# Svelte MapLibre GL

![NPM Version](https://img.shields.io/npm/v/svelte-maplibre-gl)
![NPM License](https://img.shields.io/npm/l/svelte-maplibre-gl?color=96C902)

:world_map: Build interactive web maps effortlessly with [MapLibre GL JS](https://maplibre.org/maplibre-gl-js/docs/) and [Svelte](https://svelte.dev/).

:point_right: **Documentaion and Live Demos:** https://svelte-maplibre-gl.mierune.dev/examples/

**Features:**

- The most declarative and reactive MapLibre GL JS experience, powered by Svelte 5
- A flexible, minimally opinionated API design that is suitable for both beginners and experienced MapLibre users
- Freedom preserved — Traditional imperative MapLibre GL JS usage remains fully supported

License: MIT or Apache 2.0

<img alt="hero image" src="./src/lib/assets/hero.svg" width="100%">

## Installation

```bash
npm install --save-dev svelte-maplibre-gl
```

`svelte-maplibre-gl` only works with **Svelte 5** and above.

## License

Licensed under the [MIT License](./LICENSE-MIT.txt) or the [Apache License 2.0](./LICENSE-APACHE.txt), at your option.

## Acknowledgements

This project `svelte-maplibre-gl` is built from scratch, while drawing strong inspiration from the work of the following libraries:

- [`dimfeld/svelte-maplibre`](https://github.com/dimfeld/svelte-maplibre) &mdash; A library offering idiomatic Svelte support for the MapLibre GL mapping software
- [`visgl/react-map-gl`](https://visgl.github.io/react-map-gl/) and [`visgl/react-maplibre`](https://visgl.github.io/react-maplibre/) &mdash; React friendly API wrapper around Mapbox/MapLibre GL JS

## Contributing

Everyone is welcome to contribute to this project! There are many ways to support it, such as:

- Trying it out and reporting any issues or missing features
- Expanding, improving, or suggesting new examples
- Any other ideas you might have!

Your contributions are greatly appreciated.

### Authors

[All contributors](https://github.com/MIERUNE/svelte-maplibre-gl/graphs/contributors)!


================================================
FILE: components.json
================================================
{
	"$schema": "https://shadcn-svelte.com/schema.json",
	"tailwind": {
		"css": "src/app.css",
		"baseColor": "slate"
	},
	"aliases": {
		"components": "$lib/components",
		"utils": "$lib/utils",
		"ui": "$lib/components/ui",
		"hooks": "$lib/hooks",
		"lib": "$lib"
	},
	"typescript": true,
	"registry": "https://shadcn-svelte.com/registry"
}


================================================
FILE: e2e/demo.test.ts
================================================
import { expect, test } from '@playwright/test';

test('home page has expected h1', async ({ page }) => {
	await page.goto('/');
	await expect(page.locator('h1')).toBeVisible();
});


================================================
FILE: eslint.config.js
================================================
import prettier from 'eslint-config-prettier';
import js from '@eslint/js';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import ts from 'typescript-eslint';

export default ts.config(
	js.configs.recommended,
	...ts.configs.recommended,
	...svelte.configs['flat/recommended'],
	prettier,
	...svelte.configs['flat/prettier'],
	{
		languageOptions: {
			globals: {
				...globals.browser,
				...globals.node
			}
		}
	},
	{
		files: ['**/*.svelte', '**/*.svelte.ts'],
		rules: {
			// surpress "Expected an assignment or function call and instead saw an expression"
			'@typescript-eslint/no-unused-expressions': 'off'
			// 'svelte/require-each-key': 'off'
		},
		languageOptions: {
			parserOptions: {
				parser: ts.parser
			}
		}
	},
	{
		ignores: ['**/build/', '**/.svelte-kit/', '**/dist/']
	}
);


================================================
FILE: extensions/contour/CHANGELOG.md
================================================
# @svelte-maplibre-gl/contour

## 1.0.3

### Patch Changes

- Updated dependencies [6b3cd54]
  - svelte-maplibre-gl@1.0.3

## 1.0.2

### Patch Changes

- Updated dependencies [608c2b5]
  - svelte-maplibre-gl@1.0.2

## 1.0.1

### Patch Changes

- Updated dependencies [a5cc3ef]
  - svelte-maplibre-gl@1.0.1


================================================
FILE: extensions/contour/package.json
================================================
{
	"name": "@svelte-maplibre-gl/contour",
	"version": "1.0.3",
	"license": "(MIT OR Apache-2.0)",
	"description": "maplibre-contour extension for svelte-maplibre-gl",
	"repository": {
		"url": "https://github.com/MIERUNE/svelte-maplibre-gl"
	},
	"homepage": "https://svelte-maplibre-gl.mierune.dev/",
	"keywords": [
		"map",
		"svelte",
		"maplibre",
		"maplibre-gl",
		"contour"
	],
	"scripts": {
		"build": "vite build && npm run prepack",
		"preview": "vite preview",
		"prepare": "svelte-kit sync || echo ''",
		"prepack": "svelte-kit sync && svelte-package && publint",
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
		"lint": "prettier --check ."
	},
	"files": [
		"dist",
		"!dist/**/*.test.*",
		"!dist/**/*.spec.*"
	],
	"sideEffects": false,
	"svelte": "./dist/index.js",
	"types": "./dist/index.d.ts",
	"type": "module",
	"exports": {
		".": {
			"types": "./dist/index.d.ts",
			"svelte": "./dist/index.js"
		}
	},
	"peerDependencies": {
		"maplibre-contour": ">=0.1.0",
		"maplibre-gl": "^5.0.0 || ^4.0.0",
		"svelte": ">=5.0.0",
		"svelte-maplibre-gl": "workspace:*"
	},
	"devDependencies": {
		"@sveltejs/kit": "catalog:",
		"@sveltejs/package": "catalog:",
		"@sveltejs/vite-plugin-svelte": "catalog:",
		"maplibre-contour": "catalog:",
		"maplibre-gl": "catalog:",
		"publint": "catalog:",
		"svelte": "catalog:",
		"svelte-check": "catalog:",
		"svelte-maplibre-gl": "workspace:*",
		"typescript": "catalog:",
		"vite": "catalog:"
	}
}


================================================
FILE: extensions/contour/src/app.d.ts
================================================
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
	namespace App {
		// interface Error {}
		// interface Locals {}
		// interface PageData {}
		// interface PageState {}
		// interface Platform {}
	}
}

export {};


================================================
FILE: extensions/contour/src/app.html
================================================
<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		%sveltekit.head%
	</head>
	<body data-sveltekit-preload-data="hover">
		<div style="display: contents">%sveltekit.body%</div>
	</body>
</html>


================================================
FILE: extensions/contour/src/lib/MapLibreContourSource.svelte
================================================
<script lang="ts">
	// https://github.com/onthegomap/maplibre-contour

	import type { Snippet } from 'svelte';
	import maplibregl from 'maplibre-gl';
	import { default as mlcontour } from 'maplibre-contour';
	import { VectorTileSource } from 'svelte-maplibre-gl';

	type LocalDemManager = typeof mlcontour.LocalDemManager.prototype;
	type DemSource = typeof mlcontour.DemSource.prototype;
	type DemSourceConstructorParams = ConstructorParameters<typeof mlcontour.DemSource>[0];
	type GlobalContourTileOptions = Parameters<DemSource['contourProtocolUrl']>[0];

	interface Props extends DemSourceConstructorParams {
		children?: Snippet<[demSource: DemSource]>;
		demSource?: DemSource;
		tileOptions: GlobalContourTileOptions;
		attribution?: string;
		getTile?: LocalDemManager['getTile'];
	}

	let {
		children,
		demSource = $bindable(),
		url,
		id,
		cacheSize,
		encoding = 'mapbox',
		maxzoom,
		timeoutMs,
		worker = true,
		actor,
		tileOptions,
		attribution,
		/** Custom getTile function for LocalDemManager (experimental) */
		getTile
	}: Props = $props();

	$effect(() => {
		if (getTile) {
			worker = false;
		}
		(async () => {
			demSource = new mlcontour.DemSource({
				url,
				id,
				cacheSize, // number of most-recent tiles to cache
				encoding,
				maxzoom,
				timeoutMs, // timeout on fetch requests
				worker, // offload isoline computation to a web worker to reduce jank
				actor
			});
			if (getTile && 'getTile' in demSource.manager) {
				demSource.manager.getTile = getTile;
			}
			demSource.setupMaplibre(maplibregl);
		})();

		return () => {
			if (demSource) {
				maplibregl.removeProtocol(demSource.sharedDemProtocolId);
				maplibregl.removeProtocol(demSource.contourProtocolId);
			}
		};
	});
</script>

{#if demSource}
	<VectorTileSource tiles={[demSource.contourProtocolUrl(tileOptions)]} maxzoom={15} {attribution}>
		{@render children?.(demSource)}
	</VectorTileSource>
{/if}


================================================
FILE: extensions/contour/src/lib/index.ts
================================================
export { default as MapLibreContourSource } from './MapLibreContourSource.svelte';


================================================
FILE: extensions/contour/svelte.config.js
================================================
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	// Consult https://svelte.dev/docs/kit/integrations
	// for more information about preprocessors
	preprocess: vitePreprocess(),

	kit: {
		// Since this is a library package, we don't need an adapter
		adapter: undefined
	}
};

export default config;


================================================
FILE: extensions/contour/tsconfig.json
================================================
{
	"extends": "./.svelte-kit/tsconfig.json",
	"compilerOptions": {
		"allowJs": true,
		"checkJs": true,
		"esModuleInterop": true,
		"forceConsistentCasingInFileNames": true,
		"resolveJsonModule": true,
		"skipLibCheck": true,
		"sourceMap": true,
		"strict": true,
		"moduleResolution": "bundler",
		"module": "ESNext",
		"target": "ES2020",
		"lib": ["ES2020", "DOM", "DOM.Iterable"],
		"types": ["svelte"]
	},
	"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
	"exclude": ["node_modules", "dist"]
}


================================================
FILE: extensions/contour/vite.config.ts
================================================
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

export default defineConfig({
	plugins: [svelte()],

	build: {
		lib: {
			entry: './src/lib/index.ts',
			name: 'SvelteMaplibreContour',
			fileName: 'index'
		},
		rollupOptions: {
			external: ['svelte', 'maplibre-gl', '@watergis/maplibre-gl-terradraw'],
			output: {
				globals: {
					svelte: 'Svelte',
					'maplibre-gl': 'maplibregl',
					'@watergis/maplibre-gl-terradraw': 'MaplibreContour'
				}
			}
		}
	}
});


================================================
FILE: extensions/deckgl/CHANGELOG.md
================================================
# @svelte-maplibre-gl/deckgl

## 1.0.3

### Patch Changes

- Updated dependencies [6b3cd54]
  - svelte-maplibre-gl@1.0.3

## 1.0.2

### Patch Changes

- Updated dependencies [608c2b5]
  - svelte-maplibre-gl@1.0.2

## 1.0.1

### Patch Changes

- Updated dependencies [a5cc3ef]
  - svelte-maplibre-gl@1.0.1


================================================
FILE: extensions/deckgl/package.json
================================================
{
	"name": "@svelte-maplibre-gl/deckgl",
	"version": "1.0.3",
	"license": "(MIT OR Apache-2.0)",
	"description": "DeckGL extension for svelte-maplibre-gl",
	"repository": {
		"url": "https://github.com/MIERUNE/svelte-maplibre-gl"
	},
	"homepage": "https://svelte-maplibre-gl.mierune.dev/",
	"keywords": [
		"map",
		"svelte",
		"maplibre",
		"maplibre-gl",
		"deckgl"
	],
	"scripts": {
		"build": "vite build && npm run prepack",
		"preview": "vite preview",
		"prepare": "svelte-kit sync || echo ''",
		"prepack": "svelte-kit sync && svelte-package && publint",
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
		"lint": "prettier --check ."
	},
	"files": [
		"dist",
		"!dist/**/*.test.*",
		"!dist/**/*.spec.*"
	],
	"sideEffects": false,
	"svelte": "./dist/index.js",
	"types": "./dist/index.d.ts",
	"type": "module",
	"exports": {
		".": {
			"types": "./dist/index.d.ts",
			"svelte": "./dist/index.js"
		}
	},
	"peerDependencies": {
		"@deck.gl/core": "^9.1.0",
		"@deck.gl/layers": "^9.1.0",
		"@deck.gl/mapbox": "^9.1.0",
		"maplibre-gl": "^5.0.0 || ^4.0.0",
		"svelte": ">=5.0.0",
		"svelte-maplibre-gl": "workspace:*"
	},
	"devDependencies": {
		"@deck.gl/core": "catalog:",
		"@deck.gl/layers": "catalog:",
		"@deck.gl/mapbox": "catalog:",
		"@sveltejs/kit": "catalog:",
		"@sveltejs/package": "catalog:",
		"@sveltejs/vite-plugin-svelte": "catalog:",
		"maplibre-gl": "catalog:",
		"publint": "catalog:",
		"svelte": "catalog:",
		"svelte-check": "catalog:",
		"svelte-maplibre-gl": "workspace:*",
		"typescript": "catalog:",
		"vite": "catalog:"
	}
}


================================================
FILE: extensions/deckgl/src/app.d.ts
================================================
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
	namespace App {
		// interface Error {}
		// interface Locals {}
		// interface PageData {}
		// interface PageState {}
		// interface Platform {}
	}
}

export {};


================================================
FILE: extensions/deckgl/src/app.html
================================================
<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		%sveltekit.head%
	</head>
	<body data-sveltekit-preload-data="hover">
		<div style="display: contents">%sveltekit.body%</div>
	</body>
</html>


================================================
FILE: extensions/deckgl/src/lib/DeckGLOverlay.svelte
================================================
<script lang="ts">
	import { onDestroy, onMount, untrack } from 'svelte';
	import maplibregl from 'maplibre-gl';
	import { MapboxOverlay, type MapboxOverlayProps } from '@deck.gl/mapbox';
	import { getMapContext } from 'svelte-maplibre-gl';

	type Props = MapboxOverlayProps;

	let {
		// not reactive
		interleaved = false,
		id,
		debug,
		_typedArrayManagerProps,
		// reactive (?)
		style,
		useDevicePixels,
		parameters,
		layers,
		layerFilter,
		effects = [],
		_framebuffer,
		_animate,
		getCursor,
		getTooltip,
		pickingRadius,
		touchAction,
		eventRecognizerOptions,
		_pickable,
		onDeviceInitialized,
		onViewStateChange,
		onInteractionStateChange,
		onHover,
		onClick,
		onDragStart,
		onDrag,
		onDragEnd,
		onLoad,
		onResize,
		onBeforeRender,
		onAfterRender,
		onError,
		_onMetrics
	}: Props = $props();

	const mapCtx = getMapContext();
	if (!mapCtx.map) throw new Error('Map instance is not initialized.');

	let deckOverlay: MapboxOverlay;
	onMount(() => {
		const options: MapboxOverlayProps = Object.fromEntries(
			Object.entries({
				interleaved,
				id,
				debug,
				_typedArrayManagerProps,
				style,
				useDevicePixels,
				parameters,
				layers,
				layerFilter,
				effects,
				_framebuffer,
				_animate,
				getCursor,
				getTooltip,
				pickingRadius,
				touchAction,
				eventRecognizerOptions,
				_pickable,
				onDeviceInitialized,
				onViewStateChange,
				onInteractionStateChange,
				onHover,
				onClick,
				onDragStart,
				onDrag,
				onDragEnd,
				onLoad,
				onResize,
				onBeforeRender,
				onAfterRender,
				onError,
				_onMetrics

				// filter out undefined values
			}).filter(([, v]) => v !== undefined)
		);

		deckOverlay = new MapboxOverlay(options);

		mapCtx.map?.addControl(deckOverlay as maplibregl.IControl);
	});

	let firstRun = true;

	// collect all reactive prop changes and apply them in a single update
	let pendingChanges: MapboxOverlayProps = {};
	let changeTrigger = $state(0);

	function reactiveProp<K extends keyof MapboxOverlayProps>(name: K, value: MapboxOverlayProps[K]) {
		if (!firstRun) {
			pendingChanges[name] = value;
			untrack(() => (changeTrigger += 1));
		}
	}

	$effect(() => reactiveProp('style', style));
	$effect(() => reactiveProp('useDevicePixels', useDevicePixels));
	$effect(() => reactiveProp('parameters', parameters));
	$effect(() => reactiveProp('layers', layers));
	$effect(() => reactiveProp('layerFilter', layerFilter));
	$effect(() => reactiveProp('effects', effects));
	$effect(() => reactiveProp('_framebuffer', _framebuffer));
	$effect(() => reactiveProp('_animate', _animate));
	$effect(() => reactiveProp('getCursor', getCursor));
	$effect(() => reactiveProp('getTooltip', getTooltip));
	$effect(() => reactiveProp('pickingRadius', pickingRadius));
	$effect(() => reactiveProp('touchAction', touchAction));
	$effect(() => reactiveProp('eventRecognizerOptions', eventRecognizerOptions));
	$effect(() => reactiveProp('_pickable', _pickable));
	$effect(() => reactiveProp('onDeviceInitialized', onDeviceInitialized));
	$effect(() => reactiveProp('onViewStateChange', onViewStateChange));
	$effect(() => reactiveProp('onInteractionStateChange', onInteractionStateChange));
	$effect(() => reactiveProp('onHover', onHover));
	$effect(() => reactiveProp('onClick', onClick));
	$effect(() => reactiveProp('onDragStart', onDragStart));
	$effect(() => reactiveProp('onDrag', onDrag));
	$effect(() => reactiveProp('onDragEnd', onDragEnd));
	$effect(() => reactiveProp('onLoad', onLoad));
	$effect(() => reactiveProp('onResize', onResize));
	$effect(() => reactiveProp('onBeforeRender', onBeforeRender));
	$effect(() => reactiveProp('onAfterRender', onAfterRender));
	$effect(() => reactiveProp('onError', onError));
	$effect(() => reactiveProp('_onMetrics', _onMetrics));

	$effect(() => {
		firstRun = false;
	});

	$effect(() => {
		changeTrigger;
		if (!firstRun) {
			deckOverlay.setProps(pendingChanges);
			pendingChanges = {};
		}
	});

	onDestroy(() => {
		mapCtx.map?.removeControl(deckOverlay as maplibregl.IControl);
	});
</script>


================================================
FILE: extensions/deckgl/src/lib/index.ts
================================================
export { default as DeckGLOverlay } from './DeckGLOverlay.svelte';


================================================
FILE: extensions/deckgl/svelte.config.js
================================================
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	// Consult https://svelte.dev/docs/kit/integrations
	// for more information about preprocessors
	preprocess: vitePreprocess(),

	kit: {
		// Since this is a library package, we don't need an adapter
		adapter: undefined
	}
};

export default config;


================================================
FILE: extensions/deckgl/tsconfig.json
================================================
{
	"extends": "./.svelte-kit/tsconfig.json",
	"compilerOptions": {
		"allowJs": true,
		"checkJs": true,
		"esModuleInterop": true,
		"forceConsistentCasingInFileNames": true,
		"resolveJsonModule": true,
		"skipLibCheck": true,
		"sourceMap": true,
		"strict": true,
		"moduleResolution": "bundler",
		"module": "ESNext",
		"target": "ES2020",
		"lib": ["ES2020", "DOM", "DOM.Iterable"],
		"types": ["svelte"]
	},
	"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
	"exclude": ["node_modules", "dist"]
}


================================================
FILE: extensions/deckgl/vite.config.ts
================================================
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

export default defineConfig({
	plugins: [svelte()],

	build: {
		lib: {
			entry: './src/lib/index.ts',
			name: 'SvelteMaplibreDeckGL',
			fileName: 'index'
		},
		rollupOptions: {
			external: ['svelte', 'maplibre-gl', '@deck.gl/mapbox'],
			output: {
				globals: {
					svelte: 'Svelte',
					'maplibre-gl': 'maplibregl',
					'@deck.gl/mapbox': 'DeckGLMapbox'
				}
			}
		}
	}
});


================================================
FILE: extensions/pmtiles/CHANGELOG.md
================================================
# @svelte-maplibre-gl/pmtiles

## 1.0.3

### Patch Changes

- Updated dependencies [6b3cd54]
  - svelte-maplibre-gl@1.0.3

## 1.0.2

### Patch Changes

- Updated dependencies [608c2b5]
  - svelte-maplibre-gl@1.0.2

## 1.0.1

### Patch Changes

- Updated dependencies [a5cc3ef]
  - svelte-maplibre-gl@1.0.1


================================================
FILE: extensions/pmtiles/package.json
================================================
{
	"name": "@svelte-maplibre-gl/pmtiles",
	"version": "1.0.3",
	"license": "(MIT OR Apache-2.0)",
	"description": "PMTiles extension for svelte-maplibre-gl",
	"repository": {
		"url": "https://github.com/MIERUNE/svelte-maplibre-gl"
	},
	"homepage": "https://svelte-maplibre-gl.mierune.dev/",
	"keywords": [
		"map",
		"svelte",
		"maplibre",
		"maplibre-gl",
		"pmtiles"
	],
	"scripts": {
		"build": "vite build && npm run prepack",
		"preview": "vite preview",
		"prepare": "svelte-kit sync || echo ''",
		"prepack": "svelte-kit sync && svelte-package && publint",
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
		"lint": "prettier --check ."
	},
	"files": [
		"dist",
		"!dist/**/*.test.*",
		"!dist/**/*.spec.*"
	],
	"sideEffects": false,
	"svelte": "./dist/index.js",
	"types": "./dist/index.d.ts",
	"type": "module",
	"exports": {
		".": {
			"types": "./dist/index.d.ts",
			"svelte": "./dist/index.js"
		}
	},
	"peerDependencies": {
		"pmtiles": "^4.0.0",
		"maplibre-gl": "^5.0.0 || ^4.0.0",
		"svelte": ">=5.0.0",
		"svelte-maplibre-gl": "workspace:*"
	},
	"devDependencies": {
		"@sveltejs/kit": "catalog:",
		"@sveltejs/package": "catalog:",
		"@sveltejs/vite-plugin-svelte": "catalog:",
		"maplibre-gl": "catalog:",
		"pmtiles": "catalog:",
		"publint": "catalog:",
		"svelte": "catalog:",
		"svelte-check": "catalog:",
		"svelte-maplibre-gl": "workspace:*",
		"typescript": "catalog:",
		"vite": "catalog:"
	}
}


================================================
FILE: extensions/pmtiles/src/app.d.ts
================================================
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
	namespace App {
		// interface Error {}
		// interface Locals {}
		// interface PageData {}
		// interface PageState {}
		// interface Platform {}
	}
}

export {};


================================================
FILE: extensions/pmtiles/src/app.html
================================================
<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		%sveltekit.head%
	</head>
	<body data-sveltekit-preload-data="hover">
		<div style="display: contents">%sveltekit.body%</div>
	</body>
</html>


================================================
FILE: extensions/pmtiles/src/lib/PMTilesProtocol.svelte
================================================
<script lang="ts">
	import { Protocol as MapLibreProtocol } from 'svelte-maplibre-gl';
	import { Protocol, type PMTiles } from 'pmtiles';

	let {
		scheme = 'pmtiles',
		metadata = false,
		errorOnMissingTile = false,
		pmtiles
	}: {
		/** URL scheme for the PMTilesProtocol */
		scheme?: string;
		/** Also load the metadata section of the PMTiles. required for some "inspect" functionality
		 * and to automatically populate the map attribution. Requires an extra HTTP request.
		 */
		metadata?: boolean;
		/** When a vector MVT tile is missing from the archive, raise an error instead of
		 * returning the empty array. Not recommended. This is only to reproduce the behavior of ZXY tile APIs
		 * which some applications depend on when overzooming. */
		errorOnMissingTile?: boolean;
		/** Array of PMTiles instances */
		pmtiles?: PMTiles[];
	} = $props();

	const protocol = new Protocol({ metadata, errorOnMissingTile });

	$effect(() => {
		protocol.metadata = metadata;
	});

	$effect(() => {
		protocol.errorOnMissingTile = errorOnMissingTile;
	});

	$effect(() => {
		if (pmtiles) {
			for (const p of pmtiles) {
				protocol.add(p);
			}
		}
	});
</script>

<MapLibreProtocol {scheme} loadFn={protocol.tile} />


================================================
FILE: extensions/pmtiles/src/lib/index.ts
================================================
export { default as PMTilesProtocol } from './PMTilesProtocol.svelte';


================================================
FILE: extensions/pmtiles/svelte.config.js
================================================
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	// Consult https://svelte.dev/docs/kit/integrations
	// for more information about preprocessors
	preprocess: vitePreprocess(),

	kit: {
		// Since this is a library package, we don't need an adapter
		adapter: undefined
	}
};

export default config;


================================================
FILE: extensions/pmtiles/tsconfig.json
================================================
{
	"extends": "./.svelte-kit/tsconfig.json",
	"compilerOptions": {
		"allowJs": true,
		"checkJs": true,
		"esModuleInterop": true,
		"forceConsistentCasingInFileNames": true,
		"resolveJsonModule": true,
		"skipLibCheck": true,
		"sourceMap": true,
		"strict": true,
		"moduleResolution": "bundler",
		"module": "ESNext",
		"target": "ES2020",
		"lib": ["ES2020", "DOM", "DOM.Iterable"],
		"types": ["svelte"]
	},
	"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
	"exclude": ["node_modules", "dist"]
}


================================================
FILE: extensions/pmtiles/vite.config.ts
================================================
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

export default defineConfig({
	plugins: [svelte()],

	build: {
		lib: {
			entry: './src/lib/index.ts',
			name: 'SvelteMaplibrePMTiles',
			fileName: 'index'
		},
		rollupOptions: {
			external: ['svelte', 'maplibre-gl', 'pmtiles', 'svelte-maplibre-gl'],
			output: {
				globals: {
					svelte: 'Svelte',
					'maplibre-gl': 'maplibregl',
					pmtiles: 'pmtiles',
					'svelte-maplibre-gl': 'SvelteMaplibreGL'
				}
			}
		}
	}
});


================================================
FILE: extensions/terradraw/CHANGELOG.md
================================================
# @svelte-maplibre-gl/terradraw

## 1.0.3

### Patch Changes

- Updated dependencies [6b3cd54]
  - svelte-maplibre-gl@1.0.3

## 1.0.2

### Patch Changes

- Updated dependencies [608c2b5]
  - svelte-maplibre-gl@1.0.2

## 1.0.1

### Patch Changes

- Updated dependencies [a5cc3ef]
  - svelte-maplibre-gl@1.0.1


================================================
FILE: extensions/terradraw/package.json
================================================
{
	"name": "@svelte-maplibre-gl/terradraw",
	"version": "1.0.3",
	"license": "(MIT OR Apache-2.0)",
	"description": "TerraDraw extension for svelte-maplibre-gl",
	"repository": {
		"url": "https://github.com/MIERUNE/svelte-maplibre-gl"
	},
	"homepage": "https://svelte-maplibre-gl.mierune.dev/",
	"keywords": [
		"map",
		"svelte",
		"maplibre",
		"maplibre-gl",
		"terradraw"
	],
	"scripts": {
		"build": "vite build && npm run prepack",
		"preview": "vite preview",
		"prepare": "svelte-kit sync || echo ''",
		"prepack": "svelte-kit sync && svelte-package && publint",
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
		"lint": "prettier --check ."
	},
	"files": [
		"dist",
		"!dist/**/*.test.*",
		"!dist/**/*.spec.*"
	],
	"sideEffects": false,
	"svelte": "./dist/index.js",
	"types": "./dist/index.d.ts",
	"type": "module",
	"exports": {
		".": {
			"types": "./dist/index.d.ts",
			"svelte": "./dist/index.js"
		}
	},
	"peerDependencies": {
		"terra-draw": "^1.0.0",
		"terra-draw-maplibre-gl-adapter": "^1.0.3",
		"maplibre-gl": "^5.0.0 || ^4.0.0",
		"svelte": ">=5.0.0",
		"svelte-maplibre-gl": "workspace:*"
	},
	"devDependencies": {
		"@sveltejs/kit": "catalog:",
		"@sveltejs/package": "catalog:",
		"@sveltejs/vite-plugin-svelte": "catalog:",
		"maplibre-gl": "catalog:",
		"publint": "catalog:",
		"svelte": "catalog:",
		"svelte-check": "catalog:",
		"svelte-maplibre-gl": "workspace:*",
		"terra-draw": "catalog:",
		"terra-draw-maplibre-gl-adapter": "catalog:",
		"typescript": "catalog:",
		"vite": "catalog:"
	}
}


================================================
FILE: extensions/terradraw/src/app.d.ts
================================================
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
	namespace App {
		// interface Error {}
		// interface Locals {}
		// interface PageData {}
		// interface PageState {}
		// interface Platform {}
	}
}

export {};


================================================
FILE: extensions/terradraw/src/app.html
================================================
<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		%sveltekit.head%
	</head>
	<body data-sveltekit-preload-data="hover">
		<div style="display: contents">%sveltekit.body%</div>
	</body>
</html>


================================================
FILE: extensions/terradraw/src/lib/TerraDraw.svelte
================================================
<script lang="ts">
	import { TerraDraw as Draw } from 'terra-draw';
	import type { IdStrategy, TerraDrawEventListeners } from 'terra-draw';
	import { TerraDrawMapLibreGLAdapter } from 'terra-draw-maplibre-gl-adapter';
	import { getMapContext } from 'svelte-maplibre-gl';

	type FeatureId = string | number;

	const mapCtx = getMapContext();

	let {
		mode,
		modes,
		tracked,
		idStrategy,
		draw = $bindable(),
		onfinish,
		onchange,
		onready,
		onselect,
		ondeselect
	}: {
		mode: string;
		modes: ConstructorParameters<typeof Draw>[0]['modes'];
		idStrategy?: IdStrategy<FeatureId>;
		tracked?: boolean;
		/** Terra Draw instance */
		draw?: Draw;
		onchange?: TerraDrawEventListeners['change'];
		onfinish?: TerraDrawEventListeners['finish'];
		onready?: TerraDrawEventListeners['ready'];
		onselect?: TerraDrawEventListeners['select'];
		ondeselect?: TerraDrawEventListeners['deselect'];
	} = $props();

	mapCtx.waitForStyleLoaded((map) => {
		draw = new Draw({
			adapter: new TerraDrawMapLibreGLAdapter({ map }),
			modes,
			idStrategy,
			tracked
		});
	});

	$effect(() => {
		draw?.start();
		return () => draw?.stop();
	});
	$effect(() => {
		draw?.setMode(mode);
	});

	// Event listeners
	$effect(() => {
		if (!onready) return;
		draw?.on('ready', onready);
		return () => draw?.off('ready', onready);
	});
	$effect(() => {
		if (!onfinish) return;
		draw?.on('finish', onfinish);
		return () => draw?.off('finish', onfinish);
	});
	$effect(() => {
		if (!onchange) return;
		draw?.on('change', onchange);
		return () => draw?.off('change', onchange);
	});
	$effect(() => {
		if (!onselect) return;
		draw?.on('select', onselect);
		return () => draw?.off('select', onselect);
	});
	$effect(() => {
		if (!ondeselect) return;
		draw?.on('deselect', ondeselect);
		return () => draw?.off('deselect', ondeselect);
	});
</script>


================================================
FILE: extensions/terradraw/src/lib/index.ts
================================================
export { default as TerraDraw } from './TerraDraw.svelte';


================================================
FILE: extensions/terradraw/svelte.config.js
================================================
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
	// Consult https://svelte.dev/docs/kit/integrations
	// for more information about preprocessors
	preprocess: vitePreprocess(),

	kit: {
		// Since this is a library package, we don't need an adapter
		adapter: undefined
	}
};

export default config;


================================================
FILE: extensions/terradraw/tsconfig.json
================================================
{
	"extends": "./.svelte-kit/tsconfig.json",
	"compilerOptions": {
		"allowJs": true,
		"checkJs": true,
		"esModuleInterop": true,
		"forceConsistentCasingInFileNames": true,
		"resolveJsonModule": true,
		"skipLibCheck": true,
		"sourceMap": true,
		"strict": true,
		"moduleResolution": "bundler",
		"module": "ESNext",
		"target": "ES2020",
		"lib": ["ES2020", "DOM", "DOM.Iterable"],
		"types": ["svelte"]
	},
	"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
	"exclude": ["node_modules", "dist"]
}


================================================
FILE: extensions/terradraw/vite.config.ts
================================================
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

export default defineConfig({
	plugins: [svelte()],

	build: {
		lib: {
			entry: './src/lib/index.ts',
			name: 'SvelteMaplibreTerraDraw',
			fileName: 'index'
		},
		rollupOptions: {
			external: ['svelte', 'maplibre-gl', 'terra-draw', 'terra-draw-maplibre-gl-adapter', 'svelte-maplibre-gl'],
			output: {
				globals: {
					svelte: 'Svelte',
					'maplibre-gl': 'maplibregl',
					'terra-draw': 'TerraDraw',
					'terra-draw-maplibre-gl-adapter': 'TerraDrawMapLibreGLAdapter',
					'svelte-maplibre-gl': 'SvelteMaplibreGL'
				}
			}
		}
	}
});


================================================
FILE: package.json
================================================
{
	"name": "@svelte-maplibre-gl/docs",
	"version": "1.0.0",
	"private": true,
	"type": "module",
	"license": "(MIT OR Apache-2.0)",
	"description": "Documentation site for svelte-maplibre-gl",
	"repository": {
		"url": "https://github.com/MIERUNE/svelte-maplibre-gl"
	},
	"homepage": "https://svelte-maplibre-gl.mierune.dev/",
	"scripts": {
		"dev": "vite dev",
		"build": "vite build",
		"build:all": "turbo run build",
		"build:packages": "turbo run build --filter='./svelte-maplibre-gl' --filter='./extensions/*'",
		"preview": "turbo run preview",
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
		"check:all": "turbo run check",
		"check:watch": "turbo run check:watch --filter='./svelte-maplibre-gl' --filter='./extensions/*'",
		"format": "prettier --write .",
		"lint": "prettier --check . && eslint .",
		"test:unit": "vitest",
		"test": "npm run test:unit -- --run && npm run test:e2e",
		"test:e2e": "playwright test",
		"changeset": "changeset",
		"version": "changeset version",
		"release": "pnpm build:packages && changeset publish"
	},
	"dependencies": {
		"@changesets/changelog-github": "^0.5.2",
		"@svelte-maplibre-gl/contour": "workspace:*",
		"@svelte-maplibre-gl/deckgl": "workspace:*",
		"@svelte-maplibre-gl/pmtiles": "workspace:*",
		"@svelte-maplibre-gl/terradraw": "workspace:*",
		"svelte-maplibre-gl": "workspace:*"
	},
	"devDependencies": {
		"@changesets/cli": "^2.29.8",
		"@deck.gl/core": "catalog:",
		"@deck.gl/layers": "catalog:",
		"@deck.gl/mapbox": "catalog:",
		"@docsearch/css": "^3.9.0",
		"@docsearch/js": "^3.9.0",
		"@eslint/js": "^9.39.2",
		"@internationalized/date": "^3.10.1",
		"@lucide/svelte": "^0.541.0",
		"@playwright/test": "^1.58.0",
		"@sveltejs/adapter-cloudflare": "^7.2.6",
		"@sveltejs/kit": "catalog:",
		"@sveltejs/package": "catalog:",
		"@sveltejs/vite-plugin-svelte": "catalog:",
		"@tailwindcss/typography": "^0.5.19",
		"@tailwindcss/vite": "^4.1.18",
		"@types/eslint": "^9.6.1",
		"@types/geojson": "catalog:",
		"@types/three": "^0.179.0",
		"bits-ui": "^2.15.4",
		"clsx": "^2.1.1",
		"eslint": "^9.39.2",
		"eslint-config-prettier": "^10.1.8",
		"eslint-plugin-svelte": "^3.14.0",
		"fast-png": "^7.0.1",
		"globals": "^17.2.0",
		"install": "^0.13.0",
		"maplibre-contour": "catalog:",
		"maplibre-gl": "catalog:",
		"mdsvex": "^0.12.6",
		"mode-watcher": "^1.1.0",
		"pathe": "^2.0.3",
		"pkg-pr-new": "^0.0.57",
		"pmtiles": "catalog:",
		"prettier": "^3.8.1",
		"prettier-plugin-svelte": "^3.4.1",
		"prettier-plugin-tailwindcss": "^0.6.14",
		"publint": "catalog:",
		"shiki": "^3.21.0",
		"superjson": "^2.2.6",
		"svelte": "catalog:",
		"svelte-check": "catalog:",
		"svelte2tsx": "0.7.34",
		"tailwind-merge": "^3.4.0",
		"tailwind-variants": "^3.2.2",
		"tailwindcss": "^4.1.18",
		"tailwindcss-animate": "^1.0.7",
		"terra-draw": "catalog:",
		"terra-draw-maplibre-gl-adapter": "catalog:",
		"three": "^0.179.1",
		"turbo": "^2.7.6",
		"typescript": "catalog:",
		"typescript-eslint": "^8.54.0",
		"vite": "catalog:",
		"vitest": "^3.2.4"
	},
	"packageManager": "pnpm@10.15.0"
}


================================================
FILE: playwright.config.ts
================================================
import { defineConfig } from '@playwright/test';

export default defineConfig({
	webServer: {
		command: 'npm run build && npm run preview',
		port: 4173
	},

	testDir: 'e2e'
});


================================================
FILE: pnpm-workspace.yaml
================================================
packages:
  - svelte-maplibre-gl
  - extensions/*
  - .

catalog:
  '@deck.gl/core': ^9.2.6
  '@deck.gl/layers': ^9.2.6
  '@deck.gl/mapbox': ^9.2.6
  '@sveltejs/kit': ^2.50.1
  '@sveltejs/package': ^2.5.7
  '@sveltejs/vite-plugin-svelte': ^6.2.4
  '@types/geojson': ^7946.0.16
  maplibre-contour: ^0.1.0
  maplibre-gl: 5.17.0
  pmtiles: ^4.3.2
  publint: ^0.3.17
  svelte: ^5.48.5
  svelte-check: ^4.3.5
  terra-draw: ^1.23.1
  terra-draw-maplibre-gl-adapter: ^1.2.3
  typescript: ^5.9.3
  vite: ^7.3.1

onlyBuiltDependencies:
  - esbuild
  - sharp
  - workerd


================================================
FILE: src/app.css
================================================
@import 'tailwindcss';

@custom-variant dark (&:where(.dark, .dark *));

@config '../tailwind.config.ts';

/*
  The default border color has changed to `currentColor` in Tailwind CSS v4,
  so we've added these compatibility styles to make sure everything still
  looks the same as it did with Tailwind CSS v3.

  If we ever want to remove these styles, we need to add an explicit border
  color utility to any element that depends on these defaults.
*/
@layer base {
	*,
	::after,
	::before,
	::backdrop,
	::file-selector-button {
		border-color: var(--color-gray-200, currentColor);
	}
}

@layer base {
	:root {
		--background: 0 0% 100%;
		--foreground: 222.2 84% 4.9%;
		--card: 0 0% 100%;
		--card-foreground: 222.2 84% 4.9%;
		--popover: 0 0% 100%;
		--popover-foreground: 222.2 84% 4.9%;
		--primary: 222.2 47.4% 11.2%;
		--primary-foreground: 210 40% 98%;
		--secondary: 210 40% 96.1%;
		--secondary-foreground: 222.2 47.4% 11.2%;
		--muted: 210 40% 96.1%;
		--muted-foreground: 215.4 16.3% 46.9%;
		--accent: 210 40% 96.1%;
		--accent-foreground: 222.2 47.4% 11.2%;
		--destructive: 0 72.22% 50.59%;
		--destructive-foreground: 210 40% 98%;
		--border: 214.3 31.8% 91.4%;
		--input: 214.3 31.8% 91.4%;
		--ring: 222.2 84% 4.9%;
		--radius: 0.5rem;
	}
	.dark {
		--background: 222.2 84% 4.9%;
		--foreground: 210 40% 98%;
		--card: 222.2 84% 4.9%;
		--card-foreground: 210 40% 98%;
		--popover: 222.2 84% 4.9%;
		--popover-foreground: 210 40% 98%;
		--primary: 210 40% 98%;
		--primary-foreground: 222.2 47.4% 11.2%;
		--secondary: 217.2 32.6% 17.5%;
		--secondary-foreground: 210 40% 98%;
		--muted: 217.2 32.6% 17.5%;
		--muted-foreground: 215 20.2% 65.1%;
		--accent: 217.2 32.6% 17.5%;
		--accent-foreground: 210 40% 98%;
		--destructive: 0 62.8% 30.6%;
		--destructive-foreground: 210 40% 98%;
		--border: 217.2 32.6% 17.5%;
		--input: 217.2 32.6% 17.5%;
		--ring: 212.7 26.8% 83.9%;
	}

	:root {
		--docsearch-primary-color: #0e58c0;
		--docsearch-text-color: rgb(28, 30, 33);
		--docsearch-spacing: 12px;
		--docsearch-icon-stroke-width: 1.4;
		--docsearch-highlight-color: var(--docsearch-primary-color);
		--docsearch-muted-color: #666;
		--docsearch-container-background: rgba(101, 108, 133, 0.8);
		--docsearch-logo-color: rgba(84, 104, 255);

		/* modal */
		--docsearch-modal-width: 560px;
		--docsearch-modal-height: 600px;
		--docsearch-modal-background: rgb(245, 246, 247);
		--docsearch-modal-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, 0.5), 0 3px 8px 0 rgba(85, 90, 100, 1);

		/* searchbox */
		--docsearch-searchbox-height: 56px;
		--docsearch-searchbox-background: transparent;
		--docsearch-searchbox-focus-background: #fff;
		--docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);

		/* hit */
		--docsearch-hit-height: 56px;
		--docsearch-hit-color: rgb(68, 73, 80);
		--docsearch-hit-active-color: #fff;
		--docsearch-hit-background: #fff;
		--docsearch-hit-shadow: 0 1px 3px 0 rgb(212, 217, 225);

		/* key */
		--docsearch-key-gradient: linear-gradient(-225deg, rgb(213, 219, 228) 0%, rgb(248, 248, 248) 100%);
		--docsearch-key-shadow:
			inset 0 -2px 0 0 rgb(205, 205, 230), inset 0 0 1px 1px #fff, 0 1px 2px 1px rgba(30, 35, 90, 0.4);
		--docsearch-key-pressed-shadow: inset 0 -2px 0 0 #cdcde6, inset 0 0 1px 1px #fff, 0 1px 1px 0 rgba(30, 35, 90, 0.4);

		/* footer */
		--docsearch-footer-height: 44px;
		--docsearch-footer-background: #fff;
		--docsearch-footer-shadow: 0 -1px 0 0 rgb(224, 227, 232), 0 -3px 6px 0 rgba(69, 98, 155, 0.12);
	}

	/* Darkmode */
	html.dark {
		--docsearch-text-color: rgb(245, 246, 247);
		--docsearch-container-background: rgba(9, 10, 17, 0.8);
		--docsearch-modal-background: #151e2a;
		--docsearch-modal-shadow: inset 1px 1px 0 0 rgb(44, 46, 64), 0 3px 8px 0 rgb(0, 3, 9);
		--docsearch-searchbox-background: #000;
		--docsearch-searchbox-focus-background: #000;
		--docsearch-hit-color: rgb(190, 195, 201);
		--docsearch-hit-shadow: none;
		--docsearch-hit-background: rgb(9, 10, 17);
		--docsearch-key-gradient: linear-gradient(-26.5deg, #566272 0%, #31425b 100%);
		--docsearch-key-shadow:
			inset 0 -2px 0 0 rgb(40, 56, 85), inset 0 0 1px 1px rgb(81, 93, 125), 0 2px 2px 0 rgba(3, 5, 9, 0.3);
		--docsearch-key-pressed-shadow: inset 0 -2px 0 0 #283b55, inset 0 0 1px 1px #51617d, 0 1px 1px 0 #0305094d;
		--docsearch-footer-background: #1f2936;
		--docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 86, 106, 0.5), 0 -4px 8px 0 rgba(0, 0, 0, 0.2);
		--docsearch-logo-color: rgb(255, 255, 255);
		--docsearch-muted-color: #aaa;
	}
}

@layer base {
	* {
		@apply border-border;
	}
	body {
		@apply bg-background text-foreground;
	}
}


================================================
FILE: src/app.d.ts
================================================
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
	namespace App {
		// interface Error {}
		// interface Locals {}
		// interface PageData {}
		// interface PageState {}
		// interface Platform {}
	}
}

export {};


================================================
FILE: src/app.html
================================================
<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/png" href="%sveltekit.assets%/favicon.png" />
		<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
		%sveltekit.head%
		<!-- Google tag (gtag.js) -->
		<script async src="https://www.googletagmanager.com/gtag/js?id=G-X35TWD4JKW"></script>
		<script>
			window.dataLayer = window.dataLayer || [];
			function gtag() {
				dataLayer.push(arguments);
			}
			gtag('js', new Date());
			gtag('config', 'G-X35TWD4JKW');
		</script>
	</head>
	<body data-sveltekit-preload-data="hover" class="antialiased">
		<div class="contents">%sveltekit.body%</div>
	</body>
</html>


================================================
FILE: src/content/CodeBlock.svelte
================================================
<script lang="ts">
	// import { browser } from '$app/environment';
	import type { HighlighterCore } from 'shiki';
	// import svelte from 'shiki/langs/svelte.mjs';
	// import dark from 'shiki/themes/github-dark-default.mjs';

	let {
		content,
		shiki
	}: {
		content: string;
		shiki: HighlighterCore;
	} = $props();

	const _content = $derived.by(() => {
		return content.replaceAll('\t', '  ').trim();
	});
</script>

<div class="my-6">
	<div class="line-numbers subpixel-antialiased">
		<!-- eslint-disable-next-line svelte/no-at-html-tags -->
		{@html shiki.codeToHtml(_content, { lang: 'svelte', theme: 'github-dark-default' })}
	</div>
	<div class="-mt-3 text-right text-sm">
		Our examples use <a href="https://tailwindcss.com/">Tailwind CSS</a> and
		<a href="https://next.shadcn-svelte.com/">shadcn-svelte</a>.
	</div>
</div>

<style>
	:global(.line-numbers .shiki code) {
		font-size: 13px;
		tab-size: 2;
		counter-reset: step;
		counter-increment: step 0;
	}

	:global(.line-numbers .shiki code .line::before) {
		content: counter(step);
		counter-increment: step;
		width: 1em;
		margin-right: 2em;
		display: inline-block;
		text-align: right;
		color: rgba(115, 131, 148, 0.5);
	}
</style>


================================================
FILE: src/content/components/toc.ts
================================================
import type { Toc } from '$lib/components/types';

export const toc: Toc = [
	{
		title: 'Map',
		items: {
			'/docs/components/MapLibre': 'MapLibre',
			'/docs/components/Image': 'Image',
			'/docs/components/Light': 'Light',
			'/docs/components/Projection': 'Projection',
			'/docs/components/Sky': 'Sky',
			'/docs/components/Sprite': 'Sprite',
			'/docs/components/Terrain': 'Terrain'
		}
	},
	{
		title: 'Sources',
		items: {
			'/docs/components/CanvasSource': 'CanvasSource',
			'/docs/components/FeatureState': 'FeatureState',
			'/docs/components/GeoJSONSource': 'GeoJSONSource',
			'/docs/components/ImageSource': 'ImageSource',
			'/docs/components/RasterDEMTileSource': 'RasterDEMTileSource',
			'/docs/components/RasterTileSource': 'RasterTileSource',
			'/docs/components/RawSource': 'RawSource',
			'/docs/components/VectorTileSource': 'VectorTileSource',
			'/docs/components/VideoSource': 'VideoSource',
			'/docs/components/MapLibreContourSource': 'MapLibreContourSource (ext)'
		}
	},
	{
		title: 'Layers',
		items: {
			'/docs/components/BackgroundLayer': 'BackgroundLayer',
			'/docs/components/CircleLayer': 'CircleLayer',
			'/docs/components/ColorReliefLayer': 'ColorReliefLayer',
			'/docs/components/CustomLayer': 'CustomLayer',
			'/docs/components/FillExtrusionLayer': 'FillExtrusionLayer',
			'/docs/components/HeatmapLayer': 'HeatmapLayer',
			'/docs/components/HillshadeLayer': 'HillshadeLayer',
			'/docs/components/LineLayer': 'LineLayer',
			'/docs/components/RasterLayer': 'RasterLayer',
			'/docs/components/RawLayer': 'RawLayer',
			'/docs/components/SymbolLayer': 'SymbolLayer'
		}
	},
	{
		title: 'Global',
		items: {
			'/docs/components/Protocol': 'Protocol',
			'/docs/components/PMTilesProtocol': 'PMTilesProtocol (ext)'
		}
	},
	{
		title: 'Marker',
		items: {
			'/docs/components/Marker': 'Marker',
			'/docs/components/Popup': 'Popup'
		}
	},
	{
		title: 'Controls',
		items: {
			'/docs/components/AttributionControl': 'AttributionControl',
			'/docs/components/CustomControl': 'CustomControl',
			'/docs/components/FullScreenControl': 'FullScreenControl',
			'/docs/components/GeolocateControl': 'GeolocateControl',
			'/docs/components/GlobeControl': 'GlobeControl',
			'/docs/components/Hash': 'Hash',
			'/docs/components/LogoControl': 'LogoControl',
			'/docs/components/NavigationControl': 'NavigationControl',
			'/docs/components/ScaleControl': 'ScaleControl',
			'/docs/components/TerrainControl': 'TerrainControl',
			'/docs/components/DeckGLOverlay': 'DeckGLOverlay (ext)',
			'/docs/components/TerraDraw': 'TerraDraw (ext)'
		}
	},
	{
		title: 'Utilities',
		items: {
			'/docs/components/ImageLoader': 'ImageLoader',
			'/docs/components/QueryRenderedFeatures': 'QueryRenderedFeatures',
			'/docs/components/QuerySourceFeatures': 'QuerySourceFeatures'
		}
	}
];


================================================
FILE: src/content/docs/quickstart/Marker.svelte
================================================
<script lang="ts">
	import { MapLibre, Marker } from 'svelte-maplibre-gl';
</script>

<MapLibre
	zoom={5}
	center={[142, 43]}
	class="h-[400px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
>
	<Marker lnglat={[141.692222, 42.775]} />
</MapLibre>


================================================
FILE: src/content/docs/quickstart/Simplest.svelte
================================================
<script lang="ts">
	import { MapLibre } from 'svelte-maplibre-gl';
</script>

<!-- Height must be set, otherwise the map size will be zero! -->
<!-- Our examples use Tailwind CSS classes for styling. -->
<MapLibre class="h-[400px]" style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json" />


================================================
FILE: src/content/docs/quickstart/content.svelte.md
================================================
---
title: Quickstart
description: Get started with svelte-maplibre-gl in just a few minutes.
---

<script lang="ts">
  import Simplest from "./Simplest.svelte";
  import simplestRaw from "./Simplest.svelte?raw";
  import Marker from "./Marker.svelte";
  import markerRaw from "./Marker.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

## 1. Launch a SvelteKit Project

Create a new SvelteKit project using the official [Svelte CLI](https://svelte.dev/docs/kit/creating-a-project).

```bash
npx sv create myapp
# Make sure to enable the Tailwind CSS add-on,
# as our examples use it for styling.

cd myapp
npm install
```

## 2. Install `svelte-maplibre-gl`

```bash
npm install -D svelte-maplibre-gl
```

## 3. Add the Simplest Map

Now you can add the simplest MapLibre GL JS map to your `+page.svelte` file with just one line of code.

<CodeBlock content={simplestRaw} {shiki} />
<Simplest />

## 4. Put a Marker on the Map

Let’s set an initial zoom and put a marker pin on the map.

<CodeBlock content={markerRaw} {shiki} />
<Marker />


================================================
FILE: src/content/docs/toc.ts
================================================
import type { Toc } from '$lib/components/types';

export const toc: Toc = [
	{
		title: 'Overview',
		items: {
			'/docs/quickstart': 'Quickstart'
			// '/docs/Concept': 'Concept',
		}
	}
];


================================================
FILE: src/content/examples/3d-buildings/Buildings3D.svelte
================================================
<script lang="ts">
	import { MapLibre, FillExtrusionLayer } from 'svelte-maplibre-gl';
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={14.5}
	pitch={70}
	minZoom={14}
	bearing={0}
	center={[-74.01, 40.7075]}
>
	<FillExtrusionLayer
		source="carto"
		sourceLayer="building"
		minzoom={14}
		filter={['!=', ['get', 'hide_3d'], true]}
		paint={{
			'fill-extrusion-color': [
				'interpolate',
				['linear'],
				['get', 'render_height'],
				0,
				'#aaccbb',
				200,
				'royalblue',
				400,
				'purple'
			],
			'fill-extrusion-height': ['interpolate', ['linear'], ['zoom'], 14, 0, 15, ['get', 'render_height']],
			'fill-extrusion-base': ['case', ['>=', ['get', 'zoom'], 14], ['get', 'render_min_height'], 0]
		}}
	/>
</MapLibre>


================================================
FILE: src/content/examples/3d-buildings/content.svelte.md
================================================
---
title: 3D Buildings
description: Use extrusions to display buildings' height in 3D.
original: https://maplibre.org/maplibre-gl-js/docs/examples/3d-buildings/
---

<script lang="ts">
  import Demo from "./Buildings3D.svelte";
  import demoRaw from "./Buildings3D.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/3d-extrusion-floorplan/Floorplan.svelte
================================================
<script lang="ts">
	import {
		MapLibre,
		RasterTileSource,
		BackgroundLayer,
		RasterLayer,
		GeoJSONSource,
		FillExtrusionLayer
	} from 'svelte-maplibre-gl';
</script>

<MapLibre class="h-[50vh] min-h-[300px]" zoom={16.5} center={[-87.61694, 41.86625]} pitch={40} bearing={30}>
	<BackgroundLayer paint={{ 'background-color': '#e0dfdf' }} />
	<RasterTileSource tiles={['https://tile.openstreetmap.org/{z}/{x}/{y}.png']} tileSize={256} minzoom={0} maxzoom={19}>
		<RasterLayer />
	</RasterTileSource>
	<GeoJSONSource data="https://maplibre.org/maplibre-gl-js/docs/assets/indoor-3d-map.geojson">
		<FillExtrusionLayer
			paint={{
				// Get the fill-extrusion parameters from the source GeoJSON properties.
				//
				// See the MapLibre Style Specification for details on data expressions.
				// https://maplibre.org/maplibre-style-spec/expressions/
				'fill-extrusion-color': ['get', 'color'],
				'fill-extrusion-height': ['get', 'height'],
				'fill-extrusion-base': ['get', 'base_height'],
				'fill-extrusion-opacity': 0.5
			}}
		/>
	</GeoJSONSource>
</MapLibre>


================================================
FILE: src/content/examples/3d-extrusion-floorplan/content.svelte.md
================================================
---
title: 3D Floor Plan
description: Create a 3D indoor map with the fill-extrude-height paint property.
original: https://maplibre.org/maplibre-gl-js/docs/examples/3d-extrusion-floorplan/
---

<script lang="ts">
  import Demo from "./Floorplan.svelte";
  import demoRaw from "./Floorplan.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/animate-images/AnimateImages.svelte
================================================
<script lang="ts">
	import { MapLibre, ImageSource, GlobeControl, RasterLayer } from 'svelte-maplibre-gl';

	const FRAME_COUNT = 5;
	let frame = $state(0);

	$effect(() => {
		function update() {
			frame = Math.round((performance.now() / 1000) * 5) % FRAME_COUNT;
			requestAnimationFrame(update);
		}
		requestAnimationFrame(update);
	});
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
	zoom={5}
	center={[-76, 43]}
>
	<GlobeControl />
	<ImageSource
		url={`https://maplibre.org/maplibre-gl-js/docs/assets/radar${frame}.gif`}
		coordinates={[
			[-80.425, 46.437],
			[-71.516, 46.437],
			[-71.516, 37.936],
			[-80.425, 37.936]
		]}
	>
		<RasterLayer paint={{ 'raster-fade-duration': 0 }} />
	</ImageSource>
</MapLibre>


================================================
FILE: src/content/examples/animate-images/content.svelte.md
================================================
---
title: Animate a series of images
description: Use a series of image sources to create an animation.
orignal: https://maplibre.org/maplibre-gl-js/docs/examples/animate-images/
---

<script lang="ts">
  import Demo from "./AnimateImages.svelte";
  import demoRaw from "./AnimateImages.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/basestyle/BaseStyle.svelte
================================================
<script lang="ts">
	import {
		HillshadeLayer,
		Light,
		LineLayer,
		MapLibre,
		Projection,
		ImageLoader,
		RasterDEMTileSource,
		Sky,
		Terrain,
		GeoJSONSource,
		SymbolLayer,
		VectorTileSource
	} from 'svelte-maplibre-gl';

	import maplibregl from 'maplibre-gl';
	import { Label } from '$lib/components/ui/label/index.js';
	import * as RadioGroup from '$lib/components/ui/radio-group/index.js';
	import { Switch } from '$lib/components/ui/switch/index.js';
	import type { FeatureCollection } from 'geojson';

	// Base styles
	const STYLES = new Map<string, string | maplibregl.StyleSpecification>([
		['Voyager', 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json'],
		['Positron', 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json'],
		['Dark Matter', 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json'],
		['Demo Tiles', 'https://demotiles.maplibre.org/style.json']
	]);
	let name = $state('Voyager');
	let style = $derived(STYLES.get(name)!);
	let globe = $state(true);

	let data: FeatureCollection = {
		type: 'FeatureCollection',
		features: [
			{
				type: 'Feature',
				geometry: { type: 'Point', coordinates: [140, 30] },
				properties: { imageName: 'osgeo', year: 2024 }
			}
		]
	};
</script>

<div class="mb-3 flex items-center justify-between">
	<RadioGroup.Root bind:value={name} class="flex flex-row gap-x-3">
		{#each STYLES as [name] (name)}
			<div class="flex items-center space-x-1">
				<RadioGroup.Item value={name} id={name} />
				<Label class="cursor-pointer" for={name}>{name}</Label>
			</div>
		{/each}
	</RadioGroup.Root>

	<div class="flex items-center space-x-2">
		<Switch id="globe" bind:checked={globe} />
		<Label for="globe">Globe</Label>
	</div>
</div>

<MapLibre class="h-[55vh] min-h-75" {style} zoom={4} maxPitch={80} center={{ lng: 137, lat: 36 }}>
	<!-- User-defined dynamic styles -->
	<Projection type={globe ? 'globe' : undefined} />
	<Light anchor="map" />
	<Sky
		sky-color="#001560"
		horizon-color="#0090c0"
		fog-color="#ffffff"
		sky-horizon-blend={0.9}
		horizon-fog-blend={0.7}
		fog-ground-blend={0.6}
		atmosphere-blend={['interpolate', ['linear'], ['zoom'], 1, 0.6, 3, 0.3, 5, 0]}
	/>
	<VectorTileSource
		tiles={['https://jma-assets.mierune.dev/tiles/mete/{z}/{x}/{y}.pbf']}
		minzoom={0}
		maxzoom={13}
		attribution="<a href='https://www.data.jma.go.jp/developer/gis.html'>JMA</a>"
	>
		<LineLayer
			sourceLayer="city"
			layout={{ 'line-join': 'round', 'line-cap': 'round' }}
			paint={{ 'line-color': '#ff00ff', 'line-width': 1 }}
		/>
	</VectorTileSource>
	<RasterDEMTileSource url="https://tiles.mapterhorn.com/tilejson.json">
		<HillshadeLayer paint={{ 'hillshade-exaggeration': 0.2 }} />
	</RasterDEMTileSource>
	{#if !globe}
		<RasterDEMTileSource url="https://tiles.mapterhorn.com/tilejson.json">
			<Terrain />
		</RasterDEMTileSource>
	{/if}
	<ImageLoader
		images={{
			osgeo: 'https://maplibre.org/maplibre-gl-js/docs/assets/osgeo-logo.png'
		}}
	>
		<GeoJSONSource {data}>
			<!-- Children components will be added after all images have been loaded -->
			<SymbolLayer
				layout={{
					'text-field': ['get', 'name'],
					'icon-image': ['get', 'imageName'],
					'icon-size': ['number', ['get', 'scale'], 1],
					'icon-text-fit': 'both',
					'icon-overlap': 'always',
					'text-overlap': 'always'
				}}
			/>
		</GeoJSONSource>
	</ImageLoader>
</MapLibre>


================================================
FILE: src/content/examples/basestyle/content.svelte.md
================================================
---
title: Change Base Style
description: This library efficiently preserves dynamic user contents even when the base style changes.
---

<script lang="ts">
  import Demo from "./BaseStyle.svelte";
  import demoRaw from "./BaseStyle.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/canvas-source/Canvas.svelte
================================================
<script lang="ts">
	import { MapLibre, CanvasSource, GlobeControl, RasterLayer } from 'svelte-maplibre-gl';
	import { Circle } from './Circle.js';

	let canvas: HTMLCanvasElement | undefined = $state();
	let ctx = $derived(canvas && canvas.getContext('2d')!);
	let animate = $state(true);

	const SIZE = 500;
	const RADIUS = 15;
	const circles: Circle[] = [];
	for (let i = 0; i < 20; i++) {
		const x = Math.random() * (SIZE - RADIUS * 2) + RADIUS;
		const y = Math.random() * (SIZE - RADIUS * 2) + RADIUS;
		const dx = (Math.random() - 0.5) * 2;
		const dy = (Math.random() - 0.5) * 2;
		const color = `#${(0x1000000 + Math.random() * 0xffffff).toString(16).substring(1, 7)}`;
		circles.push(new Circle(x, y, dx, dy, RADIUS, color));
	}

	function frame() {
		if (ctx && animate) {
			ctx.clearRect(0, 0, SIZE, SIZE);
			for (const circle of circles) {
				circle.update(ctx);
			}
		}
		requestAnimationFrame(frame);
	}

	$effect(() => {
		requestAnimationFrame(frame);
	});
</script>

<canvas bind:this={canvas} class="hidden" width={SIZE} height={SIZE}>Canvas not supported</canvas>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={2}
	center={{ lng: 135, lat: 35 }}
	onclick={() => (animate = !animate)}
>
	<GlobeControl />
	<CanvasSource
		{canvas}
		{animate}
		coordinates={[
			[110, 60],
			[160, 60],
			[160, 10],
			[110, 10]
		]}
	>
		<RasterLayer paint={{ 'raster-fade-duration': 0 }} />
	</CanvasSource>
</MapLibre>


================================================
FILE: src/content/examples/canvas-source/Circle.ts
================================================
export class Circle {
	constructor(
		public x: number,
		public y: number,
		public dx: number,
		public dy: number,
		public radius: number,
		public color: string
	) {}

	draw(ctx: CanvasRenderingContext2D) {
		ctx.beginPath();
		ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
		ctx.strokeStyle = this.color;
		ctx.stroke();
	}

	update(ctx: CanvasRenderingContext2D) {
		if (this.x + this.radius > ctx.canvas.width || this.x - this.radius < 0) {
			this.dx = -this.dx;
		}
		if (this.y + this.radius > ctx.canvas.height || this.y - this.radius < 0) {
			this.dy = -this.dy;
		}
		this.x += this.dx;
		this.y += this.dy;

		this.draw(ctx);
	}
}


================================================
FILE: src/content/examples/canvas-source/content.svelte.md
================================================
---
title: Canvas Source
description: Add a canvas source to the map.
original: https://maplibre.org/maplibre-gl-js/docs/examples/canvas-source/
---

<script lang="ts">
  import Demo from "./Canvas.svelte";
  import demoRaw from "./Canvas.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/clusters/Clusters.svelte
================================================
<script lang="ts">
	import { CircleLayer, MapLibre, GeoJSONSource, SymbolLayer, GlobeControl } from 'svelte-maplibre-gl';
	import { Slider } from '$lib/components/ui/slider/index.js';
	import { Checkbox } from '$lib/components/ui/checkbox/index.js';
	import { Label } from '$lib/components/ui/label/index.js';

	let cluster = $state(true);
	let clusterMaxZoom = $state(11);
	let clusterRadius = $state(50);
</script>

<div class="mb-4 flex items-center justify-between gap-x-10">
	<div class="flex items-center space-x-2">
		<Checkbox id="cluster" bind:checked={cluster} />
		<Label
			for="cluster"
			class="text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70">Cluster</Label
		>
	</div>
	<div class="flex flex-1 grow flex-col gap-y-4">
		<Label for="clusterMaxZoom">clusterMaxZoom: {clusterMaxZoom.toFixed(2)}</Label>
		<Slider type="single" id="clusterMaxZoom" bind:value={clusterMaxZoom} min={0} max={22} step={1} />
	</div>
	<div class="flex flex-1 grow flex-col gap-y-4">
		<Label for="clusterRadius">clusterRadius: {clusterRadius.toFixed(2)}</Label>
		<Slider type="single" id="clusterRadius" bind:value={clusterRadius} min={0} max={100} step={1} />
	</div>
</div>

<MapLibre
	class="h-[55vh] min-h-75"
	style="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
	zoom={2}
	center={{ lng: 180, lat: 35 }}
>
	<GlobeControl />
	<GeoJSONSource
		data="https://maplibre.org/maplibre-gl-js/docs/assets/earthquakes.geojson"
		{cluster}
		clusterMaxZoom={cluster ? clusterMaxZoom : undefined}
		clusterRadius={cluster ? clusterRadius : undefined}
	>
		<CircleLayer
			filter={['has', 'point_count']}
			paint={{
				'circle-color': ['step', ['get', 'point_count'], '#51bbd6', 50, '#f1f075', 150, '#f28cb1'],
				'circle-radius': ['+', 10, ['sqrt', ['get', 'point_count']]],
				'circle-opacity': 0.8
			}}
		/>
		<SymbolLayer
			filter={['has', 'point_count']}
			layout={{
				'text-field': '{point_count_abbreviated}',
				'text-size': 12
			}}
		/>
		<CircleLayer
			filter={['!', ['has', 'point_count']]}
			paint={{
				'circle-color': '#ffff00',
				'circle-radius': 2
			}}
		/>
	</GeoJSONSource>
</MapLibre>


================================================
FILE: src/content/examples/clusters/content.svelte.md
================================================
---
title: Clusters
description: Use MapLibre's built-in functions to visualize points as clusters.
original: https://maplibre.org/maplibre-gl-js/docs/examples/cluster/
---

<script lang="ts">
  import Demo from "./Clusters.svelte";
  import demoRaw from "./Clusters.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/color-relief/ColorRelief.svelte
================================================
<script lang="ts">
	import {
		HillshadeLayer,
		MapLibre,
		RasterDEMTileSource,
		TerrainControl,
		GlobeControl,
		Light,
		ColorReliefLayer
	} from 'svelte-maplibre-gl';
	import type { ExpressionSpecification } from 'maplibre-gl';
	import { Label } from '$lib/components/ui/label/index.js';
	import { Slider } from '$lib/components/ui/slider/index.js';

	// https://nathanmolson.github.io/color_relief
	const COLOR_RAMPS: Record<string, ExpressionSpecification> = {
		LINZ: [
			'interpolate',
			['linear'],
			['elevation'],
			0,
			'#c0e0ffff',
			0.1,
			'#d8d8d8ff',
			3,
			'#548359ff',
			255,
			'#32482dff',
			1000,
			'#32482dff',
			1200,
			'#adb7a3ff',
			1700,
			'#bfbfb8ff',
			1750,
			'#e6f4fdff',
			3000,
			'#ffffffff'
		],
		isoluminant: [
			'interpolate',
			['linear'],
			['elevation'],
			0,
			'rgb(112, 209, 255)',
			12.88581315,
			'rgb(113, 211, 247)',
			51.5432526,
			'rgb(114, 212, 234)',
			115.9723183,
			'rgb(117, 213, 222)',
			206.1730104,
			'rgb(120, 214, 209)',
			322.1453287,
			'rgb(124, 215, 196)',
			463.8892734,
			'rgb(130, 215, 183)',
			631.4048443,
			'rgb(138, 215, 169)',
			824.6920415,
			'rgb(149, 214, 155)',
			1043.750865,
			'rgb(163, 212, 143)',
			1288.581315,
			'rgb(178, 209, 134)',
			1559.183391,
			'rgb(193, 205, 127)',
			1855.557093,
			'rgb(207, 202, 121)',
			2177.702422,
			'rgb(220, 197, 118)',
			2525.619377,
			'rgb(233, 193, 118)',
			2899.307958,
			'rgb(244, 188, 120)',
			3298.768166,
			'rgb(255, 183, 124)',
			3724,
			'rgb(255, 178, 129)'
		],
		rainbow: [
			'interpolate',
			['linear'],
			['elevation'],
			0,
			'rgb(4, 0, 108)',
			12.88581315,
			'rgb(5, 1, 154)',
			51.5432526,
			'rgb(10, 21, 189)',
			115.9723183,
			'rgb(16, 44, 218)',
			206.1730104,
			'rgb(24, 69, 240)',
			322.1453287,
			'rgb(20, 112, 193)',
			463.8892734,
			'rgb(39, 144, 116)',
			631.4048443,
			'rgb(57, 169, 29)',
			824.6920415,
			'rgb(111, 186, 5)',
			1043.750865,
			'rgb(160, 201, 4)',
			1288.581315,
			'rgb(205, 216, 2)',
			1559.183391,
			'rgb(244, 221, 4)',
			1855.557093,
			'rgb(251, 194, 14)',
			2177.702422,
			'rgb(252, 163, 21)',
			2525.619377,
			'rgb(253, 128, 20)',
			2899.307958,
			'rgb(254, 85, 14)',
			3298.768166,
			'rgb(243, 36, 13)',
			3724,
			'rgb(215, 5, 13)'
		],
		geographical: [
			'interpolate',
			['linear'],
			['elevation'],
			0,
			'rgb(112, 209, 255)',
			1,
			'rgb(112, 209, 255)',
			2,
			'rgb(112, 173, 92)',
			176.4705882,
			'rgb(131, 174, 94)',
			352.9411765,
			'rgb(149, 175, 95)',
			529.4117647,
			'rgb(166, 176, 97)',
			705.8823529,
			'rgb(181, 177, 99)',
			882.3529412,
			'rgb(195, 177, 101)',
			1058.823529,
			'rgb(208, 178, 103)',
			1235.294118,
			'rgb(220, 180, 105)',
			1411.764706,
			'rgb(228, 182, 108)',
			1588.235294,
			'rgb(231, 187, 111)',
			1764.705882,
			'rgb(231, 192, 118)',
			1941.176471,
			'rgb(231, 197, 129)',
			2117.647059,
			'rgb(231, 203, 144)',
			2294.117647,
			'rgb(230, 208, 161)',
			2470.588235,
			'rgb(229, 212, 177)',
			2647.058824,
			'rgb(229, 217, 194)',
			2823.529412,
			'rgb(228, 222, 210)',
			3000,
			'rgb(226, 226, 226)'
		],
		categorical: [
			'interpolate',
			['linear'],
			['elevation'],
			0,
			'rgb(4, 0, 108)',
			1,
			'rgb(5, 1, 159)',
			232.75,
			'rgb(5, 1, 159)',
			233.75,
			'rgb(12, 28, 197)',
			465.5,
			'rgb(12, 28, 197)',
			466.5,
			'rgb(17, 53, 230)',
			698.25,
			'rgb(17, 53, 230)',
			699.25,
			'rgb(32, 92, 222)',
			931,
			'rgb(32, 92, 222)',
			932,
			'rgb(21, 135, 144)',
			1163.75,
			'rgb(21, 135, 144)',
			1164.75,
			'rgb(51, 164, 44)',
			1396.5,
			'rgb(51, 164, 44)',
			1397.5,
			'rgb(108, 184, 6)',
			1629.25,
			'rgb(108, 184, 6)',
			1630.25,
			'rgb(163, 202, 4)',
			1862,
			'rgb(163, 202, 4)',
			1863,
			'rgb(214, 218, 2)',
			2094.75,
			'rgb(214, 218, 2)',
			2095.75,
			'rgb(249, 214, 7)',
			2327.5,
			'rgb(249, 214, 7)',
			2328.5,
			'rgb(252, 180, 18)',
			2560.25,
			'rgb(252, 180, 18)',
			2561.25,
			'rgb(252, 143, 21)',
			2793,
			'rgb(252, 143, 21)',
			2794,
			'rgb(254, 98, 16)',
			3025.75,
			'rgb(254, 98, 16)',
			3026.75,
			'rgb(246, 41, 13)',
			3258.5,
			'rgb(246, 41, 13)',
			3259.5,
			'rgb(215, 5, 13)',
			3491.25,
			'rgb(215, 5, 13)'
		],
		monochrome: ['interpolate', ['linear'], ['elevation'], 0.1, '#111', 0.2, 'black', 3724, 'white'],
		rgbk: ['interpolate', ['linear'], ['elevation'], 0, '#f00', 800, '#0f0', 1600, '#00f', 2400, '#fff', 3724, 'black']
	};
	type ColorRamp = keyof typeof COLOR_RAMPS;

	let colorRamp: ColorRamp = $state('LINZ');
	let hillshade = $state(0.4);
</script>

<MapLibre class="h-[55vh] min-h-75" zoom={9.5} center={{ lng: 11.5, lat: 47.3 }}>
	<GlobeControl />
	<Light anchor="map" />
	<!-- Terrain -->
	<RasterDEMTileSource url="https://tiles.mapterhorn.com/tilejson.json">
		<TerrainControl position="top-right" />
	</RasterDEMTileSource>
	<!-- Color Relief and Hillshade -->
	<RasterDEMTileSource url="https://tiles.mapterhorn.com/tilejson.json">
		<ColorReliefLayer
			paint={{
				'color-relief-opacity': 1,
				'color-relief-color': COLOR_RAMPS[colorRamp]
			}}
		/>
		<HillshadeLayer
			paint={{
				'hillshade-method': 'igor',
				'hillshade-exaggeration': hillshade,
				'hillshade-highlight-color': '#ffffff'
			}}
		/>
	</RasterDEMTileSource>

	<!-- Controls -->
	<div
		class="absolute top-3 left-3 z-10 flex min-w-50 flex-col items-stretch gap-1 rounded bg-background/60 p-3 text-sm backdrop-blur-sm"
	>
		<div class="mb-2 flex items-center justify-between space-x-2">
			<Label for="shadow-method" class="leading-none">Color Ramp</Label>
			<select bind:value={colorRamp} id="hillshade-method" class="text-center">
				{#each Object.keys(COLOR_RAMPS) as ramp (ramp)}
					<option value={ramp}>{ramp}</option>
				{/each}
			</select>
		</div>
		<div class="flex items-center justify-between space-x-3">
			<Label for="hillshade" class="leading-none">Hillshade</Label>
			<Slider type="single" id="hillshade" bind:value={hillshade} min={0} max={1} step={0.01} />
		</div>
	</div>
</MapLibre>


================================================
FILE: src/content/examples/color-relief/content.svelte.md
================================================
---
title: Color Relief
description: Render hypsometric tints using DEM sources
original: https://nathanmolson.github.io/color_relief/
---

<script lang="ts">
  import Demo from "./ColorRelief.svelte";
  import demoRaw from "./ColorRelief.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/complex/Complex.svelte
================================================
<script lang="ts">
	import maplibregl from 'maplibre-gl';
	import {
		MapLibre,
		RasterTileSource,
		RasterDEMTileSource,
		VectorTileSource,
		GeoJSONSource,
		BackgroundLayer,
		RasterLayer,
		FillLayer,
		LineLayer,
		CircleLayer,
		FillExtrusionLayer,
		NavigationControl,
		FullScreenControl,
		ScaleControl,
		LogoControl,
		GeolocateControl,
		AttributionControl,
		HeatmapLayer,
		TerrainControl,
		Hash,
		HillshadeLayer,
		Terrain,
		Sky,
		Projection,
		Light,
		Marker,
		Popup,
		GlobeControl
	} from 'svelte-maplibre-gl';
	import { PMTilesProtocol } from '@svelte-maplibre-gl/pmtiles';

	let map: maplibregl.Map | undefined = $state.raw();
	let hash = $state(true);
	let sky = $state(true);
	let globe = $state(true);
	let showCities = $state(true);
	let hillshade = $state(true);
	let extrude = $state(false);
	let heatmap = $state(false);
	let pointColor = $state('#ffff00');
	let lineColor = $state('#ff00dd');
	let lineWidth = $state(1.5);
	let circleRadius = $state(3);
	let center: [number, number] = $state([137.3543, 37.062]);
	let zoom = $state(6.0);
	let pitch = $state(0);
	let bearing = $state(0);
	let controlPosition: maplibregl.ControlPosition | undefined = $state('bottom-right');
	let markerLnglat = $state({ lng: 139.767052, lat: 35.681167 });
	let popupOpen = $state(false);
</script>

<PMTilesProtocol />

<div class="flex items-center gap-x-2 p-1 text-sm">
	<label>
		<input class="rounded border p-1 leading-none" type="checkbox" bind:checked={showCities} />
		Cities
	</label>
	<label>
		<input class="rounded border p-1 leading-none" type="checkbox" bind:checked={hillshade} />
		Hillshade
	</label>
	<label>
		<input class="rounded border p-1 leading-none" type="checkbox" bind:checked={sky} />
		Sky
	</label>
	<label>
		<input class="rounded border p-1 leading-none" type="checkbox" bind:checked={extrude} />
		Extrude
	</label>
	<label>
		<input class="rounded border p-1 leading-none" type="checkbox" bind:checked={heatmap} />
		Heatmap
	</label>
	<label>
		<input class="rounded border p-1 leading-none" type="checkbox" bind:checked={globe} />
		Globe
	</label>
	<label>
		pC:
		<input type="color" bind:value={pointColor} class="inline-block w-7 rounded border leading-none" />
	</label>
	<label>
		pR:
		<input
			type="number"
			min="0"
			max="10"
			step="0.5"
			bind:value={circleRadius}
			class="w-12 rounded border p-1 leading-none"
		/>
	</label>
	<label>
		lC:
		<input type="color" bind:value={lineColor} class="w-7 rounded border leading-none" />
	</label>
	<label>
		lW:
		<input
			type="number"
			min="0"
			max="10"
			step="0.5"
			bind:value={lineWidth}
			class="w-12 rounded border p-1 leading-none"
		/>
	</label>
	<select bind:value={controlPosition}>
		<option value="top-left">top-left</option>
		<option value="top-right">top-right</option>
		<option value="bottom-left">botom-left</option>
		<option value="bottom-right">bottom-right</option>
		<option value={undefined}>auto</option>
	</select>
	<button
		class="rounded border p-1 leading-none"
		onclick={() => {
			map?.flyTo({ center: markerLnglat, zoom: 15 });
		}}>Fly to</button
	>
</div>
<div class="flex items-center gap-x-4 text-sm">
	<pre
		class="my-1 grow">{`lat: ${center[1].toFixed(3)}, lng: ${center[0].toFixed(3)}, z: ${zoom.toFixed(1)}, pitch: ${pitch.toFixed(1)}, bearing: ${bearing.toFixed(1)}`}</pre>
	<pre class="my-1 grow">marker: {`${markerLnglat.lat.toFixed(3)}, ${markerLnglat.lng.toFixed(3)}`}</pre>
	<label>
		z:
		<input type="number" min="0" max="24" step="0.5" bind:value={zoom} class="w-12 rounded border p-1 leading-none" />
	</label>
	<label>
		<input type="checkbox" bind:checked={popupOpen} /> Popup Open
	</label>
	<label>
		<input type="checkbox" bind:checked={hash} /> Hash
	</label>
</div>

<MapLibre
	class="h-[55vh] min-h-75"
	bind:map
	bind:zoom
	bind:center
	bind:pitch
	bind:bearing
	maxPitch={85}
	attributionControl={false}
>
	{#if hash}
		<Hash />
	{/if}
	{#if sky}
		<Sky
			sky-color="#001560"
			horizon-color="#0090c0"
			fog-color="#ffffff"
			sky-horizon-blend={0.9}
			horizon-fog-blend={0.8}
			fog-ground-blend={0.7}
			atmosphere-blend={['interpolate', ['linear'], ['zoom'], 2, 0.8, 4, 0.3, 7, 0]}
		/>
	{/if}
	<Light anchor="map" />
	<Projection type={globe ? 'globe' : undefined} />
	<AttributionControl position={controlPosition} compact />
	<LogoControl position={controlPosition} />
	<ScaleControl position={controlPosition} />
	<FullScreenControl position={controlPosition} />
	<GeolocateControl position={controlPosition} />
	<NavigationControl position={controlPosition} visualizePitch />
	<TerrainControl position={controlPosition} source="terrain" />
	<GlobeControl position={controlPosition} />
	<RasterDEMTileSource id="terrain" url="https://tiles.mapterhorn.com/tilejson.json">
		{#if !globe}
			<Terrain />
		{/if}
	</RasterDEMTileSource>
	<RasterTileSource
		tiles={['https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg']}
		minzoom={2}
		maxzoom={18}
		attribution="国土地理院, TSIC, GEO Grid/AIST, USGS, GEBCO, NASA"
	>
		<RasterLayer />
	</RasterTileSource>
	<BackgroundLayer id="dummy1" layout={{ visibility: 'none' }} />
	{#if hillshade}
		<RasterDEMTileSource url="https://tiles.mapterhorn.com/tilejson.json">
			<HillshadeLayer beforeId="dummy1" />
		</RasterDEMTileSource>
	{/if}
	<BackgroundLayer id="dummy2" layout={{ visibility: 'none' }} />
	<BackgroundLayer id="dummy3" layout={{ visibility: 'none' }} />
	<VectorTileSource
		url="pmtiles://https://jma-assets.mierune.dev/pmtiles/mete.pmtiles"
		minzoom={0}
		maxzoom={13}
		attribution="<a href='https://www.data.jma.go.jp/developer/gis.html'>気象庁</a>"
	>
		{#if showCities}
			<LineLayer
				sourceLayer="city"
				beforeId="dummy3"
				layout={{ 'line-join': 'round', 'line-cap': 'round' }}
				paint={{ 'line-color': lineColor, 'line-width': lineWidth }}
			/>
			{#if extrude}
				<FillExtrusionLayer
					sourceLayer="city"
					beforeId="dummy2"
					paint={{
						'fill-extrusion-color': '#555533',
						'fill-extrusion-height': ['/', ['to-number', ['get', 'code']], 100],
						'fill-extrusion-opacity': 0.7
					}}
				/>
			{:else}
				<FillLayer
					id="cityfill"
					sourceLayer="city"
					beforeId="dummy2"
					paint={{ 'fill-color': '#aaaa33', 'fill-opacity': 0.3 }}
				/>
			{/if}
		{/if}
	</VectorTileSource>
	<GeoJSONSource data="https://jma-assets.mierune.dev/codes/amedas_ame.geojson">
		{#if heatmap}
			<HeatmapLayer
				paint={{
					'heatmap-weight': 1,
					'heatmap-intensity': ['interpolate', ['exponential', 2], ['zoom'], 0, 0.9, 18, 10],
					'heatmap-color': [
						'interpolate',
						['linear'],
						['heatmap-density'],
						0,
						'rgba(33,102,172,0)',
						0.2,
						'rgb(103,169,207)',
						0.4,
						'rgb(209,229,240)',
						0.6,
						'rgb(253,219,199)',
						0.7,
						'rgb(239,138,98)',
						0.9,
						'rgb(178,24,43)',
						1,
						'rgb(100,0,200)'
					],
					'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 8, 18, 20],
					'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 2, 1, 18, 0]
				}}
			/>
		{:else}
			<CircleLayer beforeId="dummy3" paint={{ 'circle-radius': circleRadius, 'circle-color': pointColor }} />
		{/if}
	</GeoJSONSource>
	<Marker bind:lnglat={markerLnglat} draggable color="#99dd55">
		{#snippet content()}
			<span class="text-3xl">🐸</span>
		{/snippet}
		<Popup class="text-black" bind:open={popupOpen}>
			<span class="text-lg">
				{`${markerLnglat.lat.toFixed(3)}, ${markerLnglat.lng.toFixed(3)}`}
			</span>
		</Popup>
	</Marker>
</MapLibre>


================================================
FILE: src/content/examples/complex/content.svelte.md
================================================
---
title: Complex
description: A showcase of various reactive features.
---

<script lang="ts">
  import Demo from "./Complex.svelte";
  import demoRaw from "./Complex.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/contour/Contour.svelte
================================================
<script lang="ts">
	import {
		HillshadeLayer,
		MapLibre,
		RasterDEMTileSource,
		LineLayer,
		SymbolLayer,
		TerrainControl
	} from 'svelte-maplibre-gl';
	import { MapLibreContourSource } from '@svelte-maplibre-gl/contour';
</script>

<MapLibre
	class="h-[55vh] min-h-75"
	style="https://demotiles.maplibre.org/styles/osm-bright-gl-style/style.json"
	zoom={12}
	minZoom={5}
	center={{ lng: 11.35, lat: 47.3 }}
>
	<MapLibreContourSource
		url={'https://tiles.mapterhorn.com/{z}/{x}/{y}.webp'}
		encoding="terrarium"
		maxzoom={14}
		tileOptions={{
			// multiplier: 1,
			thresholds: {
				// zoom: [minor, major]
				5: [500, 2000],
				8: [250, 1000],
				11: [100, 500],
				12: [50, 200],
				13: [20, 100],
				14: [10, 50]
			},
			// optional, override vector tile parameters:
			contourLayer: 'contours',
			elevationKey: 'ele',
			levelKey: 'level'
		}}
		attribution="<a href='https://mapterhorn.com/attribution/'>Mapterhorn</a>"
	>
		{#snippet children(demSource)}
			<RasterDEMTileSource tiles={[demSource.sharedDemProtocolUrl]} maxzoom={14} tileSize={256}>
				<TerrainControl />
			</RasterDEMTileSource>
			<RasterDEMTileSource tiles={[demSource.sharedDemProtocolUrl]} maxzoom={14} tileSize={256}>
				<HillshadeLayer
					paint={{
						'hillshade-exaggeration': 0.5,
						'hillshade-illumination-anchor': 'map',
						'hillshade-shadow-color': '#3080b0'
					}}
				/>
			</RasterDEMTileSource>
			<LineLayer
				sourceLayer="contours"
				paint={{
					'line-color': 'rgba(90, 20, 0, 1)',
					'line-width': ['match', ['get', 'level'], 1, 1.5, 0.5]
				}}
			/>
			<SymbolLayer
				sourceLayer="contours"
				filter={['>', ['get', 'level'], 0]}
				layout={{
					'symbol-placement': 'line',
					'text-size': 12,
					'text-field': ['number-format', ['get', 'ele'], {}]
				}}
				paint={{
					'text-halo-color': 'white',
					'text-halo-width': 1
				}}
			/>
		{/snippet}
	</MapLibreContourSource>
</MapLibre>


================================================
FILE: src/content/examples/contour/content.svelte.md
================================================
---
title: Contour Lines
description: Render contour lines from a raster DEM source using maplibre-contour
original: https://maplibre.org/maplibre-gl-js/docs/examples/add-contour-lines/
---

<script lang="ts">
  import Demo from "./Contour.svelte";
  import demoRaw from "./Contour.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/cursor/Cursor.svelte
================================================
<script lang="ts">
	import { MapLibre, GeoJSONSource, CircleLayer } from 'svelte-maplibre-gl';
	import type GeoJSON from 'geojson';

	const CURSORS = [
		'cell',
		'col-resize',
		'context-menu',
		'copy',
		'crosshair',
		'default',
		'grab',
		'help',
		'move',
		'not-allowed',
		'pointer',
		'progress',
		'row-resize',
		'text',
		'vertical-text',
		'wait',
		'zoom-in',
		'zoom-out'
	];
	const center = [0, 0];
	const data: GeoJSON.FeatureCollection = {
		type: 'FeatureCollection',
		features: CURSORS.map((cursor, i) => ({
			type: 'Feature',
			geometry: {
				type: 'Point',
				coordinates: [
					center[0] + Math.cos((i / CURSORS.length) * Math.PI * 2) * 15,
					center[1] + Math.sin((i / CURSORS.length) * Math.PI * 2) * 15
				]
			},
			properties: { cursor }
		}))
	};

	let cursor: string | undefined = $state();
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={2}
	center={{ lng: 0, lat: 0 }}
	{cursor}
>
	<GeoJSONSource {data}>
		<CircleLayer
			onmousemove={(e) => (cursor = e.features![0].properties.cursor)}
			onmouseleave={() => (cursor = undefined)}
			paint={{
				'circle-radius': 12,
				'circle-color': '#007cbf',
				'circle-stroke-color': '#fff',
				'circle-stroke-width': 3
			}}
		/>
	</GeoJSONSource>
</MapLibre>


================================================
FILE: src/content/examples/cursor/content.svelte.md
================================================
---
title: Change Cursor
description: Change the cursor style on hover
---

<script lang="ts">
  import Demo from "./Cursor.svelte";
  import demoRaw from "./Cursor.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/custom-control/CustomControl.svelte
================================================
<script lang="ts">
	import { HillshadeLayer, MapLibre, RasterDEMTileSource, Terrain, CustomControl } from 'svelte-maplibre-gl';
	import maplibregl from 'maplibre-gl';
	import Sun from '@lucide/svelte/icons/sun';
	import Moon from '@lucide/svelte/icons/moon';
	import ArrowUpLeft from '@lucide/svelte/icons/arrow-up-left';
	import ArrowUpRight from '@lucide/svelte/icons/arrow-up-right';
	import ArrowDownLeft from '@lucide/svelte/icons/arrow-down-left';
	import ArrowDownRight from '@lucide/svelte/icons/arrow-down-right';
	import { MyControl } from './MyControl.js';

	let isHillshadeVisible = $state(true);
	let isTerrainVisible = $state(true);
	let isDarkMode = $state(false);
	const mapStyle = $derived(
		isDarkMode
			? 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json'
			: 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json'
	);
	let center = $state({ lng: 11.09085, lat: 47.3 });
	let controlPosition: maplibregl.ControlPosition = $state('top-left');

	const myControl = new MyControl({
		toggleHillshade: () => (isHillshadeVisible = !isHillshadeVisible),
		toggleTerrain: () => (isTerrainVisible = !isTerrainVisible)
	});
</script>

<MapLibre class="h-[55vh] min-h-50" style={mapStyle} zoom={12} pitch={40} maxPitch={85} bind:center>
	<!-- inject IControl (useful for plugin) -->
	<CustomControl position="top-left" control={myControl} />

	<!-- Control / Group / Icon -->
	<CustomControl position="bottom-left">
		<button onclick={() => (isDarkMode = !isDarkMode)} class="flex! items-center justify-center text-gray-900">
			{#if isDarkMode}
				<Moon class="w-5" />
			{:else}
				<Sun class="w-5" />
			{/if}
		</button>
	</CustomControl>

	<!-- Group -->
	<CustomControl position={controlPosition} class="text-gray-900">
		<button class="flex! items-center justify-center" onclick={() => (controlPosition = 'top-left')}
			><ArrowUpLeft class="w-5" /></button
		>
		<button class="flex! items-center justify-center" onclick={() => (controlPosition = 'top-right')}
			><ArrowUpRight class="w-5" /></button
		>
		<button class="flex! items-center justify-center" onclick={() => (controlPosition = 'bottom-right')}
			><ArrowDownRight class="w-5" /></button
		>
		<button class="flex! items-center justify-center" onclick={() => (controlPosition = 'bottom-left')}
			><ArrowDownLeft class="w-5" /></button
		>
	</CustomControl>

	<!-- Control / Group / any svelte elements -->
	<CustomControl position="top-right">
		<div class="p-2 text-yellow-700">Arbitrary HTML</div>
		<div class="border-t border-t-[#ddd] p-2 text-center text-yellow-700">
			({center.lat.toFixed(4)}, {center.lng.toFixed(4)})
		</div>
	</CustomControl>

	<RasterDEMTileSource url="https://tiles.mapterhorn.com/tilejson.json">
		{#if isTerrainVisible}
			<Terrain />
		{/if}
	</RasterDEMTileSource>
	<RasterDEMTileSource url="https://tiles.mapterhorn.com/tilejson.json">
		{#if isHillshadeVisible}
			<HillshadeLayer />
		{/if}
	</RasterDEMTileSource>
</MapLibre>


================================================
FILE: src/content/examples/custom-control/MyControl.ts
================================================
interface MyControlConstructorOptions {
	toggleTerrain: () => boolean;
	toggleHillshade: () => boolean;
}

class MyControl implements maplibregl.IControl {
	private _container: HTMLElement | undefined;
	private _toggleTerrain: () => boolean;
	private _toggleHillshade: () => boolean;

	constructor(options: MyControlConstructorOptions) {
		this._toggleTerrain = options.toggleTerrain;
		this._toggleHillshade = options.toggleHillshade;
	}

	onAdd() {
		this._container = document.createElement('div');
		this._container.className = 'maplibregl-ctrl maplibregl-ctrl-group p-2 rounded flex w-[240px] gap-x-2';

		const toggleTerrain = document.createElement('button');
		toggleTerrain.textContent = 'Disable Terrain';
		toggleTerrain.type = 'button';
		toggleTerrain.style.backgroundColor = 'red';
		toggleTerrain.style.color = 'white';
		toggleTerrain.style.width = '50%';
		toggleTerrain.style.height = '100%';
		toggleTerrain.style.borderRadius = '0.25rem';
		toggleTerrain.addEventListener('click', () => {
			const newState = this._toggleTerrain();
			toggleTerrain.textContent = newState ? 'Disable Terrain' : 'Enable Terrain';
		});

		const toggleHillshade = document.createElement('button');
		toggleHillshade.textContent = 'Disable Hillshade';
		toggleHillshade.type = 'button';
		toggleHillshade.style.backgroundColor = 'blue';
		toggleHillshade.style.color = 'white';
		toggleHillshade.style.height = '100%';
		toggleHillshade.style.width = '50%';
		toggleHillshade.style.borderRadius = '0.25rem';
		toggleHillshade.addEventListener('click', () => {
			const newState = this._toggleHillshade();
			toggleHillshade.textContent = newState ? 'Disable Hillshade' : 'Enable Hillshade';
		});

		this._container.appendChild(toggleTerrain);
		this._container.appendChild(toggleHillshade);
		return this._container!;
	}

	onRemove() {
		if (this._container && this._container.parentNode) {
			this._container.parentNode.removeChild(this._container);
		}
	}
}

export { MyControl };


================================================
FILE: src/content/examples/custom-control/content.svelte.md
================================================
---
title: Custom Control
description: Easily create user-defined controls with a native look and feel.
---

<script lang="ts">
  import Demo from "./CustomControl.svelte";
  import demoRaw from "./CustomControl.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/custom-layer/CustomLayer.svelte
================================================
<script lang="ts">
	import { MapLibre, CustomLayer, GlobeControl, Projection } from 'svelte-maplibre-gl';
	import maplibregl from 'maplibre-gl';

	// define vertices of the triangle to be rendered in the custom style layer
	const helsinki = maplibregl.MercatorCoordinate.fromLngLat({ lng: 25.004, lat: 60.239 });
	const berlin = maplibregl.MercatorCoordinate.fromLngLat({ lng: 13.403, lat: 52.562 });
	const kyiv = maplibregl.MercatorCoordinate.fromLngLat({ lng: 30.498, lat: 50.541 });

	class CustomLayerImpl implements Omit<maplibregl.CustomLayerInterface, 'id' | 'type'> {
		private shaderMap: Map<string, WebGLProgram> = new Map();
		private aPos: number = 0;
		private buffer: WebGLBuffer | null = null;

		private getShader(
			gl: WebGL2RenderingContext | WebGLRenderingContext,
			shaderDescription: maplibregl.CustomRenderMethodInput['shaderData']
		) {
			// Pick a shader based on the current projection, defined by `variantName`.
			if (this.shaderMap.has(shaderDescription.variantName)) {
				return this.shaderMap.get(shaderDescription.variantName)!;
			}

			// Create vertex shader
			//
			// Note that we need to use a complex function to project from the source mercator
			// coordinates to the globe. Internal shaders in MapLibre need to do this too.
			// This is done using the `projectTile` function.
			// In MapLibre, this function accepts vertex coordinates local to the current tile,
			// in range 0..EXTENT (8192), but for custom layers MapLibre supplies uniforms such that
			// the function accepts mercator coordinates of the whole world in range 0..1.
			// This is controlled by the `u_projection_tile_mercator_coords` uniform.
			//
			// The `projectTile` function can also handle mercator to globe transitions and can
			// handle the mercator projection - different code is supplied based on what projection is used,
			// and for this reason we use different shaders based on what shader projection variant is currently used.
			// See `variantName` usage earlier in this file.
			//
			// The code for the projection function and uniforms is also supplied by MapLibre
			// and must be injected into custom layer shaders in order to draw on a globe.
			// We simply use string interpolation for that here.
			//
			// See MapLibre source code for more details, especially src/shaders/_projection_globe.vertex.glsl
			//
			const vertexShader = gl.createShader(gl.VERTEX_SHADER)!;
			const vertexSource = `#version 300 es
				// Inject MapLibre projection code
				${shaderDescription.vertexShaderPrelude}
				${shaderDescription.define}

				in vec2 a_pos;
				void main() {
						gl_Position = projectTile(a_pos);
				}`;
			gl.shaderSource(vertexShader, vertexSource);
			gl.compileShader(vertexShader);

			// Create fragment shader
			const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)!;
			const fragmentSource = `#version 300 es
				out highp vec4 fragColor;
				void main() {
						fragColor = vec4(1.0, 0.0, 1.0, 0.75);
				}`;
			gl.shaderSource(fragmentShader, fragmentSource);
			gl.compileShader(fragmentShader);

			// Link the two shaders into a WebGL program
			const program = gl.createProgram();
			gl.attachShader(program, vertexShader);
			gl.attachShader(program, fragmentShader);
			gl.linkProgram(program);

			this.aPos = gl.getAttribLocation(program, 'a_pos');
			this.shaderMap.set(shaderDescription.variantName, program);
			return program;
		}

		// Method called when the layer is added to the map
		onAdd(_map: maplibregl.Map, gl: WebGL2RenderingContext) {
			// create and initialize a WebGLBuffer to store vertex and color data
			this.buffer = gl.createBuffer();
			gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
			gl.bufferData(
				gl.ARRAY_BUFFER,
				new Float32Array([helsinki.x, helsinki.y, kyiv.x, kyiv.y, berlin.x, berlin.y]),
				gl.STATIC_DRAW
			);
			// Explanation of horizon clipping in MapLibre globe projection:
			//
			// When zooming in, the triangle will eventually start doing what at first glance
			// appears to be clipping the underlying map.
			//
			// Instead it is being clipped by the "horizon" plane, which the globe uses to
			// clip any geometry behind horizon (regular face culling isn't enough).
			// The horizon plane is not necessarily aligned with the near/far planes.
			// The clipping is done by assigning a custom value to `gl_Position.z` in the `projectTile`
			// MapLibre uses a constant z value per layer, so `gl_Position.z` can be anything,
			// since it later gets overwritten by `glDepthRange`.
			//
			// At high zooms, the triangle's three vertices can end up beyond the horizon plane,
			// resulting in the triangle getting clipped.
			//
			// This can be fixed by subdividing the triangle's geometry.
			// This is in general advisable to do, since without subdivision
			// geometry would not project to a curved shape under globe projection.
			// MapLibre also internally subdivides all geometry when globe projection is used.
		}

		// Method fired on each animation frame
		render(gl: WebGL2RenderingContext | WebGLRenderingContext, args: maplibregl.CustomRenderMethodInput) {
			const program = this.getShader(gl, args.shaderData);
			gl.useProgram(program);
			gl.uniformMatrix4fv(
				gl.getUniformLocation(program, 'u_projection_matrix'),
				false,
				args.defaultProjectionData.mainMatrix
			);
			gl.uniformMatrix4fv(
				gl.getUniformLocation(program, 'u_projection_fallback_matrix'),
				false,
				args.defaultProjectionData.fallbackMatrix
			);
			gl.uniform1f(
				gl.getUniformLocation(program, 'u_projection_transition'),
				args.defaultProjectionData.projectionTransition
			);
			gl.uniform4f(
				gl.getUniformLocation(program, 'u_projection_tile_mercator_coords'),
				...args.defaultProjectionData.tileMercatorCoords
			);
			gl.uniform4f(
				gl.getUniformLocation(program, 'u_projection_clipping_plane'),
				...args.defaultProjectionData.clippingPlane
			);

			gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
			gl.enableVertexAttribArray(this.aPos);
			gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, 0, 0);
			gl.enable(gl.BLEND);
			gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
			gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
		}
	}
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={3}
	center={[20, 58]}
>
	<CustomLayer implementation={new CustomLayerImpl()} />
	<Projection type="globe" />
	<GlobeControl />
</MapLibre>


================================================
FILE: src/content/examples/custom-layer/content.svelte.md
================================================
---
title: Custom Layer
description: Use a custom layer to draw simple WebGL content on a globe.
original: https://maplibre.org/maplibre-gl-js/docs/examples/globe-custom-simple/
---

<script lang="ts">
  import Demo from "./CustomLayer.svelte";
  import demoRaw from "./CustomLayer.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/custom-protocol/CustomProtocol.svelte
================================================
<script lang="ts">
	import {
		MapLibre,
		RasterTileSource,
		VectorTileSource,
		RasterLayer,
		LineLayer,
		FillLayer,
		Protocol
	} from 'svelte-maplibre-gl';
	import { PMTilesProtocol } from '@svelte-maplibre-gl/pmtiles';
	import maplibregl from 'maplibre-gl';

	const myProtocolLoadFn: maplibregl.AddProtocolAction = async (params) => {
		const zxy = params.url.replace('myprotocol://', '');
		const [z, x, y] = zxy.split('/').map((v) => parseInt(v, 10));

		const png = await new Promise((resolve) => {
			const canvas = document.createElement('canvas');
			canvas.width = 512;
			canvas.height = 512;
			const context = canvas.getContext('2d')!;

			// checkered pattern
			context.fillStyle = (z + x - y) % 2 === 0 ? 'rgba(255, 255, 255, 0.4)' : 'rgba(0, 0, 0, 0.4)';
			context.fillRect(0, 0, canvas.width, canvas.height);
			context.fillStyle = 'white';
			context.font = '32px sans-serif';
			context.fillText(`${z}/${x}/${y}`, 32, 64);

			// canvas -> Blob (png) -> ArrayBuffer
			canvas.toBlob(async (blob) => {
				resolve(await blob!.arrayBuffer());
			});
		});

		return { data: png };
	};
</script>

<!-- Adds a custom resource loading function to handle URLs that start with a custom URL scheme. -->
<PMTilesProtocol />
<Protocol scheme="myprotocol" loadFn={myProtocolLoadFn} />

<!-- Use custom protocols -->
<MapLibre class="h-[55vh] min-h-[200px]" zoom={6} center={{ lng: 140.0, lat: 37.5 }}>
	<VectorTileSource url="pmtiles://https://tile.openstreetmap.jp/static/planet.pmtiles">
		<LineLayer sourceLayer="transportation" paint={{ 'line-color': 'orange' }} />
		<FillLayer sourceLayer="water" paint={{ 'fill-color': 'dodgerblue' }} />
		<LineLayer sourceLayer="building" paint={{ 'line-color': 'lime' }} />
	</VectorTileSource>
	<RasterTileSource tiles={['myprotocol://{z}/{x}/{y}']} tileSize={256}>
		<RasterLayer />
	</RasterTileSource>
</MapLibre>


================================================
FILE: src/content/examples/custom-protocol/content.svelte.md
================================================
---
title: Custom Protocols
description: Add a custom resource loading function to handle a custom URL scheme.
---

<script lang="ts">
  import Demo from "./CustomProtocol.svelte";
  import demoRaw from "./CustomProtocol.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/deckgl-overlay/DeckGL.svelte
================================================
<script lang="ts">
	import { onMount } from 'svelte';
	import { MapLibre, FillExtrusionLayer } from 'svelte-maplibre-gl';
	import { DeckGLOverlay } from '@svelte-maplibre-gl/deckgl';
	import { ArcLayer } from '@deck.gl/layers';

	const NUM = 30;
	let data: { source: [number, number]; target: [number, number] }[] = $state([]);

	onMount(() => {
		let handle = requestAnimationFrame(function updateFrame(t) {
			data = Array.from({ length: NUM }, (_, i) => {
				const O = (2 * Math.PI) / NUM;
				const r = (1.3 + Math.sin(t / 510 + i * O)) * 0.002;
				return {
					source: [139.7672, 35.6812],
					target: [139.7672 + Math.cos(t / 730 + i * O) * r, 35.6812 + Math.sin(t / 730 + i * O) * r]
				};
			});
			handle = requestAnimationFrame(updateFrame);
		});
		return () => cancelAnimationFrame(handle);
	});
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={15}
	pitch={60}
	minZoom={4}
	bearing={-45}
	center={[139.7672, 35.6812]}
>
	<DeckGLOverlay
		interleaved
		layers={[
			new ArcLayer({
				id: 'deckgl-arc',
				data,
				getSourcePosition: (d) => d.source,
				getTargetPosition: (d) => d.target,
				getSourceColor: [0, 255, 100],
				getTargetColor: [0, 190, 255],
				getWidth: 5
			})
		]}
	/>
	<FillExtrusionLayer
		source="carto"
		sourceLayer="building"
		minzoom={14}
		paint={{
			'fill-extrusion-color': '#aaa',
			'fill-extrusion-height': ['interpolate', ['linear'], ['zoom'], 14, 0, 14.05, ['get', 'render_height']],
			'fill-extrusion-base': ['interpolate', ['linear'], ['zoom'], 14, 0, 14.05, ['get', 'render_min_height']],
			'fill-extrusion-opacity': 0.8
		}}
	/>
</MapLibre>


================================================
FILE: src/content/examples/deckgl-overlay/content.svelte.md
================================================
---
title: deck.gl Overlay
description: Interleaving deck.gl with MapLibre layers
original: https://deck.gl/gallery/maplibre-overlay
---

<script lang="ts">
  import Demo from "./DeckGL.svelte";
  import demoRaw from "./DeckGL.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/dynamic-image/DynamicImage.svelte
================================================
<script lang="ts">
	import { MapLibre, Image, GeoJSONSource, SymbolLayer } from 'svelte-maplibre-gl';

	const size = 64;
	const data = new Uint8Array(size * size * 4);

	let p = 0;
	for (let x = 0; x < size; x++) {
		for (let y = 0; y < size; y++) {
			data[p + 0] = (y / size) * 255;
			data[p + 1] = (x / size) * 255;
			data[p + 2] = 128;
			data[p + 3] = 255;
			p += 4;
		}
	}
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={4}
	center={{ lng: 137, lat: 36 }}
>
	<Image id="gradient" image={{ width: size, height: size, data }} />
	<GeoJSONSource
		data={{
			type: 'FeatureCollection',
			features: [
				{
					type: 'Feature',
					geometry: {
						type: 'Point',
						coordinates: [137, 36]
					},
					properties: {}
				}
			]
		}}
	>
		<SymbolLayer layout={{ 'icon-image': 'gradient' }} />
	</GeoJSONSource>
</MapLibre>


================================================
FILE: src/content/examples/dynamic-image/content.svelte.md
================================================
---
title: Dynamic Image
description: Add an icon to the map that was generated at runtime.
original: https://maplibre.org/maplibre-gl-js/docs/examples/add-image-generated/
---

<script lang="ts">
  import Demo from "./DynamicImage.svelte";
  import demoRaw from "./DynamicImage.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/fullscreen/Fullscreen.svelte
================================================
<script lang="ts">
	import { MapLibre, FullScreenControl } from 'svelte-maplibre-gl';
</script>

<MapLibre
	class="h-[55vh] min-h-[300px] border-8 border-slate-500"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
>
	<FullScreenControl position="top-left" />
</MapLibre>


================================================
FILE: src/content/examples/fullscreen/content.svelte.md
================================================
---
title: Fullscreen
description: View a fullscreen map
original: https://maplibre.org/maplibre-gl-js/docs/examples/fullscreen/
---

<script lang="ts">
  import Demo from "./Fullscreen.svelte";
  import demoRaw from "./Fullscreen.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/geolocate/Geolocate.svelte
================================================
<script lang="ts">
	import { MapLibre, GeolocateControl } from 'svelte-maplibre-gl';

	let logString = $state('Press the GeolocateControl button.\n');
	function log(s: string) {
		logString += '» ' + s + '\n';
	}
</script>

<div class="flex h-[55vh] min-h-[300px] overflow-hidden rounded-md">
	<pre class="m-0! h-full flex-1 rounded-none">{logString}</pre>
	<MapLibre class="h-full flex-1" style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json">
		<GeolocateControl
			position="top-left"
			positionOptions={{ enableHighAccuracy: true }}
			trackUserLocation={true}
			showAccuracyCircle={true}
			ontrackuserlocationstart={() => log('trackuserlocationstart')}
			ontrackuserlocationend={() => log('trackuserlocationend')}
			ongeolocate={(ev) => log(`geolocate ${JSON.stringify(ev.coords, null, 2)}`)}
		/>
	</MapLibre>
</div>


================================================
FILE: src/content/examples/geolocate/content.svelte.md
================================================
---
title: Locate the User
description: Locate the User
original: https://maplibre.org/maplibre-gl-js/docs/examples/locate-user/
---

<script lang="ts">
  import Demo from "./Geolocate.svelte";
  import demoRaw from "./Geolocate.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/global-state/Plain.svelte
================================================
<script lang="ts">
	import { Label } from '$lib/components/ui/label';
	import { MapLibre, GeoJSONSource, CircleLayer, SymbolLayer } from 'svelte-maplibre-gl';

	let type = $state('');
</script>

<MapLibre
	class="h-[55vh] min-h-75"
	style="https://demotiles.maplibre.org/style.json"
	zoom={9}
	center={[9.0679, 45.9]}
	globalState={{
		type: type
	}}
>
	<GeoJSONSource data="https://maplibre.org/maplibre-gl-js/docs/assets/funicolares-and-funivias-como.json">
		<SymbolLayer
			layout={{
				'text-field': '{name}',
				'text-font': ['Open Sans Semibold'],
				'text-offset': [0, 1],
				'text-anchor': 'top'
			}}
			paint={{
				'text-color': '#000000',
				'text-halo-color': '#ffffff',
				'text-halo-width': 2
			}}
			filter={[
				'case',
				['==', ['to-string', ['global-state', 'type']], ''],
				true,
				['==', ['get', 'type'], ['global-state', 'type']]
			]}
		/>
		<CircleLayer
			paint={{
				'circle-radius': 5,
				'circle-color': '#000000'
			}}
			filter={[
				'case',
				['==', ['to-string', ['global-state', 'type']], ''],
				true,
				['==', ['get', 'type'], ['global-state', 'type']]
			]}
		/>
	</GeoJSONSource>

	<!-- Controls -->
	<div
		class="absolute top-3 left-3 z-10 flex min-w-50 flex-col items-stretch gap-1 rounded bg-background/60 p-3 text-sm backdrop-blur-sm"
	>
		<div class="flex items-center justify-between space-x-2">
			<Label for="global-state-type" class="leading-none">global-state: type =</Label>
			<select bind:value={type} id="global-state-type" class="text-center">
				<option value="">"" (All)</option>
				<option value="lift">"lift"</option>
				<option value="railway">"railway"</option>
			</select>
		</div>
	</div>
</MapLibre>


================================================
FILE: src/content/examples/global-state/content.svelte.md
================================================
---
title: Global State
description: Filter a layer symbols based on user input using setGlobalStateProperty().
original: https://maplibre.org/maplibre-gl-js/docs/examples/filter-layer-symbols-using-global-state/
---

<script lang="ts">
  import Demo from "./Plain.svelte";
  import demoRaw from "./Plain.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/globe-atmosphere/Globe.svelte
================================================
<script lang="ts">
	import { MapLibre, Projection, Sky, Light } from 'svelte-maplibre-gl';

	let thetaDeg = $state(135);
	let phiDeg = $state(0);
	let p = $derived(
		(Math.acos(Math.cos((thetaDeg / 180 + 1) * Math.PI) * Math.cos((phiDeg / 180) * Math.PI)) / Math.PI) * 180
	);
	let a = $derived(
		90 +
			(Math.atan2(
				Math.sin((phiDeg / 180) * Math.PI),
				Math.sin((thetaDeg / 180 + 1) * Math.PI) * Math.cos((phiDeg / 180) * Math.PI)
			) /
				Math.PI) *
				180
	);
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
	zoom={1.5}
	center={{ lng: 155, lat: 45 }}
>
	<Projection type="globe" />
	<Light anchor="map" position={[100, a, p]} />
	<Sky atmosphere-blend={['interpolate', ['linear'], ['zoom'], 0, 1, 5, 1, 7, 0]} />

	<!-- Control -->
	<div
		class="absolute top-3 left-3 z-10 flex min-w-[200px] flex-col items-stretch gap-1 rounded bg-background/60 p-3 text-sm backdrop-blur-sm"
	>
		<div class="mb-4 flex flex-col items-center space-y-2 px-2">
			<label for="theta" class="leading-none">Theta ({thetaDeg})</label>
			<input type="range" id="theta" bind:value={thetaDeg} min={-180} max={180} />
		</div>
		<div class="mb-4 flex flex-col items-center space-y-2 px-2">
			<label for="phi" class="leading-none">Phi ({phiDeg.toFixed(1)})</label>
			<input type="range" id="phi" bind:value={phiDeg} min={-90} max={90} step={0.1} />
		</div>
	</div>
</MapLibre>


================================================
FILE: src/content/examples/globe-atmosphere/content.svelte.md
================================================
---
title: Globe with an atmosphere
description: Display a globe with an atmosphere.
original: https://maplibre.org/maplibre-gl-js/docs/examples/globe-atmosphere/
---

<script lang="ts">
  import Demo from "./Globe.svelte";
  import demoRaw from "./Globe.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/hover-styles/HoverStyles.svelte
================================================
<script lang="ts">
	import { FillLayer, LineLayer, MapLibre, GeoJSONSource, FeatureState, Popup } from 'svelte-maplibre-gl';
	import maplibregl from 'maplibre-gl';
	let hoveredFeature: maplibregl.MapGeoJSONFeature | undefined = $state.raw();
	let lnglat = $state.raw(new maplibregl.LngLat(0, 0));
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
	zoom={2}
	center={{ lng: -100.486052, lat: 37.830348 }}
>
	<GeoJSONSource data="https://maplibre.org/maplibre-gl-js/docs/assets/us_states.geojson">
		<FillLayer
			paint={{
				'fill-color': '#00ff55',
				// Change the opacity for the hovered feature
				'fill-opacity': ['case', ['boolean', ['feature-state', 'hover'], false], 0.4, 0.1]
			}}
			onmousemove={(ev) => {
				// Listen to mousemove events to track the hovered feature
				hoveredFeature = ev.features?.[0];
				lnglat = ev.lngLat; // cursor location
			}}
			onmouseleave={() => (hoveredFeature = undefined)}
		/>
		<LineLayer
			paint={{
				'line-color': '#00ff55',
				// Change the opacity for the hovered feature
				'line-opacity': ['case', ['boolean', ['feature-state', 'hover'], false], 1, 0.3],
				'line-width': 1
			}}
		/>
		{#if hoveredFeature}
			<!-- Set the hover state on the source for the hovered feature -->
			<FeatureState id={hoveredFeature.id} state={{ hover: true }} />
			<Popup {lnglat} closeButton={false}>{hoveredFeature.properties.STATE_NAME}</Popup>
		{/if}
	</GeoJSONSource>
</MapLibre>


================================================
FILE: src/content/examples/hover-styles/content.svelte.md
================================================
---
title: Hover Styles
description: Use events and feature states to create a per feature hover effect.
original: https://maplibre.org/maplibre-gl-js/docs/examples/hover-styles/
---

<script lang="ts">
  import Demo from "./HoverStyles.svelte";
  import demoRaw from "./HoverStyles.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/image-loader/Images.svelte
================================================
<script lang="ts">
	import { MapLibre, ImageLoader, GeoJSONSource, SymbolLayer } from 'svelte-maplibre-gl';
	import type { FeatureCollection } from 'geojson';

	let data: FeatureCollection = {
		type: 'FeatureCollection',
		features: [
			{
				type: 'Feature',
				geometry: { type: 'Point', coordinates: [-48.47279, -1.44585] },
				properties: { imageName: 'osgeo', year: 2024 }
			},
			{
				type: 'Feature',
				geometry: { type: 'Point', coordinates: [0, 0] },
				properties: { imageName: 'cat', scale: 0.2 }
			},
			{
				type: 'Feature',
				geometry: { type: 'Point', coordinates: [40, -30] },
				properties: { imageName: 'popup-debug', name: 'Line 1\nLine 2\nLine 3' }
			},
			{
				type: 'Feature',
				geometry: { type: 'Point', coordinates: [-40, -30] },
				properties: { imageName: 'popup-debug', name: 'One longer line' }
			}
		]
	};
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={1.5}
	center={{ lng: -10.0, lat: -20 }}
>
	<GeoJSONSource {data}>
		<ImageLoader
			images={{
				osgeo: 'https://maplibre.org/maplibre-gl-js/docs/assets/osgeo-logo.png',
				cat: 'https://upload.wikimedia.org/wikipedia/commons/7/7c/201408_cat.png',
				'popup-debug': [
					'https://maplibre.org/maplibre-gl-js/docs/assets/popup_debug.png',
					{
						// stretchable image
						stretchX: [
							[25, 55],
							[85, 115]
						],
						stretchY: [[25, 100]],
						content: [25, 25, 115, 100],
						pixelRatio: 2
					}
				]
			}}
		>
			<!-- Children components will be added after all images have been loaded -->
			<SymbolLayer
				layout={{
					'text-field': ['get', 'name'],
					'icon-image': ['get', 'imageName'],
					'icon-size': ['number', ['get', 'scale'], 1],
					'icon-text-fit': 'both',
					'icon-overlap': 'always',
					'text-overlap': 'always'
				}}
			/>
		</ImageLoader>
	</GeoJSONSource>
</MapLibre>


================================================
FILE: src/content/examples/image-loader/content.svelte.md
================================================
---
title: Load Images from URLs
description: Utility for loading images from URLs
original: https://maplibre.org/maplibre-gl-js/docs/examples/add-image-stretchable/
---

<script lang="ts">
  import Demo from "./Images.svelte";
  import demoRaw from "./Images.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/limit-interaction/LimitInteraction.svelte
================================================
<script lang="ts">
	import { MapLibre } from 'svelte-maplibre-gl';

	import { Checkbox } from '$lib/components/ui/checkbox/index.js';
	import { Label } from '$lib/components/ui/label/index.js';
	import { Slider } from '$lib/components/ui/slider/index.js';

	let zoomRange = $state([5, 11]);
	let pitchRange = $state([0, 60]);
	let boxZoom = $state(true);
	let doubleClickZoom = $state(true);
	let dragRotate = $state(true);
	let dragPan = $state(true);
	let keyboard = $state(true);
	let scrollZoom = $state(true);
	let touchZoomRotate = $state(true);
	let touchPitch = $state(true);
</script>

<MapLibre
	class="relative h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={5}
	center={{ lng: 137, lat: 36 }}
	{doubleClickZoom}
	{boxZoom}
	{keyboard}
	{dragRotate}
	{dragPan}
	{scrollZoom}
	{touchZoomRotate}
	{touchPitch}
	minZoom={zoomRange[0]}
	maxZoom={zoomRange[1]}
	minPitch={pitchRange[0]}
	maxPitch={pitchRange[1]}
>
	<div class="absolute top-3 right-3 z-10 flex flex-col gap-1 rounded bg-background/60 p-3 text-sm backdrop-blur-sm">
		<div class="mb-3 flex flex-col items-center space-y-2.5 px-2">
			<Label for="zoom" class="leading-none">Zoom Range ({zoomRange})</Label>
			<Slider type="multiple" id="zoom" bind:value={zoomRange} min={0} max={22} />
		</div>
		<div class="mb-3 flex flex-col items-center space-y-2.5 px-2">
			<Label for="pitch" class="leading-none">Pitch Range ({pitchRange})</Label>
			<Slider type="multiple" id="pitch" bind:value={pitchRange} min={0} max={90} />
		</div>
		<div class="flex items-center space-x-2">
			<Checkbox id="scrollZoom" bind:checked={scrollZoom} />
			<Label for="scrollZoom" class="leading-none">Scroll Zoom</Label>
		</div>
		<div class="flex items-center space-x-2">
			<Checkbox id="boxZoom" bind:checked={boxZoom} />
			<Label for="boxZoom" class="leading-none">Box Zoom</Label>
		</div>
		<div class="flex items-center space-x-2">
			<Checkbox id="dragPan" bind:checked={dragPan} />
			<Label for="dragPan" class="leading-none">Drag Pan</Label>
		</div>
		<div class="flex items-center space-x-2">
			<Checkbox id="dragRotate" bind:checked={dragRotate} />
			<Label for="dragRotate" class="leading-none">Drag Rotate</Label>
		</div>
		<div class="flex items-center space-x-2">
			<Checkbox id="doubleClickZoom" bind:checked={doubleClickZoom} />
			<Label for="doubleClickZoom" class="leading-none">Double Click Zoom</Label>
		</div>
		<div class="flex items-center space-x-2">
			<Checkbox id="keyboard" bind:checked={keyboard} />
			<Label for="keyboard" class="leading-none">Keyboard</Label>
		</div>
		<div class="flex items-center space-x-2">
			<Checkbox id="touchZoomRotate" bind:checked={touchZoomRotate} />
			<Label for="touchZoomRotate" class="leading-none">Touch Zoom Rotate</Label>
		</div>
		<div class="flex items-center space-x-2">
			<Checkbox id="touchPitch" bind:checked={touchPitch} />
			<Label for="touchPitch" class="leading-none">Touch Pitch</Label>
		</div>
	</div>
</MapLibre>


================================================
FILE: src/content/examples/limit-interaction/content.svelte.md
================================================
---
title: Limit Map Interactions
description: Set the zoom/pitch range and toggle UI handlers on the map.
original: https://maplibre.org/maplibre-gl-js/docs/examples/toggle-interaction-handlers/
---

<script lang="ts">
  import Demo from "./LimitInteraction.svelte";
  import demoRaw from "./LimitInteraction.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/marker-popup/MarkerAndPopup.svelte
================================================
<script lang="ts">
	import maplibregl from 'maplibre-gl';
	import { MapLibre, Marker, Popup } from 'svelte-maplibre-gl';

	let lnglat = $state({ lng: 139.767052, lat: 35.681167 });
	let lngLatText = $derived(`(${lnglat.lat.toFixed(3)}, ${lnglat.lng.toFixed(3)})`);
	let popupOpen = $state(true);
	let offset = $state(24);

	let offsets: maplibregl.Offset = $derived({
		top: [0, offset],
		bottom: [0, -offset],
		left: [offset + 12, 0],
		right: [-offset - 12, 0],
		center: [0, 0],
		'top-left': [offset, offset],
		'top-right': [-offset, offset],
		'bottom-left': [offset, -offset],
		'bottom-right': [-offset, -offset]
	});
</script>

<div class="flex items-center gap-x-4 text-sm">
	<label><input type="checkbox" bind:checked={popupOpen} /> Popup Open</label>
	<label>Offset ({offset}): <input type="range" min="0" max="30" bind:value={offset} /></label>
	<pre class="my-1 grow">marker: {lngLatText}</pre>
</div>

<MapLibre
	style="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
	class="h-[55vh] min-h-[300px]"
	zoom={10}
	center={[139.7, 35.7]}
	maxPitch={85}
	attributionControl={false}
>
	<Marker bind:lnglat draggable>
		{#snippet content()}
			<div class="text-center leading-none">
				<div class="text-3xl">🐶</div>
				<div class="font-bold text-white drop-shadow-xs">{lngLatText}</div>
			</div>
		{/snippet}
		<Popup class="text-black" bind:open={popupOpen} offset={offsets}>
			<span class="text-lg">{lngLatText}</span>
		</Popup>
	</Marker>
</MapLibre>


================================================
FILE: src/content/examples/marker-popup/content.svelte.md
================================================
---
title: Marker and Popup
description: Control marker and popup states using Svelte’s reactivity.
---

<script lang="ts">
  import Demo from "./MarkerAndPopup.svelte";
  import demoRaw from "./MarkerAndPopup.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/plain/Plain.svelte
================================================
<script lang="ts">
	import { MapLibre, NavigationControl, ScaleControl, GlobeControl } from 'svelte-maplibre-gl';
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={3.5}
	center={{ lng: 137, lat: 36 }}
>
	<NavigationControl />
	<ScaleControl />
	<GlobeControl />
</MapLibre>


================================================
FILE: src/content/examples/plain/content.svelte.md
================================================
---
title: Plain Map
description: A minimal example showing only the base map.
---

<script lang="ts">
  import Demo from "./Plain.svelte";
  import demoRaw from "./Plain.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/pmtiles/PMTiles.svelte
================================================
<script lang="ts">
	import { MapLibre } from 'svelte-maplibre-gl';
	import { PMTilesProtocol } from '@svelte-maplibre-gl/pmtiles';
	import type { LayerSpecification } from 'maplibre-gl';

	// Extract the layers spec from the OSM style
	let layers: LayerSpecification[] = $state.raw([]);
	$effect(() => {
		fetch('https://tile.openstreetmap.jp/styles/openmaptiles/style.json')
			.then((response) => response.json())
			.then((data) => {
				layers = data['layers'].filter(
					(layer: LayerSpecification) => !('source' in layer) || layer.source === 'openmaptiles'
				);
			});
	});
</script>

<!-- Add pmtiles:// Protocol globally -->
<PMTilesProtocol />

<!-- Use the pmtiles:// protocol -->
<MapLibre
	class="h-[55vh] min-h-[200px]"
	zoom={10}
	center={[12.484151635086198, 41.8960910478323]}
	style={{
		version: 8,
		glyphs: 'https://tile.openstreetmap.jp/fonts/{fontstack}/{range}.pbf',
		sprite: 'https://tile.openstreetmap.jp/styles/openmaptiles/sprite',
		sources: {
			openmaptiles: {
				type: 'vector',
				url: 'pmtiles://https://tile.openstreetmap.jp/static/planet.pmtiles',
				attribution: 'OSM Japan © OpenMapTiles © OpenStreetMap contributors'
			}
		},
		layers
	}}
></MapLibre>


================================================
FILE: src/content/examples/pmtiles/content.svelte.md
================================================
---
title: PMTiles Protocol
description: Uses the PMTiles plugin and the custom protocol to present a map.
original: https://maplibre.org/maplibre-gl-js/docs/examples/pmtiles/
---

<script lang="ts">
  import Demo from "./PMTiles.svelte";
  import demoRaw from "./PMTiles.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/query-features/Query.svelte
================================================
<script lang="ts">
	import {
		MapLibre,
		GeoJSONSource,
		CircleLayer,
		Marker,
		GlobeControl,
		QuerySourceFeatures,
		QueryRenderedFeatures
	} from 'svelte-maplibre-gl';
	import maplibregl from 'maplibre-gl';
	import * as Tabs from '$lib/components/ui/tabs/index.js';

	let features: maplibregl.MapGeoJSONFeature[] = $state.raw([]);
	let mode: 'source' | 'rendered' = $state('source');
</script>

<div class="flex h-[55vh] min-h-[300px] gap-x-3">
	<MapLibre
		class="h-[55vh] min-h-[300px] grow"
		style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
		zoom={3}
		center={{ lng: 120, lat: 20 }}
	>
		<GlobeControl />
		<GeoJSONSource
			id="earthquakes"
			data="https://maplibre.org/maplibre-gl-js/docs/assets/significant-earthquakes-2015.geojson"
			promoteId="ids"
		>
			{#if mode == 'source'}
				<!-- map.querySourceFeatures() -->
				<QuerySourceFeatures bind:features>
					{#snippet children(feature: maplibregl.MapGeoJSONFeature)}
						{#if feature.geometry.type === 'Point'}
							<Marker lnglat={feature.geometry.coordinates as [number, number]} />
						{/if}
					{/snippet}
				</QuerySourceFeatures>
			{/if}
			<CircleLayer paint={{ 'circle-color': 'red', 'circle-radius': 4 }}>
				{#if mode == 'rendered'}
					<!-- map.queryRenderedFeatures() -->
					<QueryRenderedFeatures bind:features>
						{#snippet children(feature: maplibregl.MapGeoJSONFeature)}
							{#if feature.geometry.type === 'Point'}
								<Marker lnglat={feature.geometry.coordinates as [number, number]} />
							{/if}
						{/snippet}
					</QueryRenderedFeatures>
				{/if}
			</CircleLayer>
		</GeoJSONSource>
	</MapLibre>

	<!-- List of earthquakes -->
	<div class="relative basis-[10em]">
		<Tabs.Root bind:value={mode} class="flex h-full flex-col">
			<Tabs.List class="grid w-full grid-cols-2">
				<Tabs.Trigger value="source">Source</Tabs.Trigger>
				<Tabs.Trigger value="rendered">Rendered</Tabs.Trigger>
			</Tabs.List>
			<Tabs.Content value="source" class="min-h-0 shrink overflow-scroll">
				<ul class="m-0 ml-2 overflow-scroll px-3 text-xs">
					{#each features as feature (feature.id)}
						<li>{feature.properties.title}</li>
					{/each}
				</ul>
			</Tabs.Content>
			<Tabs.Content value="rendered" class="min-h-0 shrink overflow-scroll">
				<ul class="m-0 ml-4 overflow-scroll px-3 text-xs">
					{#each features as feature (feature.id)}
						<li>{feature.properties.title}</li>
					{/each}
				</ul>
			</Tabs.Content>
		</Tabs.Root>
	</div>
</div>


================================================
FILE: src/content/examples/query-features/content.svelte.md
================================================
---
title: Query Features
description: Query source and rendered features to place markers and display a list.
---

<script lang="ts">
  import Demo from "./Query.svelte";
  import demoRaw from "./Query.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/side-by-side/SideBySide.svelte
================================================
<script lang="ts">
	import { MapLibre, Projection } from 'svelte-maplibre-gl';

	import { Label } from '$lib/components/ui/label/index.js';
	import { Switch } from '$lib/components/ui/switch/index.js';
	import * as RadioGroup from '$lib/components/ui/radio-group/index.js';

	let center = $state({ lng: 137, lat: 36.5 });
	let zoom = $state(4);
	let bearing = $state(0);
	let pitch = $state(0);
	let roll: number | undefined = $state(undefined);
	let elevation: number | undefined = $state(undefined);

	const MODES = ['Side by Side', 'Split', 'Scope'] as const;
	type Modes = (typeof MODES)[number];

	let splitMode: Modes = $state('Side by Side');
	let width = $state(0);
	let globe = $state(false);
	let point = $state({ x: 100, y: 100 });

	export const ro = (node: Element) => {
		const ro = new ResizeObserver(([entry]) => (width = entry.contentRect.width));
		ro.observe(node);
		return { destroy: () => ro.disconnect() };
	};
</script>

<div class="mb-3 flex items-center justify-between">
	<RadioGroup.Root bind:value={splitMode} class="flex flex-row gap-x-3">
		{#each MODES as mode (mode)}
			<div class="flex items-center space-x-1">
				<RadioGroup.Item value={mode} id={mode} />
				<Label for={mode}>{mode}</Label>
			</div>
		{/each}
	</RadioGroup.Root>
	<div class="flex items-center space-x-2">
		<Switch id="globe" bind:checked={globe} />
		<Label for="globe">Globe</Label>
	</div>
</div>

<div
	class="relative flex h-[55vh] min-h-[300px] flex-row-reverse"
	use:ro
	role="application"
	onmousemove={(ev) => (point = { x: ev.offsetX, y: ev.offsetY })}
>
	<MapLibre
		class="flex-1"
		style="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
		bind:center
		bind:zoom
		bind:bearing
		bind:pitch
		bind:roll
		bind:elevation
		padding={splitMode === 'Split' ? { left: 0, right: width / 2, top: 0, bottom: 0 } : undefined}
	>
		<Projection type={globe ? 'globe' : undefined} />
	</MapLibre>
	<MapLibre
		class={splitMode === 'Scope' ? 'absolute! inset-0' : 'flex-1'}
		style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
		inlineStyle={splitMode === 'Scope' ? `clip-path: circle(15% at ${point.x}px ${point.y}px);` : undefined}
		bind:center
		bind:zoom
		bind:bearing
		bind:pitch
		bind:roll
		bind:elevation
		attributionControl={false}
		padding={splitMode === 'Split' ? { left: width / 2, right: 0, top: 0, bottom: 0 } : undefined}
	>
		<Projection type={globe ? 'globe' : undefined} />
	</MapLibre>
</div>


================================================
FILE: src/content/examples/side-by-side/content.svelte.md
================================================
---
title: Side by Side
description: Synchronize two maps.
original: https://visgl.github.io/react-maplibre/examples/side-by-side
---

<script lang="ts">
  import Demo from "./SideBySide.svelte";
  import demoRaw from "./SideBySide.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
    let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/terradraw/TerraDraw.svelte
================================================
<script lang="ts">
	import { MapLibre, GlobeControl } from 'svelte-maplibre-gl';
	import { TerraDraw } from '@svelte-maplibre-gl/terradraw';
	import type { TerraDraw as Draw } from 'terra-draw';
	import {
		TerraDrawCircleMode,
		TerraDrawRectangleMode,
		TerraDrawFreehandMode,
		TerraDrawAngledRectangleMode,
		TerraDrawLineStringMode,
		TerraDrawPolygonMode,
		TerraDrawPointMode,
		TerraDrawSectorMode,
		TerraDrawSelectMode,
		TerraDrawSensorMode
	} from 'terra-draw';

	const defaultSelectFlags = {
		feature: {
			draggable: true,
			coordinates: {
				deletable: true,
				midpoints: true,
				draggable: true
			}
		}
	};
	const modes = [
		new TerraDrawSelectMode({
			flags: {
				point: defaultSelectFlags,
				linestring: defaultSelectFlags,
				polygon: defaultSelectFlags,
				freehand: defaultSelectFlags,
				circle: defaultSelectFlags,
				rectangle: defaultSelectFlags,
				sector: defaultSelectFlags,
				sensor: defaultSelectFlags,
				'angled-rectangle': defaultSelectFlags
			}
		}),
		new TerraDrawPointMode(),
		new TerraDrawLineStringMode(),
		new TerraDrawPolygonMode(),
		new TerraDrawCircleMode(),
		new TerraDrawSectorMode(),
		new TerraDrawSensorMode(),
		new TerraDrawRectangleMode(),
		new TerraDrawFreehandMode(),
		new TerraDrawAngledRectangleMode()
	];
	const modeNames = modes.map((mode) => mode.mode);
	let mode = $state('select');
	let selected: string | number | null = $state(null);
	let draw: Draw | undefined = $state.raw();
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={2}
	center={{ lng: 60, lat: 20 }}
>
	<!-- Terra Draw -->
	<TerraDraw
		{mode}
		{modes}
		bind:draw
		onselect={(featureId) => (selected = featureId)}
		ondeselect={() => (selected = null)}
		onfinish={() => (mode = 'select')}
	/>

	<!-- Draw controls -->
	<div
		class="absolute top-3 left-3 z-10 flex flex-col items-stretch gap-1 rounded bg-background/60 p-3 text-sm backdrop-blur-sm"
	>
		{#each modeNames as modeName (modeName)}
			<label><input type="radio" bind:group={mode} value={modeName} class="mr-1" /> {modeName}</label>
		{/each}
		{#if selected}
			<button
				class="mt-1 rounded border px-1"
				onclick={() => {
					if (!selected) return;
					draw?.removeFeatures([selected]);
					draw?.deselectFeature(selected);
				}}>Remove</button
			>
		{/if}
	</div>
	<GlobeControl />
</MapLibre>


================================================
FILE: src/content/examples/terradraw/content.svelte.md
================================================
---
title: Terra Draw
description: Use Terra Draw to draw a geometry in various forms such as point, line or polygon on your map.
---

<script lang="ts">
  import Demo from "./TerraDraw.svelte";
  import demoRaw from "./TerraDraw.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/terrain/Terrain.svelte
================================================
<script lang="ts">
	import {
		HillshadeLayer,
		MapLibre,
		RasterDEMTileSource,
		Sky,
		Terrain,
		TerrainControl,
		GlobeControl,
		Light
	} from 'svelte-maplibre-gl';
	import { Checkbox } from '$lib/components/ui/checkbox/index.js';
	import { Label } from '$lib/components/ui/label/index.js';
	import { Slider } from '$lib/components/ui/slider/index.js';
	import * as Tabs from '$lib/components/ui/tabs/index.js';

	// 'hillshade-method' option is available since Maplibre GL JS v5.5.0
	// Note that 'multidirectional' method doesn't work as intended in this
	// example because it requires multiple directions and colors. For the
	// details, please refer to the spec: https://maplibre.org/maplibre-style-spec/layers/#hillshade-method
	const HILLSHADE_METHODS = ['standard', 'basic', 'combined', 'igor', 'multidirectional'] as const;
	type HillshadeMethod = (typeof HILLSHADE_METHODS)[number];

	let mode: 'terrain' | 'sky' = $state('terrain');
	// Terrain
	let exaggeration = $state(1.0);
	let hillshade = $state(0.7);
	let hillshadeMethod: HillshadeMethod = $state(HILLSHADE_METHODS[0]);
	let shadowColor = $state('#004050');
	let accentColor = $state('#aaff00');
	let highlightColor = $state('#ffffff');
	let direction = $state(0.0);
	let altitude = $state(45.0);
	// Sky
	let skyEnabled = $state(true);
	let skyColor = $state('#001560');
	let horizonColor = $state('#0090c0');
	let fogColor = $state('#ffffff');
	let skyHorizonBlend = $state(0.5);
	let horizonFogBlend = $state(0.7);
	let fogGroundBlend = $state(0.5);
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={12}
	pitch={72}
	maxPitch={85}
	center={{ lng: 11.39085, lat: 47.3 }}
>
	<GlobeControl />
	<Light anchor="map" />
	{#if skyEnabled}
		<Sky
			sky-color={skyColor}
			horizon-color={horizonColor}
			fog-color={fogColor}
			sky-horizon-blend={skyHorizonBlend}
			horizon-fog-blend={horizonFogBlend}
			fog-ground-blend={fogGroundBlend}
			atmosphere-blend={0.5}
		/>
	{/if}
	<!-- Terrain -->
	<RasterDEMTileSource id="terrain" url="https://tiles.mapterhorn.com/tilejson.json">
		<TerrainControl position="top-right" />
		<Terrain {exaggeration} />
	</RasterDEMTileSource>
	<!-- Hillshade -->
	<RasterDEMTileSource url="https://tiles.mapterhorn.com/tilejson.json">
		<HillshadeLayer
			paint={{
				'hillshade-method': hillshadeMethod,
				'hillshade-exaggeration': hillshade,
				'hillshade-shadow-color': shadowColor,
				'hillshade-accent-color': accentColor,
				'hillshade-highlight-color': highlightColor,
				'hillshade-illumination-anchor': 'map',
				'hillshade-illumination-altitude': altitude,
				'hillshade-illumination-direction': direction
			}}
		/>
	</RasterDEMTileSource>

	<div
		class="absolute top-3 left-3 z-10 flex min-w-50 flex-col items-stretch gap-1 rounded bg-background/60 p-3 text-sm backdrop-blur-sm"
	>
		<Tabs.Root bind:value={mode} class="flex h-full flex-col">
			<Tabs.List class="grid w-full grid-cols-2">
				<Tabs.Trigger value="terrain">Terrain</Tabs.Trigger>
				<Tabs.Trigger value="sky">Sky</Tabs.Trigger>
			</Tabs.List>
			<Tabs.Content value="terrain" class="min-h-0 shrink overflow-scroll pt-1">
				<div class="mb-4 flex flex-col items-center space-y-2 px-2">
					<Label for="pitch" class="leading-none">Exaggeration ({exaggeration.toFixed(2)})</Label>
					<Slider type="single" id="pitch" bind:value={exaggeration} min={0} max={2} step={0.01} />
				</div>
				<div class="mb-3 flex flex-col items-center space-y-2 px-2">
					<Label for="hillshade" class="leading-none">Hillshade ({hillshade.toFixed(2)})</Label>
					<Slider type="single" id="hillshade" bind:value={hillshade} min={0} max={1} step={0.01} />
				</div>
				<div class="mb-2 flex items-center justify-between space-x-2">
					<Label for="shadow-method" class="leading-none">Method</Label>
					<select bind:value={hillshadeMethod} id="hillshade-method" class="text-center">
						{#each HILLSHADE_METHODS as method (method)}
							<option value={method}>{method}</option>
						{/each}
					</select>
				</div>
				<div class="mb-1 flex items-center justify-between space-x-2">
					<Label for="shadow-sm" class="leading-none">Shadow</Label>
					<input type="color" id="shadow-sm" bind:value={shadowColor} />
				</div>
				{#if hillshadeMethod === 'standard'}
					<div class="mb-1 flex items-center justify-between space-x-2">
						<Label for="accent" class="leading-none">Accent</Label>
						<input type="color" id="accent" bind:value={accentColor} />
					</div>
				{/if}
				<div class="mb-2 flex items-center justify-between space-x-2">
					<Label for="highlight" class="leading-none">Highlight</Label>
					<input type="color" id="highlight" bind:value={highlightColor} />
				</div>
				<div class="mb-3 flex flex-col items-center space-y-2 px-2">
					<Label for="direction" class="leading-none">Direction ({direction})</Label>
					<Slider type="single" id="direction" bind:value={direction} min={0} max={360} />
				</div>
				{#if !['standard', 'igor'].includes(hillshadeMethod)}
					<div class="mb-3 flex flex-col items-center space-y-2 px-2">
						<Label for="altitude" class="leading-none">Altitude ({altitude.toFixed(2)})</Label>
						<Slider type="single" id="altitude" bind:value={altitude} min={0} max={90} step={0.01} />
					</div>
				{/if}
			</Tabs.Content>
			<Tabs.Content value="sky" class="min-h-0 shrink overflow-scroll pt-1">
				<div class="mb-2 flex items-center space-x-2 self-center justify-self-center">
					<Checkbox id="skyEnabled" bind:checked={skyEnabled} />
					<Label for="skyEnabled" class="leading-none">Enable Sky</Label>
				</div>
				<div class="mb-1 flex items-center justify-between space-x-2">
					<Label for="skyColor" class="leading-none">Sky color</Label>
					<input type="color" id="skyColor" bind:value={skyColor} />
				</div>
				<div class="mb-3 flex flex-col items-center space-y-2 px-2">
					<Label for="skyHorizonBlend" class="leading-none">sky-horizon-blend ({skyHorizonBlend})</Label>
					<Slider type="single" id="skyHorizonBlend" bind:value={skyHorizonBlend} min={0} max={1} step={0.01} />
				</div>
				<div class="mb-1 flex items-center justify-between space-x-2">
					<Label for="horizonColor" class="leading-none">Horizon color</Label>
					<input type="color" id="horizonColor" bind:value={horizonColor} />
				</div>
				<div class="mb-3 flex flex-col items-center space-y-2 px-2">
					<Label for="horizonFogBlend" class="leading-none">horizon-fog-blend ({horizonFogBlend})</Label>
					<Slider type="single" id="horizonFogBlend" bind:value={horizonFogBlend} min={0} max={1} step={0.01} />
				</div>
				<div class="mb-1 flex items-center justify-between space-x-2">
					<Label for="fogColor" class="leading-none">Fog color</Label>
					<input type="color" id="fogColor" bind:value={fogColor} />
				</div>
				<div class="mb-3 flex flex-col items-center space-y-2 px-2">
					<Label for="fogGroundBlend" class="leading-none">fog-ground-blend ({fogGroundBlend})</Label>
					<Slider type="single" id="fogGroundBlend" bind:value={fogGroundBlend} min={0} max={1} step={0.01} />
				</div>
			</Tabs.Content>
		</Tabs.Root>
	</div>
</MapLibre>


================================================
FILE: src/content/examples/terrain/content.svelte.md
================================================
---
title: 3D Terrain and Sky
description: Show elevation in actual 3D with the sky.
original: https://maplibre.org/maplibre-gl-js/docs/examples/sky-with-fog-and-terrain/
---

<script lang="ts">
  import Demo from "./Terrain.svelte";
  import demoRaw from "./Terrain.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/threejs-model/CustomLayer.svelte
================================================
<script lang="ts">
	import { MapLibre, CustomLayer, GlobeControl, Projection } from 'svelte-maplibre-gl';
	import maplibregl from 'maplibre-gl';
	import * as THREE from 'three';
	import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

	class CustomLayerImpl implements Omit<maplibregl.CustomLayerInterface, 'id' | 'type'> {
		renderingMode = '3d' as const;
		private camera = new THREE.Camera();
		private scene = new THREE.Scene();
		private renderer: THREE.WebGLRenderer | null = null;
		private map: maplibregl.Map | null = null;

		onAdd(map: maplibregl.Map, gl: WebGL2RenderingContext) {
			this.map = map;

			// Create two three.js lights to illuminate the model
			const directionalLight1 = new THREE.DirectionalLight(0xffffff);
			directionalLight1.position.set(0, -70, 100).normalize();
			this.scene.add(directionalLight1);

			const directionalLight2 = new THREE.DirectionalLight(0xffffff);
			directionalLight2.position.set(0, 70, 100).normalize();
			this.scene.add(directionalLight2);

			// Use the three.js GLTF loader to add the 3D model to the three.js scene
			const loader = new GLTFLoader();
			loader.load('https://maplibre.org/maplibre-gl-js/docs/assets/34M_17/34M_17.gltf', (gltf) => {
				this.scene.add(gltf.scene);
			});

			// Use the MapLibre GL JS map canvas for three.js
			this.renderer = new THREE.WebGLRenderer({
				canvas: map.getCanvas(),
				context: gl,
				antialias: true
			});
			this.renderer.autoClear = false;
		}

		render(_gl: WebGL2RenderingContext | WebGLRenderingContext, args: maplibregl.CustomRenderMethodInput) {
			const modelOrigin: [number, number] = [148.9819, -35.39847];
			const modelAltitude = 0;
			const scaling = 10_000.0;
			// We can use this API to get the correct model matrix.
			// It will work regardless of current projection.
			// See MapLibre source code, file "mercator_transform.ts" or "vertical_perspective_transform.ts".
			const modelMatrix = this.map!.transform.getMatrixForModel(modelOrigin, modelAltitude);
			const m = new THREE.Matrix4().fromArray(args.defaultProjectionData.mainMatrix);
			const l = new THREE.Matrix4().fromArray(modelMatrix).scale(new THREE.Vector3(scaling, scaling, scaling));

			this.camera.projectionMatrix = m.multiply(l);
			this.renderer!.resetState();
			this.renderer!.render(this.scene, this.camera);
			this.map!.triggerRepaint();
		}
	}

	const customLayerImpl = new CustomLayerImpl();
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	zoom={5}
	pitch={50}
	maxPitch={80}
	center={[150.16546137527212, -35.017179237129994]}
>
	<CustomLayer implementation={customLayerImpl} />
	<GlobeControl />
	<Projection type="globe" />
</MapLibre>


================================================
FILE: src/content/examples/threejs-model/content.svelte.md
================================================
---
title: 3D model with three.js
description: Use a custom style layer with three.js to add a 3D model to the map.
original: https://maplibre.org/maplibre-gl-js/docs/examples/globe-3d-model/
---

<script lang="ts">
  import Demo from "./CustomLayer.svelte";
  import demoRaw from "./CustomLayer.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/content/examples/toc.ts
================================================
import type { Toc } from '$lib/components/types';

export const toc: Toc = [
	{
		title: 'Basic',
		items: {
			'/examples/plain': 'Plain Map',
			'/examples/complex': 'Complex',
			'/examples/marker-popup': 'Marker and Popup',
			'/examples/basestyle': 'Change Base Style',
			'/examples/hover-styles': 'Hover Styles',
			'/examples/clusters': 'Clusters',
			'/examples/limit-interaction': 'Limit Map Interactions',
			'/examples/animate-images': 'Animate a Series of Images',
			'/examples/video-on-a-map': 'Video on a Map',
			'/examples/fullscreen': 'Fullscreen',
			'/examples/geolocate': 'Locate the User',
			'/examples/cursor': 'Change Cursor'
		}
	},
	{
		title: 'Styles',
		items: {
			'/examples/terrain': '3D Terrain and Sky',
			'/examples/color-relief': 'Color Relief',
			'/examples/globe-atmosphere': 'Globe with an Atmosphere',
			'/examples/3d-buildings': '3D Buildings',
			'/examples/global-state': 'Global State'
		}
	},
	{
		title: 'Utilities',
		items: {
			'/examples/image-loader': 'Load Images from URLs',
			'/examples/query-features': 'Query Features'
		}
	},
	{
		title: 'Techniques',
		items: {
			'/examples/side-by-side': 'Side by Side',
			'/examples/3d-extrusion-floorplan': '3D Floor Plan'
		}
	},
	{
		title: 'Advanced',
		items: {
			'/examples/custom-control': 'Custom Control',
			'/examples/custom-protocol': 'Custom Protocols',
			'/examples/canvas-source': 'Canvas Source',
			'/examples/custom-layer': 'Custom Layer',
			'/examples/dynamic-image': 'Dynamic Image',
			'/examples/threejs-model': '3D model with three.js'
		}
	},
	{
		title: 'Extensions',
		items: {
			'/examples/pmtiles': 'PMTiles Protocol',
			'/examples/deckgl-overlay': 'deck.gl Overlay',
			'/examples/contour': 'Contour Lines',
			'/examples/terradraw': 'Terra Draw'
		}
	}
];


================================================
FILE: src/content/examples/video-on-a-map/Video.svelte
================================================
<script lang="ts">
	import { MapLibre, VideoSource, GlobeControl, RasterLayer } from 'svelte-maplibre-gl';
	import maplibregl from 'maplibre-gl';

	let source: maplibregl.VideoSource | undefined = $state(undefined);
	let playing = $state(true);

	function toggle() {
		if (source) {
			playing = !playing;
			playing ? source.play() : source.pause();
		}
	}
</script>

<MapLibre
	class="h-[55vh] min-h-[300px]"
	style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
	minZoom={14}
	zoom={17}
	center={{ lng: -122.514426, lat: 37.562984 }}
	bearing={-96}
	onclick={toggle}
>
	<GlobeControl />
	<VideoSource
		bind:source
		urls={[
			'https://static-assets.mapbox.com/mapbox-gl-js/drone.mp4',
			'https://static-assets.mapbox.com/mapbox-gl-js/drone.webm'
		]}
		coordinates={[
			[-122.51596391201019, 37.56238816766053],
			[-122.51467645168304, 37.56410183312965],
			[-122.51309394836426, 37.563391708549425],
			[-122.51423120498657, 37.56161849366671]
		]}
	>
		<RasterLayer paint={{ 'raster-opacity': 0.7 }} />
	</VideoSource>
</MapLibre>


================================================
FILE: src/content/examples/video-on-a-map/content.svelte.md
================================================
---
title: Video on a map
description: Display a video.
original: https://maplibre.org/maplibre-gl-js/docs/examples/video-on-a-map/
---

<script lang="ts">
  import Demo from "./Video.svelte";
  import demoRaw from "./Video.svelte?raw";
  import CodeBlock from "../../CodeBlock.svelte";
  let { shiki } = $props();
</script>

<Demo />

<CodeBlock content={demoRaw} {shiki} />


================================================
FILE: src/demo.spec.ts
================================================
import { describe, it, expect } from 'vitest';

describe('sum test', () => {
	it('adds 1 + 2 to equal 3', () => {
		expect(1 + 2).toBe(3);
	});
});


================================================
FILE: src/lib/assets/fonts/LICENSE.txt
================================================
Copyright (c) 2023 Vercel, in collaboration with basement.studio

This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL

-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------

PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.

The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.

DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.

"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).

"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).

"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.

"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.

PERMISSION AND CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:

1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.

2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.

3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.

4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.

5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.

TERMINATION
This license becomes null and void if any of the above conditions are
not met.

DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.


================================================
FILE: src/lib/assets/fonts/geist.css
================================================
@font-face {
	font-family: 'Geist';
	src: url('./geist.woff2') format('woff2');
	font-display: swap;
}
@font-face {
	font-family: 'Geist Mono';
	src: url('./geist-mono.woff2') format('woff2');
	font-display: swap;
}


================================================
FILE: src/lib/assets/icons/GitHub.svelte
================================================
<script lang="ts">
	import type { SVGAttributes } from 'svelte/elements';

	let { ...props }: SVGAttributes<SVGElement> = $props();
</script>

<svg viewBox="0 0 438.549 438.549" {...props}>
	<path
		fill="currentColor"
		d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 01-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"
	/>
</svg>


================================================
FILE: src/lib/components/Index.svelte
================================================
<script lang="ts">
	import { page } from '$app/state';
	import type { Toc } from './types';
	let { name, toc }: { name: string; toc: Toc } = $props();
</script>

<nav>
	<h2 class="mb-4 text-lg leading-none font-bold">{name}</h2>
	{#each toc as subtoc (subtoc.title)}
		<h3 class="my-3">{subtoc.title}</h3>
		<ul class="flex flex-col text-sm">
			{#each Object.entries(subtoc.items) as [path, title] (path)}
				<li
					class="border-l border-foreground/10 py-1 pl-4 data-[active=true]:border-foreground"
					data-active={page.url.pathname === path}
				>
					<!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
					<a class="data-[active=true]:font-medium" data-active={page.url.pathname === path} href={path}>{title}</a>
				</li>
			{/each}
		</ul>
	{/each}
</nav>


================================================
FILE: src/lib/components/types.ts
================================================
export type Toc = {
	title: string;
	items: Record<string, string>;
}[];


================================================
FILE: src/lib/components/ui/badge/badge.svelte
================================================
<script lang="ts" module>
	import { type VariantProps, tv } from "tailwind-variants";

	export const badgeVariants = tv({
		base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] [&>svg]:pointer-events-none [&>svg]:size-3",
		variants: {
			variant: {
				default:
					"bg-primary text-primary-foreground [a&]:hover:bg-primary/90 border-transparent",
				secondary:
					"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90 border-transparent",
				destructive:
					"bg-destructive [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/70 border-transparent text-white",
				outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
			},
		},
		defaultVariants: {
			variant: "default",
		},
	});

	export type BadgeVariant = VariantProps<typeof badgeVariants>["variant"];
</script>

<script lang="ts">
	import type { HTMLAnchorAttributes } from "svelte/elements";
	import { cn, type WithElementRef } from "$lib/utils.js";

	let {
		ref = $bindable(null),
		href,
		class: className,
		variant = "default",
		children,
		...restProps
	}: WithElementRef<HTMLAnchorAttributes> & {
		variant?: BadgeVariant;
	} = $props();
</script>

<svelte:element
	this={href ? "a" : "span"}
	bind:this={ref}
	data-slot="badge"
	{href}
	class={cn(badgeVariants({ variant }), className)}
	{...restProps}
>
	{@render children?.()}
</svelte:element>


================================================
FILE: src/lib/components/ui/badge/index.ts
================================================
export { default as Badge } from "./badge.svelte";
export { badgeVariants, type BadgeVariant } from "./badge.svelte";


================================================
FILE: src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte
================================================
<script lang="ts">
	import EllipsisIcon from "@lucide/svelte/icons/ellipsis";
	import type { HTMLAttributes } from "svelte/elements";
	import { cn, type WithElementRef, type WithoutChildren } from "$lib/utils.js";

	let {
		ref = $bindable(null),
		class: className,
		...restProps
	}: WithoutChildren<WithElementRef<HTMLAttributes<HTMLSpanElement>>> = $props();
</script>

<span
	bind:this={ref}
	data-slot="breadcrumb-ellipsis"
	role="presentation"
	aria-hidden="true"
	class={cn("flex size-9 items-center justify-center", className)}
	{...restProps}
>
	<EllipsisIcon class="size-4" />
	<span class="sr-only">More</span>
</span>


================================================
FILE: src/lib/components/ui/breadcrumb/breadcrumb-item.svelte
================================================
<script lang="ts">
	import type { HTMLLiAttributes } from "svelte/elements";
	import { cn, type WithElementRef } from "$lib/utils.js";

	let {
		ref = $bindable(null),
		class: className,
		children,
		...restProps
	}: WithElementRef<HTMLLiAttributes> = $props();
</script>

<li
	bind:this={ref}
	data-slot="breadcrumb-item"
	class={cn("inline-flex items-center gap-1.5", className)}
	{...restProps}
>
	{@render children?.()}
</li>


================================================
FILE: src/lib/components/ui/breadcrumb/breadcrumb-link.svelte
================================================
<script lang="ts">
	import type { HTMLAnchorAttributes } from "svelte/elements";
	import type { Snippet } from "svelte";
	import { cn, type WithElementRef } from "$lib/utils.js";

	let {
		ref = $bindable(null),
		class: className,
		href = undefined,
		child,
		children,
		...restProps
	}: WithElementRef<HTMLAnchorAttributes> & {
		child?: Snippet<[{ props: HTMLAnchorAttributes }]>;
	} = $props();

	const attrs = $derived({
		"data-slot": "breadcrumb-link",
		class: cn("hover:text-foreground transition-colors", className),
		href,
		...restProps,
	});
</script>

{#if child}
	{@render child({ props: attrs })}
{:else}
	<a bind:this={ref} {...attrs}>
		{@render children?.()}
	</a>
{/if}


================================================
FILE: src/lib/components/ui/breadcrumb/breadcrumb-list.svelte
================================================
<script lang="ts">
	import type { HTMLOlAttributes } from "svelte/elements";
	import { cn, type WithElementRef } from "$lib/utils.js";

	let {
		ref = $bindable(null),
		class: className,
		children,
		...restProps
	}: WithElementRef<HTMLOlAttributes> = $props();
</script>

<ol
	bind:this={ref}
	data-slot="breadcrumb-list"
	class={cn(
		"text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
		className
	)}
	{...restProps}
>
	{@render children?.()}
</ol>


================================================
FILE: src/lib/components/ui/breadcrumb/breadcrumb-page.svelte
================================================
<script lang="ts">
	import type { HTMLAttributes } from "svelte/elements";
	import { cn, type WithElementRef } from "$lib/utils.js";

	let {
		ref = $bindable(null),
		class: className,
		children,
		...restProps
	}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
</script>

<span
	bind:this={ref}
	data-slot="breadcrumb-page"
	role="link"
	aria-disabled="true"
	aria-current="page"
	class={cn("text-foreground font-normal", className)}
	{...restProps}
>
	{@render children?.()}
</span>


================================================
FILE: src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte
================================================
<script lang="ts">
	import ChevronRightIcon from "@lucide/svelte/icons/chevron-right";
	import { cn, type WithElementRef } from "$lib/utils.js";
	import type { HTMLLiAttributes } from "svelte/elements";

	let {
		ref = $bindable(null),
		class: className,
		children,
		...restProps
	}: WithElementRef<HTMLLiAttributes> = $props();
</script>

<li
	bind:this={ref}
	data-slot="breadcrumb-separator"
	role="presentation"
	aria-hidden="true"
	class={cn("[&>svg]:size-3.5", className)}
	{...restProps}
>
	{#if children}
		{@render children?.()}
	{:else}
		<ChevronRightIcon />
	{/if}
</li>


================================================
FILE: src/lib/components/ui/breadcrumb/breadcrumb.svelte
================================================
<script lang="ts">
	import type { WithElementRef } from "$lib/utils.js";
	import type { HTMLAttributes } from "svelte/elements";

	let {
		ref = $bindable(null),
		class: className,
		children,
		...restProps
	}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
</script>

<nav
	bind:this={ref}
	data-slot="breadcrumb"
	class={className}
	aria-label="breadcrumb"
	{...restProps}
>
	{@render children?.()}
</nav>


================================================
FILE: src/lib/components/ui/breadcrumb/index.ts
================================================
import Root from "./breadcrumb.svelte";
import Ellipsis from "./breadcrumb-ellipsis.svelte";
import Item from "./breadcrumb-item.svelte";
import Separator from "./breadcrumb-separator.svelte";
import Link from "./breadcrumb-link.svelte";
import List from "./breadcrumb-list.svelte";
import Page from "./breadcrumb-page.svelte";

export {
	Root,
	Ellipsis,
	Item,
	Separator,
	Link,
	List,
	Page,
	//
	Root as Breadcrumb,
	Ellipsis as BreadcrumbEllipsis,
	Item as BreadcrumbItem,
	Separator as BreadcrumbSeparator,
	Link as BreadcrumbLink,
	List as BreadcrumbList,
	Page as BreadcrumbPage,
};


================================================
FILE: src/lib/components/ui/button/button.svelte
================================================
<script lang="ts" module>
	import { cn, type WithElementRef } from "$lib/utils.js";
	import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
	import { type VariantProps, tv } from "tailwind-variants";

	export const buttonVariants = tv({
		base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
		variants: {
			variant: {
				default: "bg-primary text-primary-foreground hover:bg-primary/90 shadow-xs",
				destructive:
					"bg-destructive hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white shadow-xs",
				outline:
					"bg-background hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border shadow-xs",
				secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-xs",
				ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
				link: "text-primary underline-offset-4 hover:underline",
			},
			size: {
				default: "h-9 px-4 py-2 has-[>svg]:px-3",
				sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
				lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
				icon: "size-9",
				"icon-sm": "size-8",
				"icon-lg": "size-10",
			},
		},
		defaultVariants: {
			variant: "default",
			size: "default",
		},
	});

	export type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
	export type ButtonSize = VariantProps<typeof buttonVariants>["size"];

	export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
		WithElementRef<HTMLAnchorAttributes> & {
			variant?: ButtonVariant;
			size?: ButtonSize;
		};
</script>

<script lang="ts">
	let {
		class: className,
		variant = "default",
		size = "default",
		ref = $bindable(null),
		href = undefined,
		type = "button",
		disabled,
		children,
		...restProps
	}: ButtonProps = $props();
</script>

{#if href}
    <!-- eslint-disable svelte/no-navigation-without-resolve -->
	<a
		bind:this={ref}
		data-slot="button"
		class={cn(buttonVariants({ variant, size }), className)}
		href={disabled ? undefined : href}
		aria-disabled={disabled}
		role={disabled ? "link" : undefined}
		tabindex={disabled ? -1 : undefined}
		{...restProps}
	>
		{@render children?.()}
	</a>
{:else}
	<button
		bind:this={ref}
		data-slot="button"
		class={cn(buttonVariants({ variant, size }), className)}
		{type}
		{disabled}
		{...restProps}
	>
		{@render children?.()}
	</button>
{/if}


================================================
FILE: src/lib/components/ui/button/index.ts
================================================
import Root, {
	type ButtonProps,
	type ButtonSize,
	type ButtonVariant,
	buttonVariants,
} from "./button.svelte";

export {
	Root,
	type ButtonProps as Props,
	//
	Root as Button,
	buttonVariants,
	type ButtonProps,
	type ButtonSize,
	type ButtonVariant,
};


================================================
FILE: src/lib/components/ui/checkbox/checkbox.svelte
================================================
<script lang="ts">
	import { Checkbox as CheckboxPrimitive } from "bits-ui";
	import CheckIcon from "@lucide/svelte/icons/check";
	import MinusIcon from "@lucide/svelte/icons/minus";
	import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";

	let {
		ref = $bindable(null),
		checked = $bindable(false),
		indeterminate = $bindable(false),
		class: className,
		...restProps
	}: WithoutChildrenOrChild<CheckboxPrimitive.RootProps> = $props();
</script>

<CheckboxPrimitive.Root
	bind:ref
	data-slot="checkbox"
	class={cn(
		"border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive peer flex size-4 shrink-0 items-center justify-center rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
		className
	)}
	bind:checked
	bind:indeterminate
	{...restProps}
>
	{#snippet children({ checked, indeterminate })}
		<div data-slot="checkbox-indicator" class="text-current transition-none">
			{#if checked}
				<CheckIcon class="size-3.5" />
			{:else if indeterminate}
				<MinusIcon class="size-3.5" />
			{/if}
		</div>
	{/snippet}
</CheckboxPrimitive.Root>


================================================
FILE: src/lib/components/ui/checkbox/index.ts
================================================
import Root from "./checkbox.svelte";
export {
	Root,
	//
	Root as Checkbox,
};


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte
================================================
<script lang="ts">
	import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";

	let {
		ref = $bindable(null),
		value = $bindable([]),
		...restProps
	}: DropdownMenuPrimitive.CheckboxGroupProps = $props();
</script>

<DropdownMenuPrimitive.CheckboxGroup
	bind:ref
	bind:value
	data-slot="dropdown-menu-checkbox-group"
	{...restProps}
/>


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte
================================================
<script lang="ts">
	import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
	import CheckIcon from "@lucide/svelte/icons/check";
	import MinusIcon from "@lucide/svelte/icons/minus";
	import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
	import type { Snippet } from "svelte";

	let {
		ref = $bindable(null),
		checked = $bindable(false),
		indeterminate = $bindable(false),
		class: className,
		children: childrenProp,
		...restProps
	}: WithoutChildrenOrChild<DropdownMenuPrimitive.CheckboxItemProps> & {
		children?: Snippet;
	} = $props();
</script>

<DropdownMenuPrimitive.CheckboxItem
	bind:ref
	bind:checked
	bind:indeterminate
	data-slot="dropdown-menu-checkbox-item"
	class={cn(
		"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
		className
	)}
	{...restProps}
>
	{#snippet children({ checked, indeterminate })}
		<span
			class="pointer-events-none absolute start-2 flex size-3.5 items-center justify-center"
		>
			{#if indeterminate}
				<MinusIcon class="size-4" />
			{:else}
				<CheckIcon class={cn("size-4", !checked && "text-transparent")} />
			{/if}
		</span>
		{@render childrenProp?.()}
	{/snippet}
</DropdownMenuPrimitive.CheckboxItem>


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte
================================================
<script lang="ts">
	import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
	import DropdownMenuPortal from "./dropdown-menu-portal.svelte";
	import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
	import type { ComponentProps } from "svelte";

	let {
		ref = $bindable(null),
		sideOffset = 4,
		portalProps,
		class: className,
		...restProps
	}: DropdownMenuPrimitive.ContentProps & {
		portalProps?: WithoutChildrenOrChild<ComponentProps<typeof DropdownMenuPortal>>;
	} = $props();
</script>

<DropdownMenuPortal {...portalProps}>
	<DropdownMenuPrimitive.Content
		bind:ref
		data-slot="dropdown-menu-content"
		{sideOffset}
		class={cn(
			"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-end-2 data-[side=right]:slide-in-from-start-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--bits-dropdown-menu-content-available-height) min-w-[8rem] origin-(--bits-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md outline-none",
			className
		)}
		{...restProps}
	/>
</DropdownMenuPortal>


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte
================================================
<script lang="ts">
	import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
	import { cn } from "$lib/utils.js";
	import type { ComponentProps } from "svelte";

	let {
		ref = $bindable(null),
		class: className,
		inset,
		...restProps
	}: ComponentProps<typeof DropdownMenuPrimitive.GroupHeading> & {
		inset?: boolean;
	} = $props();
</script>

<DropdownMenuPrimitive.GroupHeading
	bind:ref
	data-slot="dropdown-menu-group-heading"
	data-inset={inset}
	class={cn("px-2 py-1.5 text-sm font-semibold data-[inset]:ps-8", className)}
	{...restProps}
/>


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte
================================================
<script lang="ts">
	import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";

	let { ref = $bindable(null), ...restProps }: DropdownMenuPrimitive.GroupProps = $props();
</script>

<DropdownMenuPrimitive.Group bind:ref data-slot="dropdown-menu-group" {...restProps} />


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte
================================================
<script lang="ts">
	import { cn } from "$lib/utils.js";
	import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";

	let {
		ref = $bindable(null),
		class: className,
		inset,
		variant = "default",
		...restProps
	}: DropdownMenuPrimitive.ItemProps & {
		inset?: boolean;
		variant?: "default" | "destructive";
	} = $props();
</script>

<DropdownMenuPrimitive.Item
	bind:ref
	data-slot="dropdown-menu-item"
	data-inset={inset}
	data-variant={variant}
	class={cn(
		"data-highlighted:bg-accent data-highlighted:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:data-highlighted:bg-destructive/10 dark:data-[variant=destructive]:data-highlighted:bg-destructive/20 data-[variant=destructive]:data-highlighted:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:ps-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
		className
	)}
	{...restProps}
/>


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte
================================================
<script lang="ts">
	import { cn, type WithElementRef } from "$lib/utils.js";
	import type { HTMLAttributes } from "svelte/elements";

	let {
		ref = $bindable(null),
		class: className,
		inset,
		children,
		...restProps
	}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
		inset?: boolean;
	} = $props();
</script>

<div
	bind:this={ref}
	data-slot="dropdown-menu-label"
	data-inset={inset}
	class={cn("px-2 py-1.5 text-sm font-semibold data-[inset]:ps-8", className)}
	{...restProps}
>
	{@render children?.()}
</div>


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte
================================================
<script lang="ts">
	import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";

	let { ...restProps }: DropdownMenuPrimitive.PortalProps = $props();
</script>

<DropdownMenuPrimitive.Portal {...restProps} />


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte
================================================
<script lang="ts">
	import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";

	let {
		ref = $bindable(null),
		value = $bindable(),
		...restProps
	}: DropdownMenuPrimitive.RadioGroupProps = $props();
</script>

<DropdownMenuPrimitive.RadioGroup
	bind:ref
	bind:value
	data-slot="dropdown-menu-radio-group"
	{...restProps}
/>


================================================
FILE: src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte
================================================
<script lang="ts">
	import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui";
	import CircleIcon from "@lucide/svelte/icons/circle";
	import { cn, type WithoutChild } from "$lib/utils.js";

	let {
		ref = $bindable(null),
		class: className,
		children: childrenProp,
		...restProps
	}: WithoutChild<DropdownMenuPrimitive.RadioItemProps> = $props();
</script>

<DropdownMenuPrimitive.RadioItem
	bind:ref
	data-slot="dropdown-menu-radio-item"
	class={cn(
		"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
		className
	)}
	{...restProps}
>
	{#snippet children({ checked })}
		<span
			class="pointer-events-none absolute start-2 flex size-3.5 items-center ju
Download .txt
gitextract_qlcdzk6r/

├── .changeset/
│   ├── README.md
│   └── config.json
├── .github/
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── lint.yml
│       ├── preview.yml
│       └── release.yml
├── .gitignore
├── .node-version
├── .npmrc
├── .prettierignore
├── .prettierrc
├── LICENSE-APACHE.txt
├── LICENSE-MIT.txt
├── README.md
├── components.json
├── e2e/
│   └── demo.test.ts
├── eslint.config.js
├── extensions/
│   ├── contour/
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── app.d.ts
│   │   │   ├── app.html
│   │   │   └── lib/
│   │   │       ├── MapLibreContourSource.svelte
│   │   │       └── index.ts
│   │   ├── svelte.config.js
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── deckgl/
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── app.d.ts
│   │   │   ├── app.html
│   │   │   └── lib/
│   │   │       ├── DeckGLOverlay.svelte
│   │   │       └── index.ts
│   │   ├── svelte.config.js
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── pmtiles/
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── app.d.ts
│   │   │   ├── app.html
│   │   │   └── lib/
│   │   │       ├── PMTilesProtocol.svelte
│   │   │       └── index.ts
│   │   ├── svelte.config.js
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   └── terradraw/
│       ├── CHANGELOG.md
│       ├── package.json
│       ├── src/
│       │   ├── app.d.ts
│       │   ├── app.html
│       │   └── lib/
│       │       ├── TerraDraw.svelte
│       │       └── index.ts
│       ├── svelte.config.js
│       ├── tsconfig.json
│       └── vite.config.ts
├── package.json
├── playwright.config.ts
├── pnpm-workspace.yaml
├── src/
│   ├── app.css
│   ├── app.d.ts
│   ├── app.html
│   ├── content/
│   │   ├── CodeBlock.svelte
│   │   ├── components/
│   │   │   └── toc.ts
│   │   ├── docs/
│   │   │   ├── quickstart/
│   │   │   │   ├── Marker.svelte
│   │   │   │   ├── Simplest.svelte
│   │   │   │   └── content.svelte.md
│   │   │   └── toc.ts
│   │   └── examples/
│   │       ├── 3d-buildings/
│   │       │   ├── Buildings3D.svelte
│   │       │   └── content.svelte.md
│   │       ├── 3d-extrusion-floorplan/
│   │       │   ├── Floorplan.svelte
│   │       │   └── content.svelte.md
│   │       ├── animate-images/
│   │       │   ├── AnimateImages.svelte
│   │       │   └── content.svelte.md
│   │       ├── basestyle/
│   │       │   ├── BaseStyle.svelte
│   │       │   └── content.svelte.md
│   │       ├── canvas-source/
│   │       │   ├── Canvas.svelte
│   │       │   ├── Circle.ts
│   │       │   └── content.svelte.md
│   │       ├── clusters/
│   │       │   ├── Clusters.svelte
│   │       │   └── content.svelte.md
│   │       ├── color-relief/
│   │       │   ├── ColorRelief.svelte
│   │       │   └── content.svelte.md
│   │       ├── complex/
│   │       │   ├── Complex.svelte
│   │       │   └── content.svelte.md
│   │       ├── contour/
│   │       │   ├── Contour.svelte
│   │       │   └── content.svelte.md
│   │       ├── cursor/
│   │       │   ├── Cursor.svelte
│   │       │   └── content.svelte.md
│   │       ├── custom-control/
│   │       │   ├── CustomControl.svelte
│   │       │   ├── MyControl.ts
│   │       │   └── content.svelte.md
│   │       ├── custom-layer/
│   │       │   ├── CustomLayer.svelte
│   │       │   └── content.svelte.md
│   │       ├── custom-protocol/
│   │       │   ├── CustomProtocol.svelte
│   │       │   └── content.svelte.md
│   │       ├── deckgl-overlay/
│   │       │   ├── DeckGL.svelte
│   │       │   └── content.svelte.md
│   │       ├── dynamic-image/
│   │       │   ├── DynamicImage.svelte
│   │       │   └── content.svelte.md
│   │       ├── fullscreen/
│   │       │   ├── Fullscreen.svelte
│   │       │   └── content.svelte.md
│   │       ├── geolocate/
│   │       │   ├── Geolocate.svelte
│   │       │   └── content.svelte.md
│   │       ├── global-state/
│   │       │   ├── Plain.svelte
│   │       │   └── content.svelte.md
│   │       ├── globe-atmosphere/
│   │       │   ├── Globe.svelte
│   │       │   └── content.svelte.md
│   │       ├── hover-styles/
│   │       │   ├── HoverStyles.svelte
│   │       │   └── content.svelte.md
│   │       ├── image-loader/
│   │       │   ├── Images.svelte
│   │       │   └── content.svelte.md
│   │       ├── limit-interaction/
│   │       │   ├── LimitInteraction.svelte
│   │       │   └── content.svelte.md
│   │       ├── marker-popup/
│   │       │   ├── MarkerAndPopup.svelte
│   │       │   └── content.svelte.md
│   │       ├── plain/
│   │       │   ├── Plain.svelte
│   │       │   └── content.svelte.md
│   │       ├── pmtiles/
│   │       │   ├── PMTiles.svelte
│   │       │   └── content.svelte.md
│   │       ├── query-features/
│   │       │   ├── Query.svelte
│   │       │   └── content.svelte.md
│   │       ├── side-by-side/
│   │       │   ├── SideBySide.svelte
│   │       │   └── content.svelte.md
│   │       ├── terradraw/
│   │       │   ├── TerraDraw.svelte
│   │       │   └── content.svelte.md
│   │       ├── terrain/
│   │       │   ├── Terrain.svelte
│   │       │   └── content.svelte.md
│   │       ├── threejs-model/
│   │       │   ├── CustomLayer.svelte
│   │       │   └── content.svelte.md
│   │       ├── toc.ts
│   │       └── video-on-a-map/
│   │           ├── Video.svelte
│   │           └── content.svelte.md
│   ├── demo.spec.ts
│   ├── lib/
│   │   ├── assets/
│   │   │   ├── fonts/
│   │   │   │   ├── LICENSE.txt
│   │   │   │   └── geist.css
│   │   │   └── icons/
│   │   │       └── GitHub.svelte
│   │   ├── components/
│   │   │   ├── Index.svelte
│   │   │   ├── types.ts
│   │   │   └── ui/
│   │   │       ├── badge/
│   │   │       │   ├── badge.svelte
│   │   │       │   └── index.ts
│   │   │       ├── breadcrumb/
│   │   │       │   ├── breadcrumb-ellipsis.svelte
│   │   │       │   ├── breadcrumb-item.svelte
│   │   │       │   ├── breadcrumb-link.svelte
│   │   │       │   ├── breadcrumb-list.svelte
│   │   │       │   ├── breadcrumb-page.svelte
│   │   │       │   ├── breadcrumb-separator.svelte
│   │   │       │   ├── breadcrumb.svelte
│   │   │       │   └── index.ts
│   │   │       ├── button/
│   │   │       │   ├── button.svelte
│   │   │       │   └── index.ts
│   │   │       ├── checkbox/
│   │   │       │   ├── checkbox.svelte
│   │   │       │   └── index.ts
│   │   │       ├── dropdown-menu/
│   │   │       │   ├── dropdown-menu-checkbox-group.svelte
│   │   │       │   ├── dropdown-menu-checkbox-item.svelte
│   │   │       │   ├── dropdown-menu-content.svelte
│   │   │       │   ├── dropdown-menu-group-heading.svelte
│   │   │       │   ├── dropdown-menu-group.svelte
│   │   │       │   ├── dropdown-menu-item.svelte
│   │   │       │   ├── dropdown-menu-label.svelte
│   │   │       │   ├── dropdown-menu-portal.svelte
│   │   │       │   ├── dropdown-menu-radio-group.svelte
│   │   │       │   ├── dropdown-menu-radio-item.svelte
│   │   │       │   ├── dropdown-menu-separator.svelte
│   │   │       │   ├── dropdown-menu-shortcut.svelte
│   │   │       │   ├── dropdown-menu-sub-content.svelte
│   │   │       │   ├── dropdown-menu-sub-trigger.svelte
│   │   │       │   ├── dropdown-menu-sub.svelte
│   │   │       │   ├── dropdown-menu-trigger.svelte
│   │   │       │   ├── dropdown-menu.svelte
│   │   │       │   └── index.ts
│   │   │       ├── label/
│   │   │       │   ├── index.ts
│   │   │       │   └── label.svelte
│   │   │       ├── radio-group/
│   │   │       │   ├── index.ts
│   │   │       │   ├── radio-group-item.svelte
│   │   │       │   └── radio-group.svelte
│   │   │       ├── select/
│   │   │       │   ├── index.ts
│   │   │       │   ├── select-content.svelte
│   │   │       │   ├── select-group-heading.svelte
│   │   │       │   ├── select-group.svelte
│   │   │       │   ├── select-item.svelte
│   │   │       │   ├── select-label.svelte
│   │   │       │   ├── select-portal.svelte
│   │   │       │   ├── select-scroll-down-button.svelte
│   │   │       │   ├── select-scroll-up-button.svelte
│   │   │       │   ├── select-separator.svelte
│   │   │       │   ├── select-trigger.svelte
│   │   │       │   └── select.svelte
│   │   │       ├── separator/
│   │   │       │   ├── index.ts
│   │   │       │   └── separator.svelte
│   │   │       ├── slider/
│   │   │       │   ├── index.ts
│   │   │       │   └── slider.svelte
│   │   │       ├── switch/
│   │   │       │   ├── index.ts
│   │   │       │   └── switch.svelte
│   │   │       ├── table/
│   │   │       │   ├── index.ts
│   │   │       │   ├── table-body.svelte
│   │   │       │   ├── table-caption.svelte
│   │   │       │   ├── table-cell.svelte
│   │   │       │   ├── table-footer.svelte
│   │   │       │   ├── table-head.svelte
│   │   │       │   ├── table-header.svelte
│   │   │       │   ├── table-row.svelte
│   │   │       │   └── table.svelte
│   │   │       └── tabs/
│   │   │           ├── index.ts
│   │   │           ├── tabs-content.svelte
│   │   │           ├── tabs-list.svelte
│   │   │           ├── tabs-trigger.svelte
│   │   │           └── tabs.svelte
│   │   └── utils.ts
│   └── routes/
│       ├── +layout.server.ts
│       ├── +layout.svelte
│       ├── +page.svelte
│       ├── DarkModeSelector.svelte
│       ├── GlobalToc.svelte
│       ├── Header.svelte
│       ├── ViewTransition.svelte
│       ├── docs/
│       │   ├── +layout.ts
│       │   ├── +page.svelte
│       │   ├── [slug]/
│       │   │   ├── +layout.svelte
│       │   │   ├── +page.svelte
│       │   │   └── +page.ts
│       │   └── components/
│       │       ├── +page.svelte
│       │       ├── [slug]/
│       │       │   ├── _+layout.svelte_
│       │       │   ├── _+page.svelte_
│       │       │   ├── _+page.ts_
│       │       │   ├── _Prop.svelte_
│       │       │   └── _utils.ts_
│       │       └── components.json
│       ├── examples/
│       │   ├── +layout.ts
│       │   ├── +page.svelte
│       │   └── [slug]/
│       │       ├── +layout.svelte
│       │       ├── +page.svelte
│       │       └── +page.ts
│       └── sitemap.xml/
│           └── +server.ts
├── svelte-maplibre-gl/
│   ├── CHANGELOG.md
│   ├── package.json
│   ├── src/
│   │   ├── app.d.ts
│   │   ├── app.html
│   │   └── lib/
│   │       ├── contexts.svelte.ts
│   │       ├── controls/
│   │       │   ├── AttributionControl.svelte
│   │       │   ├── CustomControl.svelte
│   │       │   ├── FullScreenControl.svelte
│   │       │   ├── GeolocateControl.svelte
│   │       │   ├── GlobeControl.svelte
│   │       │   ├── Hash.svelte
│   │       │   ├── LogoControl.svelte
│   │       │   ├── NavigationControl.svelte
│   │       │   ├── ScaleControl.svelte
│   │       │   └── TerrainControl.svelte
│   │       ├── global/
│   │       │   └── Protocol.svelte
│   │       ├── index.ts
│   │       ├── layers/
│   │       │   ├── BackgroundLayer.svelte
│   │       │   ├── CircleLayer.svelte
│   │       │   ├── ColorReliefLayer.svelte
│   │       │   ├── CustomLayer.svelte
│   │       │   ├── FillExtrusionLayer.svelte
│   │       │   ├── FillLayer.svelte
│   │       │   ├── HeatmapLayer.svelte
│   │       │   ├── HillshadeLayer.svelte
│   │       │   ├── LineLayer.svelte
│   │       │   ├── RasterLayer.svelte
│   │       │   ├── RawLayer.svelte
│   │       │   ├── SymbolLayer.svelte
│   │       │   └── common.ts
│   │       ├── map/
│   │       │   ├── Image.svelte
│   │       │   ├── Light.svelte
│   │       │   ├── MapLibre.svelte
│   │       │   ├── Projection.svelte
│   │       │   ├── Sky.svelte
│   │       │   ├── Sprite.svelte
│   │       │   └── Terrain.svelte
│   │       ├── markers/
│   │       │   ├── Marker.svelte
│   │       │   └── Popup.svelte
│   │       ├── sources/
│   │       │   ├── CanvasSource.svelte
│   │       │   ├── FeatureState.svelte
│   │       │   ├── GeoJSONSource.svelte
│   │       │   ├── ImageSource.svelte
│   │       │   ├── RasterDEMTileSource.svelte
│   │       │   ├── RasterTileSource.svelte
│   │       │   ├── RawSource.svelte
│   │       │   ├── VectorTileSource.svelte
│   │       │   └── VideoSource.svelte
│   │       ├── types.ts
│   │       ├── utilities/
│   │       │   ├── ImageLoader.svelte
│   │       │   ├── QueryRenderedFeatures.svelte
│   │       │   └── QuerySourceFeatures.svelte
│   │       └── utils.ts
│   ├── svelte.config.js
│   ├── tsconfig.json
│   └── vite.config.ts
├── svelte.config.js
├── tailwind.config.ts
├── tsconfig.json
├── turbo.json
├── vite.config.ts
└── wrangler.jsonc
Download .txt
SYMBOL INDEX (48 symbols across 8 files)

FILE: src/content/examples/canvas-source/Circle.ts
  class Circle (line 1) | class Circle {
    method constructor (line 2) | constructor(
    method draw (line 11) | draw(ctx: CanvasRenderingContext2D) {
    method update (line 18) | update(ctx: CanvasRenderingContext2D) {

FILE: src/content/examples/custom-control/MyControl.ts
  type MyControlConstructorOptions (line 1) | interface MyControlConstructorOptions {
  class MyControl (line 6) | class MyControl implements maplibregl.IControl {
    method constructor (line 11) | constructor(options: MyControlConstructorOptions) {
    method onAdd (line 16) | onAdd() {
    method onRemove (line 51) | onRemove() {

FILE: src/lib/components/types.ts
  type Toc (line 1) | type Toc = {

FILE: src/lib/utils.ts
  function cn (line 4) | function cn(...inputs: ClassValue[]) {
  type WithoutChild (line 9) | type WithoutChild<T> = T extends { child?: any } ? Omit<T, 'child'> : T;
  type WithoutChildren (line 11) | type WithoutChildren<T> = T extends { children?: any } ? Omit<T, 'childr...
  type WithoutChildrenOrChild (line 12) | type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
  type WithElementRef (line 13) | type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?...

FILE: svelte-maplibre-gl/src/lib/contexts.svelte.ts
  constant MAP_CONTEXT_KEY (line 15) | const MAP_CONTEXT_KEY = Symbol('MapLibre map context');
  constant SOURCE_CONTEXT_KEY (line 16) | const SOURCE_CONTEXT_KEY = Symbol('MapLibre source context');
  constant LAYER_CONTEXT_KEY (line 17) | const LAYER_CONTEXT_KEY = Symbol('MapLibre layer context');
  constant MARKER_CONTEXT_KEY (line 18) | const MARKER_CONTEXT_KEY = Symbol('MapLibre marker context');
  class MapContext (line 21) | class MapContext {
    method map (line 48) | get map() {
    method map (line 52) | set map(value: maplibregl.Map | null) {
    method addLayer (line 64) | addLayer(addLayerObject: AddLayerObject, beforeId?: string) {
    method removeLayer (line 71) | removeLayer(id: string) {
    method addSource (line 79) | addSource(id: string, source: SourceSpecification | CanvasSourceSpecif...
    method removeSource (line 85) | removeSource(id: string) {
    method waitForStyleLoaded (line 93) | waitForStyleLoaded(func: (map: maplibregl.Map) => void) {
    method _onstyledata (line 106) | private _onstyledata(ev: maplibregl.MapStyleDataEvent) {
    method setStyle (line 117) | setStyle(style: string | StyleSpecification | null) {
  function prepareMapContext (line 160) | function prepareMapContext(): MapContext {
  function getMapContext (line 166) | function getMapContext(): MapContext {
  class SourceContext (line 173) | class SourceContext {
  function prepareSourceContext (line 178) | function prepareSourceContext(): SourceContext {
  function getSourceContext (line 184) | function getSourceContext(): SourceContext {
  class LayerContext (line 190) | class LayerContext {
  function prepareLayerContext (line 194) | function prepareLayerContext(): LayerContext {
  function getLayerContext (line 200) | function getLayerContext(): LayerContext | null {
  class MarkerContext (line 206) | class MarkerContext {
  function prepareMarkerContext (line 210) | function prepareMarkerContext(): MarkerContext {
  function getMarkerContext (line 216) | function getMarkerContext(): MarkerContext | null {

FILE: svelte-maplibre-gl/src/lib/layers/common.ts
  type MapLayerEventProps (line 3) | type MapLayerEventProps = {

FILE: svelte-maplibre-gl/src/lib/types.ts
  type Listener (line 1) | type Listener<T> = (event: T) => void;
  type Event (line 3) | type Event<T, N = string> = {

FILE: svelte-maplibre-gl/src/lib/utils.ts
  function generateLayerID (line 6) | function generateLayerID() {
  function generateSourceID (line 10) | function generateSourceID() {
  function resetEventListener (line 19) | function resetEventListener(
  function resetLayerEventListener (line 40) | function resetLayerEventListener(
  function formatLngLat (line 57) | function formatLngLat(target: maplibregl.LngLatLike, lnglat: maplibregl....
Condensed preview — 294 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (378K chars).
[
  {
    "path": ".changeset/README.md",
    "chars": 510,
    "preview": "# Changesets\n\nHello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that wo"
  },
  {
    "path": ".changeset/config.json",
    "chars": 396,
    "preview": "{\n\t\"$schema\": \"https://unpkg.com/@changesets/config@3.0.0/schema.json\",\n\t\"changelog\": \"@changesets/cli/changelog\",\n\t\"com"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 118,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: 'github-actions'\n    directory: '/'\n    schedule:\n      interval: 'weekly'\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 236,
    "preview": "<!-- Close or Related Issues -->\n\nClose #0\n\n### What I did\n<!-- Please describe the motivation behind this PR and the ch"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 522,
    "preview": "name: Lint\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    permiss"
  },
  {
    "path": ".github/workflows/preview.yml",
    "chars": 749,
    "preview": "name: Preview Release\n\non:\n  pull_request:\n\njobs:\n  preview-release:\n    runs-on: ubuntu-latest\n    permissions:\n      c"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 1373,
    "preview": "name: Release\n\non:\n  push:\n    branches:\n      - main\n\nconcurrency: ${{ github.workflow }}-${{ github.ref }}\n\njobs:\n  re"
  },
  {
    "path": ".gitignore",
    "chars": 274,
    "preview": "test-results\nnode_modules\n\n# Output\n.output\n.vercel\n**/.svelte-kit/\n**/dist/\n/build\n.turbo\n\n# OS\n.DS_Store\nThumbs.db\n\n# "
  },
  {
    "path": ".node-version",
    "chars": 5,
    "preview": "22.17"
  },
  {
    "path": ".npmrc",
    "chars": 18,
    "preview": "engine-strict=true"
  },
  {
    "path": ".prettierignore",
    "chars": 154,
    "preview": "# Package Managers\npackage-lock.json\npnpm-lock.yaml\nyarn.lock\n\n**/dist/\n**/.svelte-kit/\n\n# shadcn-svelte\nsrc/lib/compone"
  },
  {
    "path": ".prettierrc",
    "chars": 397,
    "preview": "{\n\t\"useTabs\": true,\n\t\"singleQuote\": true,\n\t\"trailingComma\": \"none\",\n\t\"printWidth\": 120,\n\t\"plugins\": [\"prettier-plugin-ta"
  },
  {
    "path": "LICENSE-APACHE.txt",
    "chars": 11357,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "LICENSE-MIT.txt",
    "chars": 1035,
    "preview": "MIT License\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associate"
  },
  {
    "path": "README.md",
    "chars": 2001,
    "preview": "# Svelte MapLibre GL\n\n![NPM Version](https://img.shields.io/npm/v/svelte-maplibre-gl)\n![NPM License](https://img.shields"
  },
  {
    "path": "components.json",
    "chars": 343,
    "preview": "{\n\t\"$schema\": \"https://shadcn-svelte.com/schema.json\",\n\t\"tailwind\": {\n\t\t\"css\": \"src/app.css\",\n\t\t\"baseColor\": \"slate\"\n\t},"
  },
  {
    "path": "e2e/demo.test.ts",
    "chars": 182,
    "preview": "import { expect, test } from '@playwright/test';\n\ntest('home page has expected h1', async ({ page }) => {\n\tawait page.go"
  },
  {
    "path": "eslint.config.js",
    "chars": 832,
    "preview": "import prettier from 'eslint-config-prettier';\nimport js from '@eslint/js';\nimport svelte from 'eslint-plugin-svelte';\ni"
  },
  {
    "path": "extensions/contour/CHANGELOG.md",
    "chars": 306,
    "preview": "# @svelte-maplibre-gl/contour\n\n## 1.0.3\n\n### Patch Changes\n\n- Updated dependencies [6b3cd54]\n  - svelte-maplibre-gl@1.0."
  },
  {
    "path": "extensions/contour/package.json",
    "chars": 1566,
    "preview": "{\n\t\"name\": \"@svelte-maplibre-gl/contour\",\n\t\"version\": \"1.0.3\",\n\t\"license\": \"(MIT OR Apache-2.0)\",\n\t\"description\": \"mapli"
  },
  {
    "path": "extensions/contour/src/app.d.ts",
    "chars": 274,
    "preview": "// See https://svelte.dev/docs/kit/types#app.d.ts\n// for information about these interfaces\ndeclare global {\n\tnamespace "
  },
  {
    "path": "extensions/contour/src/app.html",
    "chars": 286,
    "preview": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width,"
  },
  {
    "path": "extensions/contour/src/lib/MapLibreContourSource.svelte",
    "chars": 1927,
    "preview": "<script lang=\"ts\">\n\t// https://github.com/onthegomap/maplibre-contour\n\n\timport type { Snippet } from 'svelte';\n\timport m"
  },
  {
    "path": "extensions/contour/src/lib/index.ts",
    "chars": 83,
    "preview": "export { default as MapLibreContourSource } from './MapLibreContourSource.svelte';\n"
  },
  {
    "path": "extensions/contour/svelte.config.js",
    "chars": 379,
    "preview": "import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';\n\n/** @type {import('@sveltejs/kit').Config} */\nconst conf"
  },
  {
    "path": "extensions/contour/tsconfig.json",
    "chars": 517,
    "preview": "{\n\t\"extends\": \"./.svelte-kit/tsconfig.json\",\n\t\"compilerOptions\": {\n\t\t\"allowJs\": true,\n\t\t\"checkJs\": true,\n\t\t\"esModuleInte"
  },
  {
    "path": "extensions/contour/vite.config.ts",
    "chars": 516,
    "preview": "import { defineConfig } from 'vite';\nimport { svelte } from '@sveltejs/vite-plugin-svelte';\n\nexport default defineConfig"
  },
  {
    "path": "extensions/deckgl/CHANGELOG.md",
    "chars": 305,
    "preview": "# @svelte-maplibre-gl/deckgl\n\n## 1.0.3\n\n### Patch Changes\n\n- Updated dependencies [6b3cd54]\n  - svelte-maplibre-gl@1.0.3"
  },
  {
    "path": "extensions/deckgl/package.json",
    "chars": 1675,
    "preview": "{\n\t\"name\": \"@svelte-maplibre-gl/deckgl\",\n\t\"version\": \"1.0.3\",\n\t\"license\": \"(MIT OR Apache-2.0)\",\n\t\"description\": \"DeckGL"
  },
  {
    "path": "extensions/deckgl/src/app.d.ts",
    "chars": 274,
    "preview": "// See https://svelte.dev/docs/kit/types#app.d.ts\n// for information about these interfaces\ndeclare global {\n\tnamespace "
  },
  {
    "path": "extensions/deckgl/src/app.html",
    "chars": 286,
    "preview": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width,"
  },
  {
    "path": "extensions/deckgl/src/lib/DeckGLOverlay.svelte",
    "chars": 4062,
    "preview": "<script lang=\"ts\">\n\timport { onDestroy, onMount, untrack } from 'svelte';\n\timport maplibregl from 'maplibre-gl';\n\timport"
  },
  {
    "path": "extensions/deckgl/src/lib/index.ts",
    "chars": 67,
    "preview": "export { default as DeckGLOverlay } from './DeckGLOverlay.svelte';\n"
  },
  {
    "path": "extensions/deckgl/svelte.config.js",
    "chars": 379,
    "preview": "import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';\n\n/** @type {import('@sveltejs/kit').Config} */\nconst conf"
  },
  {
    "path": "extensions/deckgl/tsconfig.json",
    "chars": 517,
    "preview": "{\n\t\"extends\": \"./.svelte-kit/tsconfig.json\",\n\t\"compilerOptions\": {\n\t\t\"allowJs\": true,\n\t\t\"checkJs\": true,\n\t\t\"esModuleInte"
  },
  {
    "path": "extensions/deckgl/vite.config.ts",
    "chars": 480,
    "preview": "import { defineConfig } from 'vite';\nimport { svelte } from '@sveltejs/vite-plugin-svelte';\n\nexport default defineConfig"
  },
  {
    "path": "extensions/pmtiles/CHANGELOG.md",
    "chars": 306,
    "preview": "# @svelte-maplibre-gl/pmtiles\n\n## 1.0.3\n\n### Patch Changes\n\n- Updated dependencies [6b3cd54]\n  - svelte-maplibre-gl@1.0."
  },
  {
    "path": "extensions/pmtiles/package.json",
    "chars": 1538,
    "preview": "{\n\t\"name\": \"@svelte-maplibre-gl/pmtiles\",\n\t\"version\": \"1.0.3\",\n\t\"license\": \"(MIT OR Apache-2.0)\",\n\t\"description\": \"PMTil"
  },
  {
    "path": "extensions/pmtiles/src/app.d.ts",
    "chars": 274,
    "preview": "// See https://svelte.dev/docs/kit/types#app.d.ts\n// for information about these interfaces\ndeclare global {\n\tnamespace "
  },
  {
    "path": "extensions/pmtiles/src/app.html",
    "chars": 286,
    "preview": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width,"
  },
  {
    "path": "extensions/pmtiles/src/lib/PMTilesProtocol.svelte",
    "chars": 1224,
    "preview": "<script lang=\"ts\">\n\timport { Protocol as MapLibreProtocol } from 'svelte-maplibre-gl';\n\timport { Protocol, type PMTiles "
  },
  {
    "path": "extensions/pmtiles/src/lib/index.ts",
    "chars": 71,
    "preview": "export { default as PMTilesProtocol } from './PMTilesProtocol.svelte';\n"
  },
  {
    "path": "extensions/pmtiles/svelte.config.js",
    "chars": 379,
    "preview": "import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';\n\n/** @type {import('@sveltejs/kit').Config} */\nconst conf"
  },
  {
    "path": "extensions/pmtiles/tsconfig.json",
    "chars": 517,
    "preview": "{\n\t\"extends\": \"./.svelte-kit/tsconfig.json\",\n\t\"compilerOptions\": {\n\t\t\"allowJs\": true,\n\t\t\"checkJs\": true,\n\t\t\"esModuleInte"
  },
  {
    "path": "extensions/pmtiles/vite.config.ts",
    "chars": 527,
    "preview": "import { defineConfig } from 'vite';\nimport { svelte } from '@sveltejs/vite-plugin-svelte';\n\nexport default defineConfig"
  },
  {
    "path": "extensions/terradraw/CHANGELOG.md",
    "chars": 308,
    "preview": "# @svelte-maplibre-gl/terradraw\n\n## 1.0.3\n\n### Patch Changes\n\n- Updated dependencies [6b3cd54]\n  - svelte-maplibre-gl@1."
  },
  {
    "path": "extensions/terradraw/package.json",
    "chars": 1644,
    "preview": "{\n\t\"name\": \"@svelte-maplibre-gl/terradraw\",\n\t\"version\": \"1.0.3\",\n\t\"license\": \"(MIT OR Apache-2.0)\",\n\t\"description\": \"Ter"
  },
  {
    "path": "extensions/terradraw/src/app.d.ts",
    "chars": 274,
    "preview": "// See https://svelte.dev/docs/kit/types#app.d.ts\n// for information about these interfaces\ndeclare global {\n\tnamespace "
  },
  {
    "path": "extensions/terradraw/src/app.html",
    "chars": 286,
    "preview": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width,"
  },
  {
    "path": "extensions/terradraw/src/lib/TerraDraw.svelte",
    "chars": 1846,
    "preview": "<script lang=\"ts\">\n\timport { TerraDraw as Draw } from 'terra-draw';\n\timport type { IdStrategy, TerraDrawEventListeners }"
  },
  {
    "path": "extensions/terradraw/src/lib/index.ts",
    "chars": 59,
    "preview": "export { default as TerraDraw } from './TerraDraw.svelte';\n"
  },
  {
    "path": "extensions/terradraw/svelte.config.js",
    "chars": 379,
    "preview": "import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';\n\n/** @type {import('@sveltejs/kit').Config} */\nconst conf"
  },
  {
    "path": "extensions/terradraw/tsconfig.json",
    "chars": 517,
    "preview": "{\n\t\"extends\": \"./.svelte-kit/tsconfig.json\",\n\t\"compilerOptions\": {\n\t\t\"allowJs\": true,\n\t\t\"checkJs\": true,\n\t\t\"esModuleInte"
  },
  {
    "path": "extensions/terradraw/vite.config.ts",
    "chars": 642,
    "preview": "import { defineConfig } from 'vite';\nimport { svelte } from '@sveltejs/vite-plugin-svelte';\n\nexport default defineConfig"
  },
  {
    "path": "package.json",
    "chars": 3089,
    "preview": "{\n\t\"name\": \"@svelte-maplibre-gl/docs\",\n\t\"version\": \"1.0.0\",\n\t\"private\": true,\n\t\"type\": \"module\",\n\t\"license\": \"(MIT OR Ap"
  },
  {
    "path": "playwright.config.ts",
    "chars": 179,
    "preview": "import { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n\twebServer: {\n\t\tcommand: 'npm run build "
  },
  {
    "path": "pnpm-workspace.yaml",
    "chars": 561,
    "preview": "packages:\n  - svelte-maplibre-gl\n  - extensions/*\n  - .\n\ncatalog:\n  '@deck.gl/core': ^9.2.6\n  '@deck.gl/layers': ^9.2.6\n"
  },
  {
    "path": "src/app.css",
    "chars": 4635,
    "preview": "@import 'tailwindcss';\n\n@custom-variant dark (&:where(.dark, .dark *));\n\n@config '../tailwind.config.ts';\n\n/*\n  The defa"
  },
  {
    "path": "src/app.d.ts",
    "chars": 274,
    "preview": "// See https://svelte.dev/docs/kit/types#app.d.ts\n// for information about these interfaces\ndeclare global {\n\tnamespace "
  },
  {
    "path": "src/app.html",
    "chars": 703,
    "preview": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<link rel=\"icon\" type=\"image/png\" href=\"%sveltekit"
  },
  {
    "path": "src/content/CodeBlock.svelte",
    "chars": 1205,
    "preview": "<script lang=\"ts\">\n\t// import { browser } from '$app/environment';\n\timport type { HighlighterCore } from 'shiki';\n\t// im"
  },
  {
    "path": "src/content/components/toc.ts",
    "chars": 2824,
    "preview": "import type { Toc } from '$lib/components/types';\n\nexport const toc: Toc = [\n\t{\n\t\ttitle: 'Map',\n\t\titems: {\n\t\t\t'/docs/com"
  },
  {
    "path": "src/content/docs/quickstart/Marker.svelte",
    "chars": 271,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, Marker } from 'svelte-maplibre-gl';\n</script>\n\n<MapLibre\n\tzoom={5}\n\tcenter={[142,"
  },
  {
    "path": "src/content/docs/quickstart/Simplest.svelte",
    "chars": 304,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre } from 'svelte-maplibre-gl';\n</script>\n\n<!-- Height must be set, otherwise the map"
  },
  {
    "path": "src/content/docs/quickstart/content.svelte.md",
    "chars": 1094,
    "preview": "---\ntitle: Quickstart\ndescription: Get started with svelte-maplibre-gl in just a few minutes.\n---\n\n<script lang=\"ts\">\n  "
  },
  {
    "path": "src/content/docs/toc.ts",
    "chars": 192,
    "preview": "import type { Toc } from '$lib/components/types';\n\nexport const toc: Toc = [\n\t{\n\t\ttitle: 'Overview',\n\t\titems: {\n\t\t\t'/doc"
  },
  {
    "path": "src/content/examples/3d-buildings/Buildings3D.svelte",
    "chars": 817,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, FillExtrusionLayer } from 'svelte-maplibre-gl';\n</script>\n\n<MapLibre\n\tclass=\"h-[5"
  },
  {
    "path": "src/content/examples/3d-buildings/content.svelte.md",
    "chars": 418,
    "preview": "---\ntitle: 3D Buildings\ndescription: Use extrusions to display buildings' height in 3D.\noriginal: https://maplibre.org/m"
  },
  {
    "path": "src/content/examples/3d-extrusion-floorplan/Floorplan.svelte",
    "chars": 1074,
    "preview": "<script lang=\"ts\">\n\timport {\n\t\tMapLibre,\n\t\tRasterTileSource,\n\t\tBackgroundLayer,\n\t\tRasterLayer,\n\t\tGeoJSONSource,\n\t\tFillEx"
  },
  {
    "path": "src/content/examples/3d-extrusion-floorplan/content.svelte.md",
    "chars": 442,
    "preview": "---\ntitle: 3D Floor Plan\ndescription: Create a 3D indoor map with the fill-extrude-height paint property.\noriginal: http"
  },
  {
    "path": "src/content/examples/animate-images/AnimateImages.svelte",
    "chars": 804,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, ImageSource, GlobeControl, RasterLayer } from 'svelte-maplibre-gl';\n\n\tconst FRAME"
  },
  {
    "path": "src/content/examples/animate-images/content.svelte.md",
    "chars": 440,
    "preview": "---\ntitle: Animate a series of images\ndescription: Use a series of image sources to create an animation.\norignal: https:"
  },
  {
    "path": "src/content/examples/basestyle/BaseStyle.svelte",
    "chars": 3387,
    "preview": "<script lang=\"ts\">\n\timport {\n\t\tHillshadeLayer,\n\t\tLight,\n\t\tLineLayer,\n\t\tMapLibre,\n\t\tProjection,\n\t\tImageLoader,\n\t\tRasterDE"
  },
  {
    "path": "src/content/examples/basestyle/content.svelte.md",
    "chars": 385,
    "preview": "---\ntitle: Change Base Style\ndescription: This library efficiently preserves dynamic user contents even when the base st"
  },
  {
    "path": "src/content/examples/canvas-source/Canvas.svelte",
    "chars": 1504,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, CanvasSource, GlobeControl, RasterLayer } from 'svelte-maplibre-gl';\n\timport { Ci"
  },
  {
    "path": "src/content/examples/canvas-source/Circle.ts",
    "chars": 662,
    "preview": "export class Circle {\n\tconstructor(\n\t\tpublic x: number,\n\t\tpublic y: number,\n\t\tpublic dx: number,\n\t\tpublic dy: number,\n\t\t"
  },
  {
    "path": "src/content/examples/canvas-source/content.svelte.md",
    "chars": 391,
    "preview": "---\ntitle: Canvas Source\ndescription: Add a canvas source to the map.\noriginal: https://maplibre.org/maplibre-gl-js/docs"
  },
  {
    "path": "src/content/examples/clusters/Clusters.svelte",
    "chars": 2170,
    "preview": "<script lang=\"ts\">\n\timport { CircleLayer, MapLibre, GeoJSONSource, SymbolLayer, GlobeControl } from 'svelte-maplibre-gl'"
  },
  {
    "path": "src/content/examples/clusters/content.svelte.md",
    "chars": 419,
    "preview": "---\ntitle: Clusters\ndescription: Use MapLibre's built-in functions to visualize points as clusters.\noriginal: https://ma"
  },
  {
    "path": "src/content/examples/color-relief/ColorRelief.svelte",
    "chars": 6052,
    "preview": "<script lang=\"ts\">\n\timport {\n\t\tHillshadeLayer,\n\t\tMapLibre,\n\t\tRasterDEMTileSource,\n\t\tTerrainControl,\n\t\tGlobeControl,\n\t\tLi"
  },
  {
    "path": "src/content/examples/color-relief/content.svelte.md",
    "chars": 391,
    "preview": "---\ntitle: Color Relief\ndescription: Render hypsometric tints using DEM sources\noriginal: https://nathanmolson.github.io"
  },
  {
    "path": "src/content/examples/complex/Complex.svelte",
    "chars": 7528,
    "preview": "<script lang=\"ts\">\n\timport maplibregl from 'maplibre-gl';\n\timport {\n\t\tMapLibre,\n\t\tRasterTileSource,\n\t\tRasterDEMTileSourc"
  },
  {
    "path": "src/content/examples/complex/content.svelte.md",
    "chars": 321,
    "preview": "---\ntitle: Complex\ndescription: A showcase of various reactive features.\n---\n\n<script lang=\"ts\">\n  import Demo from \"./C"
  },
  {
    "path": "src/content/examples/contour/Contour.svelte",
    "chars": 1935,
    "preview": "<script lang=\"ts\">\n\timport {\n\t\tHillshadeLayer,\n\t\tMapLibre,\n\t\tRasterDEMTileSource,\n\t\tLineLayer,\n\t\tSymbolLayer,\n\t\tTerrainC"
  },
  {
    "path": "src/content/examples/contour/content.svelte.md",
    "chars": 434,
    "preview": "---\ntitle: Contour Lines\ndescription: Render contour lines from a raster DEM source using maplibre-contour\noriginal: htt"
  },
  {
    "path": "src/content/examples/cursor/Cursor.svelte",
    "chars": 1331,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, GeoJSONSource, CircleLayer } from 'svelte-maplibre-gl';\n\timport type GeoJSON from"
  },
  {
    "path": "src/content/examples/cursor/content.svelte.md",
    "chars": 317,
    "preview": "---\ntitle: Change Cursor\ndescription: Change the cursor style on hover\n---\n\n<script lang=\"ts\">\n  import Demo from \"./Cur"
  },
  {
    "path": "src/content/examples/custom-control/CustomControl.svelte",
    "chars": 2974,
    "preview": "<script lang=\"ts\">\n\timport { HillshadeLayer, MapLibre, RasterDEMTileSource, Terrain, CustomControl } from 'svelte-maplib"
  },
  {
    "path": "src/content/examples/custom-control/MyControl.ts",
    "chars": 1984,
    "preview": "interface MyControlConstructorOptions {\n\ttoggleTerrain: () => boolean;\n\ttoggleHillshade: () => boolean;\n}\n\nclass MyContr"
  },
  {
    "path": "src/content/examples/custom-control/content.svelte.md",
    "chars": 364,
    "preview": "---\ntitle: Custom Control\ndescription: Easily create user-defined controls with a native look and feel.\n---\n\n<script lan"
  },
  {
    "path": "src/content/examples/custom-layer/CustomLayer.svelte",
    "chars": 6480,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, CustomLayer, GlobeControl, Projection } from 'svelte-maplibre-gl';\n\timport maplib"
  },
  {
    "path": "src/content/examples/custom-layer/content.svelte.md",
    "chars": 434,
    "preview": "---\ntitle: Custom Layer\ndescription: Use a custom layer to draw simple WebGL content on a globe.\noriginal: https://mapli"
  },
  {
    "path": "src/content/examples/custom-protocol/CustomProtocol.svelte",
    "chars": 1876,
    "preview": "<script lang=\"ts\">\n\timport {\n\t\tMapLibre,\n\t\tRasterTileSource,\n\t\tVectorTileSource,\n\t\tRasterLayer,\n\t\tLineLayer,\n\t\tFillLayer"
  },
  {
    "path": "src/content/examples/custom-protocol/content.svelte.md",
    "chars": 373,
    "preview": "---\ntitle: Custom Protocols\ndescription: Add a custom resource loading function to handle a custom URL scheme.\n---\n\n<scr"
  },
  {
    "path": "src/content/examples/deckgl-overlay/DeckGL.svelte",
    "chars": 1686,
    "preview": "<script lang=\"ts\">\n\timport { onMount } from 'svelte';\n\timport { MapLibre, FillExtrusionLayer } from 'svelte-maplibre-gl'"
  },
  {
    "path": "src/content/examples/deckgl-overlay/content.svelte.md",
    "chars": 379,
    "preview": "---\ntitle: deck.gl Overlay\ndescription: Interleaving deck.gl with MapLibre layers\noriginal: https://deck.gl/gallery/mapl"
  },
  {
    "path": "src/content/examples/dynamic-image/DynamicImage.svelte",
    "chars": 917,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, Image, GeoJSONSource, SymbolLayer } from 'svelte-maplibre-gl';\n\n\tconst size = 64;"
  },
  {
    "path": "src/content/examples/dynamic-image/content.svelte.md",
    "chars": 431,
    "preview": "---\ntitle: Dynamic Image\ndescription: Add an icon to the map that was generated at runtime.\noriginal: https://maplibre.o"
  },
  {
    "path": "src/content/examples/fullscreen/Fullscreen.svelte",
    "chars": 292,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, FullScreenControl } from 'svelte-maplibre-gl';\n</script>\n\n<MapLibre\n\tclass=\"h-[55"
  },
  {
    "path": "src/content/examples/fullscreen/content.svelte.md",
    "chars": 383,
    "preview": "---\ntitle: Fullscreen\ndescription: View a fullscreen map\noriginal: https://maplibre.org/maplibre-gl-js/docs/examples/ful"
  },
  {
    "path": "src/content/examples/geolocate/Geolocate.svelte",
    "chars": 843,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, GeolocateControl } from 'svelte-maplibre-gl';\n\n\tlet logString = $state('Press the"
  },
  {
    "path": "src/content/examples/geolocate/content.svelte.md",
    "chars": 381,
    "preview": "---\ntitle: Locate the User\ndescription: Locate the User\noriginal: https://maplibre.org/maplibre-gl-js/docs/examples/loca"
  },
  {
    "path": "src/content/examples/global-state/Plain.svelte",
    "chars": 1689,
    "preview": "<script lang=\"ts\">\n\timport { Label } from '$lib/components/ui/label';\n\timport { MapLibre, GeoJSONSource, CircleLayer, Sy"
  },
  {
    "path": "src/content/examples/global-state/content.svelte.md",
    "chars": 457,
    "preview": "---\ntitle: Global State\ndescription: Filter a layer symbols based on user input using setGlobalStateProperty().\noriginal"
  },
  {
    "path": "src/content/examples/globe-atmosphere/Globe.svelte",
    "chars": 1450,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, Projection, Sky, Light } from 'svelte-maplibre-gl';\n\n\tlet thetaDeg = $state(135);"
  },
  {
    "path": "src/content/examples/globe-atmosphere/content.svelte.md",
    "chars": 407,
    "preview": "---\ntitle: Globe with an atmosphere\ndescription: Display a globe with an atmosphere.\noriginal: https://maplibre.org/mapl"
  },
  {
    "path": "src/content/examples/hover-styles/HoverStyles.svelte",
    "chars": 1510,
    "preview": "<script lang=\"ts\">\n\timport { FillLayer, LineLayer, MapLibre, GeoJSONSource, FeatureState, Popup } from 'svelte-maplibre-"
  },
  {
    "path": "src/content/examples/hover-styles/content.svelte.md",
    "chars": 435,
    "preview": "---\ntitle: Hover Styles\ndescription: Use events and feature states to create a per feature hover effect.\noriginal: https"
  },
  {
    "path": "src/content/examples/image-loader/Images.svelte",
    "chars": 1920,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, ImageLoader, GeoJSONSource, SymbolLayer } from 'svelte-maplibre-gl';\n\timport type"
  },
  {
    "path": "src/content/examples/image-loader/content.svelte.md",
    "chars": 412,
    "preview": "---\ntitle: Load Images from URLs\ndescription: Utility for loading images from URLs\noriginal: https://maplibre.org/maplib"
  },
  {
    "path": "src/content/examples/limit-interaction/LimitInteraction.svelte",
    "chars": 3015,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre } from 'svelte-maplibre-gl';\n\n\timport { Checkbox } from '$lib/components/ui/checkb"
  },
  {
    "path": "src/content/examples/limit-interaction/content.svelte.md",
    "chars": 462,
    "preview": "---\ntitle: Limit Map Interactions\ndescription: Set the zoom/pitch range and toggle UI handlers on the map.\noriginal: htt"
  },
  {
    "path": "src/content/examples/marker-popup/MarkerAndPopup.svelte",
    "chars": 1488,
    "preview": "<script lang=\"ts\">\n\timport maplibregl from 'maplibre-gl';\n\timport { MapLibre, Marker, Popup } from 'svelte-maplibre-gl';"
  },
  {
    "path": "src/content/examples/marker-popup/content.svelte.md",
    "chars": 362,
    "preview": "---\ntitle: Marker and Popup\ndescription: Control marker and popup states using Svelte’s reactivity.\n---\n\n<script lang=\"t"
  },
  {
    "path": "src/content/examples/plain/Plain.svelte",
    "chars": 354,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, NavigationControl, ScaleControl, GlobeControl } from 'svelte-maplibre-gl';\n</scri"
  },
  {
    "path": "src/content/examples/plain/content.svelte.md",
    "chars": 323,
    "preview": "---\ntitle: Plain Map\ndescription: A minimal example showing only the base map.\n---\n\n<script lang=\"ts\">\n  import Demo fro"
  },
  {
    "path": "src/content/examples/pmtiles/PMTiles.svelte",
    "chars": 1199,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre } from 'svelte-maplibre-gl';\n\timport { PMTilesProtocol } from '@svelte-maplibre-gl"
  },
  {
    "path": "src/content/examples/pmtiles/content.svelte.md",
    "chars": 424,
    "preview": "---\ntitle: PMTiles Protocol\ndescription: Uses the PMTiles plugin and the custom protocol to present a map.\noriginal: htt"
  },
  {
    "path": "src/content/examples/query-features/Query.svelte",
    "chars": 2495,
    "preview": "<script lang=\"ts\">\n\timport {\n\t\tMapLibre,\n\t\tGeoJSONSource,\n\t\tCircleLayer,\n\t\tMarker,\n\t\tGlobeControl,\n\t\tQuerySourceFeatures"
  },
  {
    "path": "src/content/examples/query-features/content.svelte.md",
    "chars": 355,
    "preview": "---\ntitle: Query Features\ndescription: Query source and rendered features to place markers and display a list.\n---\n\n<scr"
  },
  {
    "path": "src/content/examples/side-by-side/SideBySide.svelte",
    "chars": 2462,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, Projection } from 'svelte-maplibre-gl';\n\n\timport { Label } from '$lib/components/"
  },
  {
    "path": "src/content/examples/side-by-side/content.svelte.md",
    "chars": 386,
    "preview": "---\ntitle: Side by Side\ndescription: Synchronize two maps.\noriginal: https://visgl.github.io/react-maplibre/examples/sid"
  },
  {
    "path": "src/content/examples/terradraw/TerraDraw.svelte",
    "chars": 2405,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, GlobeControl } from 'svelte-maplibre-gl';\n\timport { TerraDraw } from '@svelte-map"
  },
  {
    "path": "src/content/examples/terradraw/content.svelte.md",
    "chars": 382,
    "preview": "---\ntitle: Terra Draw\ndescription: Use Terra Draw to draw a geometry in various forms such as point, line or polygon on "
  },
  {
    "path": "src/content/examples/terrain/Terrain.svelte",
    "chars": 7206,
    "preview": "<script lang=\"ts\">\n\timport {\n\t\tHillshadeLayer,\n\t\tMapLibre,\n\t\tRasterDEMTileSource,\n\t\tSky,\n\t\tTerrain,\n\t\tTerrainControl,\n\t\t"
  },
  {
    "path": "src/content/examples/terrain/content.svelte.md",
    "chars": 419,
    "preview": "---\ntitle: 3D Terrain and Sky\ndescription: Show elevation in actual 3D with the sky.\noriginal: https://maplibre.org/mapl"
  },
  {
    "path": "src/content/examples/threejs-model/CustomLayer.svelte",
    "chars": 2738,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, CustomLayer, GlobeControl, Projection } from 'svelte-maplibre-gl';\n\timport maplib"
  },
  {
    "path": "src/content/examples/threejs-model/content.svelte.md",
    "chars": 448,
    "preview": "---\ntitle: 3D model with three.js\ndescription: Use a custom style layer with three.js to add a 3D model to the map.\norig"
  },
  {
    "path": "src/content/examples/toc.ts",
    "chars": 1792,
    "preview": "import type { Toc } from '$lib/components/types';\n\nexport const toc: Toc = [\n\t{\n\t\ttitle: 'Basic',\n\t\titems: {\n\t\t\t'/exampl"
  },
  {
    "path": "src/content/examples/video-on-a-map/Video.svelte",
    "chars": 1058,
    "preview": "<script lang=\"ts\">\n\timport { MapLibre, VideoSource, GlobeControl, RasterLayer } from 'svelte-maplibre-gl';\n\timport mapli"
  },
  {
    "path": "src/content/examples/video-on-a-map/content.svelte.md",
    "chars": 376,
    "preview": "---\ntitle: Video on a map\ndescription: Display a video.\noriginal: https://maplibre.org/maplibre-gl-js/docs/examples/vide"
  },
  {
    "path": "src/demo.spec.ts",
    "chars": 148,
    "preview": "import { describe, it, expect } from 'vitest';\n\ndescribe('sum test', () => {\n\tit('adds 1 + 2 to equal 3', () => {\n\t\texpe"
  },
  {
    "path": "src/lib/assets/fonts/LICENSE.txt",
    "chars": 4368,
    "preview": "Copyright (c) 2023 Vercel, in collaboration with basement.studio\n\nThis Font Software is licensed under the SIL Open Font"
  },
  {
    "path": "src/lib/assets/fonts/geist.css",
    "chars": 216,
    "preview": "@font-face {\n\tfont-family: 'Geist';\n\tsrc: url('./geist.woff2') format('woff2');\n\tfont-display: swap;\n}\n@font-face {\n\tfon"
  },
  {
    "path": "src/lib/assets/icons/GitHub.svelte",
    "chars": 2352,
    "preview": "<script lang=\"ts\">\n\timport type { SVGAttributes } from 'svelte/elements';\n\n\tlet { ...props }: SVGAttributes<SVGElement> "
  },
  {
    "path": "src/lib/components/Index.svelte",
    "chars": 790,
    "preview": "<script lang=\"ts\">\n\timport { page } from '$app/state';\n\timport type { Toc } from './types';\n\tlet { name, toc }: { name: "
  },
  {
    "path": "src/lib/components/types.ts",
    "chars": 73,
    "preview": "export type Toc = {\n\ttitle: string;\n\titems: Record<string, string>;\n}[];\n"
  },
  {
    "path": "src/lib/components/ui/badge/badge.svelte",
    "chars": 1750,
    "preview": "<script lang=\"ts\" module>\n\timport { type VariantProps, tv } from \"tailwind-variants\";\n\n\texport const badgeVariants = tv("
  },
  {
    "path": "src/lib/components/ui/badge/index.ts",
    "chars": 118,
    "preview": "export { default as Badge } from \"./badge.svelte\";\nexport { badgeVariants, type BadgeVariant } from \"./badge.svelte\";\n"
  },
  {
    "path": "src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte",
    "chars": 631,
    "preview": "<script lang=\"ts\">\n\timport EllipsisIcon from \"@lucide/svelte/icons/ellipsis\";\n\timport type { HTMLAttributes } from \"svel"
  },
  {
    "path": "src/lib/components/ui/breadcrumb/breadcrumb-item.svelte",
    "chars": 432,
    "preview": "<script lang=\"ts\">\n\timport type { HTMLLiAttributes } from \"svelte/elements\";\n\timport { cn, type WithElementRef } from \"$"
  },
  {
    "path": "src/lib/components/ui/breadcrumb/breadcrumb-link.svelte",
    "chars": 694,
    "preview": "<script lang=\"ts\">\n\timport type { HTMLAnchorAttributes } from \"svelte/elements\";\n\timport type { Snippet } from \"svelte\";"
  },
  {
    "path": "src/lib/components/ui/breadcrumb/breadcrumb-list.svelte",
    "chars": 495,
    "preview": "<script lang=\"ts\">\n\timport type { HTMLOlAttributes } from \"svelte/elements\";\n\timport { cn, type WithElementRef } from \"$"
  },
  {
    "path": "src/lib/components/ui/breadcrumb/breadcrumb-page.svelte",
    "chars": 500,
    "preview": "<script lang=\"ts\">\n\timport type { HTMLAttributes } from \"svelte/elements\";\n\timport { cn, type WithElementRef } from \"$li"
  },
  {
    "path": "src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte",
    "chars": 586,
    "preview": "<script lang=\"ts\">\n\timport ChevronRightIcon from \"@lucide/svelte/icons/chevron-right\";\n\timport { cn, type WithElementRef"
  },
  {
    "path": "src/lib/components/ui/breadcrumb/breadcrumb.svelte",
    "chars": 419,
    "preview": "<script lang=\"ts\">\n\timport type { WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLAttributes } from \"svelte/el"
  },
  {
    "path": "src/lib/components/ui/breadcrumb/index.ts",
    "chars": 592,
    "preview": "import Root from \"./breadcrumb.svelte\";\nimport Ellipsis from \"./breadcrumb-ellipsis.svelte\";\nimport Item from \"./breadcr"
  },
  {
    "path": "src/lib/components/ui/button/button.svelte",
    "chars": 2907,
    "preview": "<script lang=\"ts\" module>\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLAnchorAttributes,"
  },
  {
    "path": "src/lib/components/ui/button/index.ts",
    "chars": 260,
    "preview": "import Root, {\n\ttype ButtonProps,\n\ttype ButtonSize,\n\ttype ButtonVariant,\n\tbuttonVariants,\n} from \"./button.svelte\";\n\nexp"
  },
  {
    "path": "src/lib/components/ui/checkbox/checkbox.svelte",
    "chars": 1424,
    "preview": "<script lang=\"ts\">\n\timport { Checkbox as CheckboxPrimitive } from \"bits-ui\";\n\timport CheckIcon from \"@lucide/svelte/icon"
  },
  {
    "path": "src/lib/components/ui/checkbox/index.ts",
    "chars": 80,
    "preview": "import Root from \"./checkbox.svelte\";\nexport {\n\tRoot,\n\t//\n\tRoot as Checkbox,\n};\n"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte",
    "chars": 346,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\n\tlet {\n\t\tref = $bindable(null),\n\t\t"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte",
    "chars": 1437,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\timport CheckIcon from \"@lucide/sve"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte",
    "chars": 1305,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithoutChildrenOrChild } from \"$lib/utils.js\";\n\timport DropdownMenuPortal from \"./"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte",
    "chars": 561,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\timport { cn } from \"$lib/utils.js\""
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte",
    "chars": 276,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\n\tlet { ref = $bindable(null), ...r"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte",
    "chars": 1187,
    "preview": "<script lang=\"ts\">\n\timport { cn } from \"$lib/utils.js\";\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\""
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte",
    "chars": 524,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLAttributes } from \"svelt"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte",
    "chars": 214,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\n\tlet { ...restProps }: DropdownMen"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte",
    "chars": 335,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\n\tlet {\n\t\tref = $bindable(null),\n\t\t"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte",
    "chars": 1107,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\timport CircleIcon from \"@lucide/sv"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte",
    "chars": 405,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\timport { cn } from \"$lib/utils.js\""
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte",
    "chars": 477,
    "preview": "<script lang=\"ts\">\n\timport type { HTMLAttributes } from \"svelte/elements\";\n\timport { cn, type WithElementRef } from \"$li"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte",
    "chars": 882,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\timport { cn } from \"$lib/utils.js\""
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte",
    "chars": 1077,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\timport ChevronRightIcon from \"@luc"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte",
    "chars": 243,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\n\tlet { open = $bindable(false), .."
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte",
    "chars": 282,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\n\tlet { ref = $bindable(null), ...r"
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/dropdown-menu.svelte",
    "chars": 245,
    "preview": "<script lang=\"ts\">\n\timport { DropdownMenu as DropdownMenuPrimitive } from \"bits-ui\";\n\n\tlet { open = $bindable(false), .."
  },
  {
    "path": "src/lib/components/ui/dropdown-menu/index.ts",
    "chars": 1735,
    "preview": "import Root from \"./dropdown-menu.svelte\";\nimport Sub from \"./dropdown-menu-sub.svelte\";\nimport CheckboxGroup from \"./dr"
  },
  {
    "path": "src/lib/components/ui/label/index.ts",
    "chars": 75,
    "preview": "import Root from \"./label.svelte\";\n\nexport {\n\tRoot,\n\t//\n\tRoot as Label,\n};\n"
  },
  {
    "path": "src/lib/components/ui/label/label.svelte",
    "chars": 542,
    "preview": "<script lang=\"ts\">\n\timport { Label as LabelPrimitive } from \"bits-ui\";\n\timport { cn } from \"$lib/utils.js\";\n\n\tlet {\n\t\tre"
  },
  {
    "path": "src/lib/components/ui/radio-group/index.ts",
    "chars": 164,
    "preview": "import Root from \"./radio-group.svelte\";\nimport Item from \"./radio-group-item.svelte\";\n\nexport {\n\tRoot,\n\tItem,\n\t//\n\tRoot"
  },
  {
    "path": "src/lib/components/ui/radio-group/radio-group-item.svelte",
    "chars": 1161,
    "preview": "<script lang=\"ts\">\n\timport { RadioGroup as RadioGroupPrimitive } from \"bits-ui\";\n\timport CircleIcon from \"@lucide/svelte"
  },
  {
    "path": "src/lib/components/ui/radio-group/radio-group.svelte",
    "chars": 397,
    "preview": "<script lang=\"ts\">\n\timport { RadioGroup as RadioGroupPrimitive } from \"bits-ui\";\n\timport { cn } from \"$lib/utils.js\";\n\n\t"
  },
  {
    "path": "src/lib/components/ui/select/index.ts",
    "chars": 997,
    "preview": "import Root from \"./select.svelte\";\nimport Group from \"./select-group.svelte\";\nimport Label from \"./select-label.svelte\""
  },
  {
    "path": "src/lib/components/ui/select/select-content.svelte",
    "chars": 1900,
    "preview": "<script lang=\"ts\">\n\timport { Select as SelectPrimitive } from \"bits-ui\";\n\timport SelectPortal from \"./select-portal.svel"
  },
  {
    "path": "src/lib/components/ui/select/select-group-heading.svelte",
    "chars": 532,
    "preview": "<script lang=\"ts\">\n\timport { Select as SelectPrimitive } from \"bits-ui\";\n\timport { cn } from \"$lib/utils.js\";\n\timport ty"
  },
  {
    "path": "src/lib/components/ui/select/select-group.svelte",
    "chars": 245,
    "preview": "<script lang=\"ts\">\n\timport { Select as SelectPrimitive } from \"bits-ui\";\n\n\tlet { ref = $bindable(null), ...restProps }: "
  },
  {
    "path": "src/lib/components/ui/select/select-item.svelte",
    "chars": 1270,
    "preview": "<script lang=\"ts\">\n\timport CheckIcon from \"@lucide/svelte/icons/check\";\n\timport { Select as SelectPrimitive } from \"bits"
  },
  {
    "path": "src/lib/components/ui/select/select-label.svelte",
    "chars": 457,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLAttributes } from \"svelt"
  },
  {
    "path": "src/lib/components/ui/select/select-portal.svelte",
    "chars": 190,
    "preview": "<script lang=\"ts\">\n\timport { Select as SelectPrimitive } from \"bits-ui\";\n\n\tlet { ...restProps }: SelectPrimitive.PortalP"
  },
  {
    "path": "src/lib/components/ui/select/select-scroll-down-button.svelte",
    "chars": 614,
    "preview": "<script lang=\"ts\">\n\timport ChevronDownIcon from \"@lucide/svelte/icons/chevron-down\";\n\timport { Select as SelectPrimitive"
  },
  {
    "path": "src/lib/components/ui/select/select-scroll-up-button.svelte",
    "chars": 600,
    "preview": "<script lang=\"ts\">\n\timport ChevronUpIcon from \"@lucide/svelte/icons/chevron-up\";\n\timport { Select as SelectPrimitive } f"
  },
  {
    "path": "src/lib/components/ui/select/select-separator.svelte",
    "chars": 455,
    "preview": "<script lang=\"ts\">\n\timport type { Separator as SeparatorPrimitive } from \"bits-ui\";\n\timport { Separator } from \"$lib/com"
  },
  {
    "path": "src/lib/components/ui/select/select-trigger.svelte",
    "chars": 1454,
    "preview": "<script lang=\"ts\">\n\timport { Select as SelectPrimitive } from \"bits-ui\";\n\timport ChevronDownIcon from \"@lucide/svelte/ic"
  },
  {
    "path": "src/lib/components/ui/select/select.svelte",
    "chars": 277,
    "preview": "<script lang=\"ts\">\n\timport { Select as SelectPrimitive } from \"bits-ui\";\n\n\tlet {\n\t\topen = $bindable(false),\n\t\tvalue = $b"
  },
  {
    "path": "src/lib/components/ui/separator/index.ts",
    "chars": 83,
    "preview": "import Root from \"./separator.svelte\";\n\nexport {\n\tRoot,\n\t//\n\tRoot as Separator,\n};\n"
  },
  {
    "path": "src/lib/components/ui/separator/separator.svelte",
    "chars": 547,
    "preview": "<script lang=\"ts\">\n\timport { Separator as SeparatorPrimitive } from \"bits-ui\";\n\timport { cn } from \"$lib/utils.js\";\n\n\tle"
  },
  {
    "path": "src/lib/components/ui/slider/index.ts",
    "chars": 77,
    "preview": "import Root from \"./slider.svelte\";\n\nexport {\n\tRoot,\n\t//\n\tRoot as Slider,\n};\n"
  },
  {
    "path": "src/lib/components/ui/slider/slider.svelte",
    "chars": 1775,
    "preview": "<script lang=\"ts\">\n\timport { Slider as SliderPrimitive } from \"bits-ui\";\n\timport { cn, type WithoutChildrenOrChild } fro"
  },
  {
    "path": "src/lib/components/ui/switch/index.ts",
    "chars": 77,
    "preview": "import Root from \"./switch.svelte\";\n\nexport {\n\tRoot,\n\t//\n\tRoot as Switch,\n};\n"
  },
  {
    "path": "src/lib/components/ui/switch/switch.svelte",
    "chars": 1160,
    "preview": "<script lang=\"ts\">\n\timport { Switch as SwitchPrimitive } from \"bits-ui\";\n\timport { cn, type WithoutChildrenOrChild } fro"
  },
  {
    "path": "src/lib/components/ui/table/index.ts",
    "chars": 574,
    "preview": "import Root from \"./table.svelte\";\nimport Body from \"./table-body.svelte\";\nimport Caption from \"./table-caption.svelte\";"
  },
  {
    "path": "src/lib/components/ui/table/table-body.svelte",
    "chars": 448,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLAttributes } from \"svelt"
  },
  {
    "path": "src/lib/components/ui/table/table-caption.svelte",
    "chars": 451,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLAttributes } from \"svelt"
  },
  {
    "path": "src/lib/components/ui/table/table-cell.svelte",
    "chars": 482,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLTdAttributes } from \"sve"
  },
  {
    "path": "src/lib/components/ui/table/table-footer.svelte",
    "chars": 479,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLAttributes } from \"svelt"
  },
  {
    "path": "src/lib/components/ui/table/table-head.svelte",
    "chars": 527,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLThAttributes } from \"sve"
  },
  {
    "path": "src/lib/components/ui/table/table-header.svelte",
    "chars": 439,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLAttributes } from \"svelt"
  },
  {
    "path": "src/lib/components/ui/table/table-row.svelte",
    "chars": 528,
    "preview": "<script lang=\"ts\">\n\timport { cn, type WithElementRef } from \"$lib/utils.js\";\n\timport type { HTMLAttributes } from \"svelt"
  }
]

// ... and 94 more files (download for full content)

About this extraction

This page contains the full source code of the MIERUNE/svelte-maplibre-gl GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 294 files (317.6 KB), approximately 104.3k tokens, and a symbol index with 48 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!