├── .changeset ├── README.md └── config.json ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── 1-documentation_change.yml │ ├── 2-feature_request.yml │ ├── 3-bug_report.yml │ └── config.yml ├── reproduire │ └── needs-reproduction.md └── workflows │ ├── build-preview.yml │ ├── ci.yml │ ├── deploy-preview.yml │ ├── deploy-prod.yml │ ├── preview-release.yml │ ├── release.yml │ ├── reproduire-close.yml │ └── reproduire.yml ├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── packages └── paneforge │ ├── .eslintignore │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .npmrc │ ├── .prettierignore │ ├── .prettierrc │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── playwright.config.ts │ ├── pnpm-lock.yaml │ ├── postcss.config.cjs │ ├── src │ ├── app.d.ts │ ├── app.html │ ├── app.pcss │ ├── index.test.ts │ └── lib │ │ ├── components │ │ ├── ctx.ts │ │ ├── index.ts │ │ ├── pane-group.svelte │ │ ├── pane-group.ts │ │ ├── pane-resizer.svelte │ │ ├── pane-resizer.ts │ │ ├── pane.svelte │ │ └── types.ts │ │ ├── index.ts │ │ └── internal │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── paneforge.ts │ │ ├── types.ts │ │ └── utils │ │ ├── adjust-layout.ts │ │ ├── aria.ts │ │ ├── assert.ts │ │ ├── chain.ts │ │ ├── compare.ts │ │ ├── event.ts │ │ ├── id.ts │ │ ├── index.ts │ │ ├── is.ts │ │ ├── lifecycle.ts │ │ ├── object.ts │ │ ├── resize.ts │ │ ├── storage.ts │ │ ├── store.ts │ │ └── style.ts │ ├── svelte.config.js │ ├── tailwind.config.cjs │ ├── tests │ └── test.ts │ ├── tsconfig.json │ └── vite.config.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── sites └── docs ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── components.json ├── content ├── components │ ├── pane-group.md │ ├── pane-resizer.md │ └── pane.md ├── examples │ ├── collapsible-panes.md │ ├── conditional-panes.md │ ├── horizontal-groups.md │ ├── nested-groups.md │ ├── overflowing-panes.md │ ├── persistent-layouts.md │ └── vertical-groups.md ├── getting-started.md ├── index.md └── styling.md ├── contentlayer.config.js ├── mdsx.config.js ├── package.json ├── pnpm-lock.yaml ├── postcss.config.cjs ├── src ├── app.d.ts ├── app.html ├── index.test.ts ├── lib │ ├── components │ │ ├── callout.svelte │ │ ├── copy-code-button.svelte │ │ ├── demos │ │ │ ├── collapsible-demo.svelte │ │ │ ├── conditional-demo.svelte │ │ │ ├── cookie-demo.svelte │ │ │ ├── horizontal-demo.svelte │ │ │ ├── index.ts │ │ │ ├── nested-groups-demo.svelte │ │ │ ├── overflow-demo.svelte │ │ │ ├── storage-demo.svelte │ │ │ └── vertical-demo.svelte │ │ ├── dev │ │ │ └── tw-indicator.svelte │ │ ├── feature-card.svelte │ │ ├── icon-grid.svelte │ │ ├── index.ts │ │ ├── layout │ │ │ ├── footer │ │ │ │ ├── footer-icons.svelte │ │ │ │ └── footer.svelte │ │ │ ├── index.ts │ │ │ ├── mobile-nav │ │ │ │ ├── mobile-nav-item.svelte │ │ │ │ ├── mobile-nav-link.svelte │ │ │ │ └── mobile-nav.svelte │ │ │ ├── navbar │ │ │ │ ├── index.ts │ │ │ │ ├── navbar-icons.svelte │ │ │ │ ├── navbar-logo.svelte │ │ │ │ ├── navbar-nav.svelte │ │ │ │ ├── navbar.svelte │ │ │ │ └── theme-dropdown.svelte │ │ │ ├── page-header │ │ │ │ ├── index.ts │ │ │ │ ├── page-header-description.svelte │ │ │ │ ├── page-header-heading.svelte │ │ │ │ ├── page-header-tagline.svelte │ │ │ │ └── page-header.svelte │ │ │ ├── sidebar │ │ │ │ ├── index.ts │ │ │ │ ├── sidebar-nav-item.svelte │ │ │ │ ├── sidebar-nav.svelte │ │ │ │ └── sidebar.svelte │ │ │ └── toc │ │ │ │ ├── index.ts │ │ │ │ ├── table-of-contents.svelte │ │ │ │ └── tree.svelte │ │ ├── loading-card.svelte │ │ ├── logos │ │ │ ├── index.ts │ │ │ ├── paneforge-dark.svelte │ │ │ ├── paneforge-light.svelte │ │ │ ├── svecosystem-dark.svelte │ │ │ └── svecosystem-light.svelte │ │ ├── markdown │ │ │ ├── a.svelte │ │ │ ├── blockquote.svelte │ │ │ ├── blueprint.svelte │ │ │ ├── code.svelte │ │ │ ├── h1.svelte │ │ │ ├── h2.svelte │ │ │ ├── h3.svelte │ │ │ ├── h4.svelte │ │ │ ├── h5.svelte │ │ │ ├── h6.svelte │ │ │ ├── hr.svelte │ │ │ ├── img.svelte │ │ │ ├── index.ts │ │ │ ├── li.svelte │ │ │ ├── ol.svelte │ │ │ ├── p.svelte │ │ │ ├── pre.svelte │ │ │ ├── table.svelte │ │ │ ├── td.svelte │ │ │ ├── th.svelte │ │ │ ├── tr.svelte │ │ │ └── ul.svelte │ │ ├── metadata.svelte │ │ ├── step.svelte │ │ ├── steps.svelte │ │ ├── tabs │ │ │ ├── index.ts │ │ │ ├── tabs-item.svelte │ │ │ └── tabs.svelte │ │ ├── ui │ │ │ ├── alert │ │ │ │ ├── alert-description.svelte │ │ │ │ ├── alert-title.svelte │ │ │ │ ├── alert.svelte │ │ │ │ └── index.ts │ │ │ ├── button │ │ │ │ ├── button.svelte │ │ │ │ └── index.ts │ │ │ ├── card │ │ │ │ ├── card-content.svelte │ │ │ │ ├── card-description.svelte │ │ │ │ ├── card-footer.svelte │ │ │ │ ├── card-header.svelte │ │ │ │ ├── card-title.svelte │ │ │ │ ├── card.svelte │ │ │ │ └── index.ts │ │ │ ├── checkbox │ │ │ │ ├── checkbox.svelte │ │ │ │ └── index.ts │ │ │ ├── collapsible │ │ │ │ ├── collapsible-content.svelte │ │ │ │ └── index.ts │ │ │ ├── dropdown-menu │ │ │ │ ├── dropdown-menu-checkbox-item.svelte │ │ │ │ ├── dropdown-menu-content.svelte │ │ │ │ ├── dropdown-menu-item.svelte │ │ │ │ ├── dropdown-menu-label.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 │ │ │ │ └── index.ts │ │ │ ├── input │ │ │ │ ├── index.ts │ │ │ │ └── input.svelte │ │ │ ├── label │ │ │ │ ├── index.ts │ │ │ │ └── label.svelte │ │ │ ├── radio-group │ │ │ │ ├── index.ts │ │ │ │ ├── radio-group-item.svelte │ │ │ │ └── radio-group.svelte │ │ │ ├── select │ │ │ │ ├── index.ts │ │ │ │ ├── select-content.svelte │ │ │ │ ├── select-item.svelte │ │ │ │ ├── select-label.svelte │ │ │ │ ├── select-separator.svelte │ │ │ │ └── select-trigger.svelte │ │ │ ├── separator │ │ │ │ ├── index.ts │ │ │ │ └── separator.svelte │ │ │ ├── skeleton │ │ │ │ ├── index.ts │ │ │ │ └── skeleton.svelte │ │ │ ├── slider │ │ │ │ ├── index.ts │ │ │ │ └── slider.svelte │ │ │ ├── sonner │ │ │ │ ├── index.ts │ │ │ │ └── sonner.svelte │ │ │ ├── switch │ │ │ │ ├── index.ts │ │ │ │ └── switch.svelte │ │ │ ├── tabs │ │ │ │ ├── index.ts │ │ │ │ ├── tabs-content.svelte │ │ │ │ ├── tabs-list.svelte │ │ │ │ └── tabs-trigger.svelte │ │ │ ├── textarea │ │ │ │ ├── index.ts │ │ │ │ └── textarea.svelte │ │ │ └── toggle │ │ │ │ ├── index.ts │ │ │ │ └── toggle.svelte │ │ └── view-example-code.svelte │ ├── config │ │ ├── index.ts │ │ ├── navigation.ts │ │ └── site.ts │ ├── icons │ │ ├── github-icon.svelte │ │ ├── index.ts │ │ ├── markdown-icon.svelte │ │ ├── shadcn-icon.svelte │ │ └── xcom-icon.svelte │ ├── index.ts │ ├── styles │ │ ├── app.pcss │ │ ├── markdown.pcss │ │ └── themes │ │ │ ├── tokyo-night-light.json │ │ │ └── tokyo-night-storm.json │ └── utils │ │ ├── browser.ts │ │ ├── contextify.ts │ │ ├── copy-code.ts │ │ ├── docs.ts │ │ ├── index.ts │ │ └── styles.ts └── routes │ ├── +layout.svelte │ ├── +page.svelte │ ├── +page.ts │ ├── docs │ ├── +layout.svelte │ ├── +page.svelte │ ├── +page.ts │ └── [...slug] │ │ ├── +page.server.ts │ │ ├── +page.svelte │ │ └── +page.ts │ └── repro │ └── +page.ts ├── static ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── apple-touch-icon.png ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── logo-dark.svg ├── logo-light.svg ├── og.png └── site.webmanifest ├── svelte.config.js ├── tailwind.config.js ├── tsconfig.json └── vite.config.ts /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", 3 | "changelog": [ 4 | "@svitejs/changesets-changelog-github-compact", 5 | { "repo": "svecosystem/paneforge" } 6 | ], 7 | "commit": false, 8 | "fixed": [], 9 | "linked": [], 10 | "access": "public", 11 | "baseBranch": "main", 12 | "updateInternalDependencies": "patch", 13 | "ignore": ["docs"] 14 | } 15 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [huntabyte] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: huntabyte 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-documentation_change.yml: -------------------------------------------------------------------------------- 1 | name: Report Docs Issue 2 | description: Suggest an addition or modification to the documentation 3 | labels: ["documentation"] 4 | body: 5 | - type: dropdown 6 | attributes: 7 | label: Change Type 8 | description: What type of change are you proposing? 9 | options: 10 | - Addition 11 | - Correction 12 | - Removal 13 | - Cleanup (formatting, typos, etc.) 14 | validations: 15 | required: true 16 | 17 | - type: textarea 18 | attributes: 19 | label: Proposed Changes 20 | description: Describe the proposed changes and why they are necessary 21 | validations: 22 | required: true 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature_request.yml: -------------------------------------------------------------------------------- 1 | name: 🛠️ Request New Feature 2 | description: Let us know what you would like to see added. 3 | labels: ["enhancement"] 4 | body: 5 | - type: textarea 6 | id: description 7 | attributes: 8 | label: Describe the feature in detail (code, mocks, or screenshots encouraged) 9 | validations: 10 | required: true 11 | - type: dropdown 12 | id: category 13 | attributes: 14 | label: What type of pull request would this be? 15 | options: 16 | - "New Feature" 17 | - "Enhancement" 18 | - "Guide" 19 | - "Docs" 20 | - "Other" 21 | - type: textarea 22 | id: references 23 | attributes: 24 | label: Provide relevant links or additional information. 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3-bug_report.yml: -------------------------------------------------------------------------------- 1 | name: "🐛 Bug report" 2 | description: Report an issue with paneforge 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: | 7 | ### Thanks for taking the time to create an issue! Please search open/closed issues before submitting, as the issue may have already been reported/addressed. 8 | - type: markdown 9 | attributes: 10 | value: | 11 | #### If you aren't sure if something is a bug or not, please do not create an issue, instead ask in one of the following channels: 12 | - [Discussions](https://github.com/huntabyte/paneforge/discussions/new?category=help) 13 | - [Discord](https://discord.gg/FKR4YhFbvB) 14 | - type: textarea 15 | id: bug-description 16 | attributes: 17 | label: Describe the bug 18 | description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us how in the description. Thanks! 19 | placeholder: Bug description 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: reproduction 24 | attributes: 25 | label: Reproduction 26 | description: | 27 | Please provide a link to a repo or Stackblitz that can reproduce the problem you ran into. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "needs reproduction" label. If no reproduction is provided within a reasonable time-frame, the issue will be closed. 28 | placeholder: Reproduction 29 | validations: 30 | required: true 31 | - type: textarea 32 | id: logs 33 | attributes: 34 | label: Logs 35 | description: "Please include browser console and server logs around the time this bug occurred. Optional if provided reproduction. Please try not to insert an image but copy paste the log text." 36 | render: bash 37 | - type: textarea 38 | id: system-info 39 | attributes: 40 | label: System Info 41 | description: Output of `npx envinfo --system --npmPackages svelte,paneforge,@sveltejs/kit --binaries --browsers` 42 | render: bash 43 | placeholder: System, Binaries, Browsers 44 | validations: 45 | required: true 46 | - type: dropdown 47 | id: severity 48 | attributes: 49 | label: Severity 50 | description: Select the severity of this issue 51 | options: 52 | - annoyance 53 | - blocking an upgrade 54 | - blocking all usage of PaneForge 55 | validations: 56 | required: true 57 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Get Help 4 | url: https://github.com/huntabyte/formsnap/discussions/new?category=help 5 | about: If you can't get something to work the way you expect, open a question in our discussion forums. 6 | - name: Discord 7 | url: https://hbyt.us/discord 8 | about: If you need to have a back-and-forth conversation, join the Discord server. 9 | -------------------------------------------------------------------------------- /.github/reproduire/needs-reproduction.md: -------------------------------------------------------------------------------- 1 | Please provide a [reproduction](https://bits-ui.com/repro). 2 | 3 |
4 | More info 5 | 6 | ### Why do I need to provide a reproduction? 7 | 8 | This project is maintained by a very small team, and we simply don't have the bandwidth to investigate issues that we can't easily replicate. Reproductions enable us to fix issues faster and more efficiently. If you care about getting your issue resolved, providing a reproduction is the best way to do that. 9 | 10 | ### I've provided a reproduction - what happens now? 11 | 12 | Once a reproduction is provided, we'll remove the `needs reproduction` label and review the issue to determine how to resolve it. If we can confirm it's a bug, we'll label it as such and prioritize it based on its severity. 13 | 14 | If `needs reproduction` labeled issues don't receive any activity (e.g., a comment with a reproduction link), they'll be closed. Feel free to comment with a reproduction at any time and the issue will be reopened. 15 | 16 | ### How can I create a reproduction? 17 | 18 | You can use [this template](https://bits-ui.com/repro) to create a minimal reproduction. You can also link to a GitHub repository with the reproduction. 19 | 20 | Please ensure that the reproduction is as **minimal** as possible. If there is a ton of custom logic in your reproduction, it is difficult to determine if the issue is with your code or with the library. The more minimal the reproduction, the more likely it is that we'll be able to assist. 21 | 22 | You might also find these other articles interesting and/or helpful: 23 | 24 | - [The Importance of Reproductions](https://antfu.me/posts/why-reproductions-are-required) 25 | - [How to Generate a Minimal, Complete, and Verifiable Example](https://stackoverflow.com/help/mcve) 26 | 27 |
28 | -------------------------------------------------------------------------------- /.github/workflows/build-preview.yml: -------------------------------------------------------------------------------- 1 | name: Build Preview Deployment 2 | 3 | # cancel in-progress runs on new commits to same PR (github.event.number) 4 | concurrency: 5 | group: ${{ github.workflow }}-${{ github.event.number || github.sha }} 6 | cancel-in-progress: true 7 | 8 | on: 9 | pull_request: 10 | types: [opened, synchronize] 11 | 12 | jobs: 13 | build-preview: 14 | runs-on: macos-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: pnpm/action-setup@v4 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: 20 21 | cache: pnpm 22 | 23 | - name: Install dependencies 24 | run: pnpm install 25 | 26 | - name: Build site 27 | run: pnpm build 28 | 29 | - name: Upload build artifact 30 | uses: actions/upload-artifact@v4 31 | with: 32 | name: preview-build 33 | path: docs/.svelte-kit/cloudflare 34 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - next 8 | paths-ignore: 9 | - ".changeset/**" 10 | - README.md 11 | - ".vscode/**" 12 | - CHANGELOG.md 13 | pull_request: 14 | paths-ignore: 15 | - ".changeset/**" 16 | - README.md 17 | - ".vscode/**" 18 | - CHANGELOG.md 19 | 20 | concurrency: 21 | group: ${{ github.workflow }}-${{ github.event.number || github.sha }} 22 | cancel-in-progress: true 23 | 24 | jobs: 25 | Check: 26 | name: Run svelte-check 27 | runs-on: macos-latest 28 | steps: 29 | - uses: actions/checkout@v4 30 | - uses: pnpm/action-setup@v4 31 | - uses: actions/setup-node@v4 32 | with: 33 | node-version: 20 34 | cache: pnpm 35 | 36 | - name: Install dependencies 37 | run: pnpm install 38 | 39 | - name: Run svelte-check 40 | run: pnpm check 41 | 42 | Lint: 43 | runs-on: macos-latest 44 | name: Lint 45 | steps: 46 | - uses: actions/checkout@v4 47 | - uses: pnpm/action-setup@v4 48 | - uses: actions/setup-node@v4 49 | with: 50 | node-version: 20 51 | cache: pnpm 52 | 53 | - name: Install dependencies 54 | run: pnpm install 55 | 56 | - run: pnpm lint 57 | -------------------------------------------------------------------------------- /.github/workflows/deploy-preview.yml: -------------------------------------------------------------------------------- 1 | name: Upload Preview Deployment 2 | 3 | on: 4 | workflow_run: 5 | workflows: [Build Preview Deployment] 6 | types: 7 | - completed 8 | 9 | permissions: 10 | actions: read 11 | deployments: write 12 | contents: read 13 | pull-requests: write 14 | 15 | jobs: 16 | deploy-preview: 17 | runs-on: macos-latest 18 | if: ${{ github.event.workflow_run.conclusion == 'success' }} 19 | steps: 20 | - name: Download build artifact 21 | uses: actions/download-artifact@v4 22 | id: preview-build-artifact 23 | with: 24 | name: preview-build 25 | path: build 26 | github-token: ${{ secrets.GITHUB_TOKEN }} 27 | run-id: ${{ github.event.workflow_run.id }} 28 | 29 | - name: Deploy to Cloudflare Pages 30 | uses: AdrianGonz97/refined-cf-pages-action@v1 31 | with: 32 | apiToken: ${{ secrets.CF_API_TOKEN }} 33 | accountId: ${{ secrets.CF_ACCOUNT_ID }} 34 | githubToken: ${{ secrets.GITHUB_TOKEN }} 35 | projectName: paneforge 36 | deploymentName: Preview 37 | directory: ${{ steps.preview-build-artifact.outputs.download-path }} 38 | -------------------------------------------------------------------------------- /.github/workflows/deploy-prod.yml: -------------------------------------------------------------------------------- 1 | name: Production Deployment 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths: 7 | - docs/** 8 | - packages/paneforge/** 9 | workflow_dispatch: 10 | 11 | jobs: 12 | deploy-production: 13 | runs-on: macos-latest 14 | permissions: 15 | contents: read 16 | deployments: write 17 | name: Deploy Production Site to Cloudflare Pages 18 | steps: 19 | - uses: actions/checkout@v4 20 | - uses: pnpm/action-setup@v4 21 | - uses: actions/setup-node@v4 22 | with: 23 | node-version: 20 24 | cache: pnpm 25 | 26 | - name: Install dependencies 27 | run: pnpm install 28 | 29 | - name: Build site 30 | run: pnpm build 31 | 32 | - name: Deploy to Cloudflare Pages 33 | uses: AdrianGonz97/refined-cf-pages-action@v1 34 | with: 35 | apiToken: ${{ secrets.CF_API_TOKEN }} 36 | accountId: ${{ secrets.CF_ACCOUNT_ID }} 37 | githubToken: ${{ secrets.GITHUB_TOKEN }} 38 | projectName: paneforge 39 | directory: ./.svelte-kit/cloudflare 40 | workingDirectory: docs 41 | deploymentName: Production 42 | -------------------------------------------------------------------------------- /.github/workflows/preview-release.yml: -------------------------------------------------------------------------------- 1 | name: Publish Preview Release 2 | on: 3 | pull_request: 4 | types: [ready_for_review, synchronize, opened, labeled] 5 | paths: [packages/**] 6 | 7 | jobs: 8 | preview-release: 9 | if: github.repository == 'svecosystem/paneforge' && contains(github.event.pull_request.labels.*.name, 'publish:preview') 10 | timeout-minutes: 5 11 | runs-on: macos-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: pnpm/action-setup@v4 15 | - uses: actions/setup-node@v4 16 | with: 17 | node-version: 20 18 | cache: pnpm 19 | 20 | - name: install dependencies 21 | run: pnpm install 22 | 23 | - name: build 24 | run: pnpm build:packages 25 | 26 | - name: publish preview 27 | run: | 28 | pnpx pkg-pr-new@0.0 publish --pnpm --compact './packages/*' 29 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - next 8 | 9 | concurrency: ${{ github.workflow }}-${{ github.ref }} 10 | 11 | jobs: 12 | release: 13 | permissions: 14 | contents: write # to create release (changesets/action) 15 | pull-requests: write # to create pull request (changesets/action) 16 | name: Release 17 | runs-on: macos-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | - uses: pnpm/action-setup@v4 23 | - uses: actions/setup-node@v4 24 | with: 25 | node-version: 20 26 | cache: pnpm 27 | 28 | - name: Install dependencies 29 | run: pnpm install 30 | 31 | - name: Create Release Pull Request or Publish to npm 32 | id: changesets 33 | uses: changesets/action@v1 34 | with: 35 | publish: pnpm ci:publish 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 38 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 39 | -------------------------------------------------------------------------------- /.github/workflows/reproduire-close.yml: -------------------------------------------------------------------------------- 1 | name: Close incomplete issues 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: "30 1 * * *" # run every day 6 | 7 | permissions: 8 | issues: write 9 | 10 | jobs: 11 | stale: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 15 | with: 16 | days-before-stale: -1 # Issues and PR will never be flagged stale automatically. 17 | stale-issue-label: needs reproduction # Label that flags an issue as stale. 18 | only-labels: needs reproduction # Only process these issues 19 | days-before-issue-close: 7 20 | ignore-updates: true 21 | remove-stale-when-updated: false 22 | close-issue-message: This issue was closed because it was open for 7 days without a reproduction. 23 | close-issue-label: closed-by-bot 24 | -------------------------------------------------------------------------------- /.github/workflows/reproduire.yml: -------------------------------------------------------------------------------- 1 | name: Reproduire 2 | on: 3 | issues: 4 | types: [labeled] 5 | 6 | permissions: 7 | issues: write 8 | 9 | jobs: 10 | reproduire: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 14 | - uses: Hebilicious/reproduire@4b686ae9cbb72dad60f001d278b6e3b2ce40a9ac # v0.0.9-mp 15 | with: 16 | label: needs reproduction 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | dist 7 | 8 | # Logs 9 | logs 10 | *.log 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | lerna-debug.log* 15 | .pnpm-debug.log* 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 19 | 20 | # Runtime data 21 | pids 22 | *.pid 23 | *.seed 24 | *.pid.lock 25 | 26 | # Directory for instrumented libs generated by jscoverage/JSCover 27 | lib-cov 28 | 29 | # Coverage directory used by tools like istanbul 30 | coverage 31 | *.lcov 32 | 33 | # nyc test coverage 34 | .nyc_output 35 | 36 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 37 | .grunt 38 | 39 | # Bower dependency directory (https://bower.io/) 40 | bower_components 41 | 42 | # node-waf configuration 43 | .lock-wscript 44 | 45 | # Compiled binary addons (https://nodejs.org/api/addons.html) 46 | build/Release 47 | 48 | # Dependency directories 49 | node_modules/ 50 | jspm_packages/ 51 | 52 | # Snowpack dependency directory (https://snowpack.dev/) 53 | web_modules/ 54 | 55 | # TypeScript cache 56 | *.tsbuildinfo 57 | 58 | # Optional npm cache directory 59 | .npm 60 | 61 | # Optional eslint cache 62 | .eslintcache 63 | 64 | # Output of 'npm pack' 65 | *.tgz 66 | 67 | # Yarn Integrity file 68 | .yarn-integrity 69 | 70 | # dotenv environment variable files 71 | .env 72 | .env.development.local 73 | .env.test.local 74 | .env.production.local 75 | .env.local 76 | 77 | sites/docs/.vercel 78 | packages/paneforge/doc 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Hunter Johnston 4 | Copyright (c) 2023 Brian Vaughn 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "private": true, 4 | "version": "0.0.0", 5 | "description": "Monorepo for Paneforge.", 6 | "author": "Hunter Johnston ", 7 | "main": "index.js", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/svecosystem/paneforge" 11 | }, 12 | "scripts": { 13 | "test": "pnpm -r test", 14 | "dev": "pnpm sync && pnpm --parallel dev", 15 | "build": "pnpm -r build", 16 | "build:packages": "pnpm -F \"./packages/**\" --parallel build", 17 | "build:content": "pnpm -F \"./sites/**\" --parallel build:content", 18 | "ci:publish": "pnpm build:packages && changeset publish", 19 | "lint": "pnpm -r lint", 20 | "format": "pnpm -r format", 21 | "check": "pnpm -r check", 22 | "sync": "pnpm -r sync", 23 | "postinstall": "pnpm -r sync" 24 | }, 25 | "license": "MIT", 26 | "devDependencies": { 27 | "@changesets/cli": "^2.26.2", 28 | "@svitejs/changesets-changelog-github-compact": "^1.1.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/paneforge/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | dist 15 | /dist -------------------------------------------------------------------------------- /packages/paneforge/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type { import("eslint").Linter.Config } */ 2 | module.exports = { 3 | root: true, 4 | extends: [ 5 | "eslint:recommended", 6 | "plugin:@typescript-eslint/recommended", 7 | "plugin:svelte/recommended", 8 | "prettier", 9 | ], 10 | parser: "@typescript-eslint/parser", 11 | plugins: ["@typescript-eslint"], 12 | parserOptions: { 13 | sourceType: "module", 14 | ecmaVersion: "latest", 15 | extraFileExtensions: [".svelte"], 16 | }, 17 | env: { 18 | browser: true, 19 | es2024: true, 20 | node: true, 21 | }, 22 | globals: { $$Generic: "readable", NodeJS: true }, 23 | rules: { 24 | "no-console": "warn", 25 | "@typescript-eslint/no-unused-vars": [ 26 | "warn", 27 | { 28 | argsIgnorePattern: "^_", 29 | varsIgnorePattern: "^_", 30 | }, 31 | ], 32 | "svelte/no-target-blank": "off", 33 | "svelte/no-immutable-reactive-statements": "error", 34 | "svelte/prefer-style-directive": "error", 35 | "svelte/no-reactive-literals": "error", 36 | "svelte/no-useless-mustaches": "error", 37 | "svelte/button-has-type": "off", 38 | "svelte/require-each-key": "off", 39 | "svelte/no-at-html-tags": "off", 40 | "svelte/no-unused-svelte-ignore": "off", 41 | "svelte/require-stores-init": "off", 42 | "svelte/css-unused-selector": "off", 43 | }, 44 | overrides: [ 45 | { 46 | files: ["*.svelte"], 47 | parser: "svelte-eslint-parser", 48 | parserOptions: { 49 | parser: "@typescript-eslint/parser", 50 | }, 51 | rules: { 52 | "@typescript-eslint/no-unused-vars": [ 53 | "warn", 54 | { 55 | argsIgnorePattern: "^_", 56 | varsIgnorePattern: "^\\$\\$(Props|Events|Slots|Generic)$", 57 | }, 58 | ], 59 | }, 60 | }, 61 | { 62 | files: ["*.ts"], 63 | parser: "@typescript-eslint/parser", 64 | rules: { 65 | "@typescript-eslint/ban-types": [ 66 | "error", 67 | { 68 | extendDefaults: true, 69 | types: { 70 | "{}": false, 71 | }, 72 | }, 73 | ], 74 | }, 75 | }, 76 | ], 77 | }; 78 | -------------------------------------------------------------------------------- /packages/paneforge/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /dist 5 | /.svelte-kit 6 | /package 7 | .env 8 | .env.* 9 | !.env.example 10 | vite.config.js.timestamp-* 11 | vite.config.ts.timestamp-* 12 | -------------------------------------------------------------------------------- /packages/paneforge/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /packages/paneforge/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore files for PNPM, NPM and YARN 2 | pnpm-lock.yaml 3 | package-lock.json 4 | yarn.lock 5 | dist 6 | .svelte-kit -------------------------------------------------------------------------------- /packages/paneforge/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": false, 4 | "trailingComma": "es5", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte"], 7 | "overrides": [ 8 | { 9 | "files": "*.svelte", 10 | "options": { 11 | "parser": "svelte" 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/paneforge/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # paneforge 2 | 3 | ## 0.0.6 4 | 5 | ### Patch Changes 6 | 7 | - chore: add license to `package.json` ([#36](https://github.com/svecosystem/paneforge/pull/36)) 8 | 9 | ## 0.0.5 10 | 11 | ### Patch Changes 12 | 13 | - chore: add svelte 5 to peer deps ([#29](https://github.com/svecosystem/paneforge/pull/29)) 14 | 15 | ## 0.0.4 16 | 17 | ### Patch Changes 18 | 19 | - chore: remove forgotten console.log ([#21](https://github.com/svecosystem/paneforge/pull/21)) 20 | 21 | ## 0.0.3 22 | 23 | ### Patch Changes 24 | 25 | - fixed a bug where safari would select the panel when dragging a handle up ([#17](https://github.com/svecosystem/paneforge/pull/17)) 26 | 27 | ## 0.0.2 28 | 29 | ### Patch Changes 30 | 31 | - Fixed resizing on mobile devices ([#4](https://github.com/svecosystem/paneforge/pull/4)) 32 | 33 | ## 0.0.1 34 | 35 | ### Patch Changes 36 | 37 | - Initial release 🎉 ([#1](https://github.com/svecosystem/paneforge/pull/1)) 38 | -------------------------------------------------------------------------------- /packages/paneforge/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Hunter Johnston 4 | Copyright (c) 2023 Brian Vaughn 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /packages/paneforge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "paneforge", 3 | "version": "0.0.6", 4 | "author": { 5 | "name": "Hunter Johnston", 6 | "url": "https://github.com/huntabyte" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/svecosystem/paneforge", 11 | "directory": "packages/paneforge" 12 | }, 13 | "license": "MIT", 14 | "scripts": { 15 | "dev": "pnpm watch", 16 | "build": "pnpm package", 17 | "preview": "vite preview", 18 | "package": "svelte-kit sync && svelte-package && publint", 19 | "prepublishOnly": "pnpm run package", 20 | "test": "npm run test:integration && npm run test:unit", 21 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 22 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 23 | "lint": "prettier --check . && eslint .", 24 | "format": "prettier --write .", 25 | "test:integration": "playwright test", 26 | "test:unit": "vitest", 27 | "watch": "svelte-kit sync && svelte-package --watch" 28 | }, 29 | "exports": { 30 | ".": { 31 | "types": "./dist/index.d.ts", 32 | "svelte": "./dist/index.js" 33 | } 34 | }, 35 | "files": [ 36 | "dist", 37 | "!dist/**/*.test.*", 38 | "!dist/**/*.spec.*" 39 | ], 40 | "peerDependencies": { 41 | "svelte": "^4.0.0 || ^5.0.0-next.1" 42 | }, 43 | "devDependencies": { 44 | "@sveltejs/adapter-auto": "^3.0.0", 45 | "@sveltejs/kit": "^2.0.0", 46 | "@sveltejs/package": "^2.0.0", 47 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 48 | "@types/eslint": "8.56.0", 49 | "@types/node": "^20.10.6", 50 | "@typescript-eslint/eslint-plugin": "^6.0.0", 51 | "@typescript-eslint/parser": "^6.0.0", 52 | "autoprefixer": "^10.4.16", 53 | "eslint": "^8.56.0", 54 | "eslint-config-prettier": "^9.1.0", 55 | "eslint-plugin-svelte": "^2.35.1", 56 | "postcss": "^8.4.32", 57 | "postcss-load-config": "^5.0.2", 58 | "prettier": "^3.1.1", 59 | "prettier-plugin-svelte": "^3.1.2", 60 | "prettier-plugin-tailwindcss": "^0.5.9", 61 | "publint": "^0.1.9", 62 | "svelte": "^4.2.7", 63 | "svelte-check": "^3.6.0", 64 | "tailwindcss": "^3.4.1", 65 | "tslib": "^2.4.1", 66 | "typescript": "^5.0.0", 67 | "vite": "^5.0.3", 68 | "vitest": "^1.0.0" 69 | }, 70 | "svelte": "./dist/index.js", 71 | "types": "./dist/index.d.ts", 72 | "type": "module", 73 | "dependencies": { 74 | "nanoid": "^5.0.4" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /packages/paneforge/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import type { PlaywrightTestConfig } from "@playwright/test"; 2 | 3 | const config: PlaywrightTestConfig = { 4 | webServer: { 5 | command: "npm run build && npm run preview", 6 | port: 4173, 7 | }, 8 | testDir: "tests", 9 | testMatch: /(.+\.)?(test|spec)\.[jt]s/, 10 | }; 11 | 12 | export default config; 13 | -------------------------------------------------------------------------------- /packages/paneforge/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const tailwindcss = require("tailwindcss"); 2 | const autoprefixer = require("autoprefixer"); 3 | 4 | const config = { 5 | plugins: [ 6 | //Some plugins, like tailwindcss/nesting, need to run before Tailwind, 7 | tailwindcss(), 8 | //But others, like autoprefixer, need to run after, 9 | autoprefixer, 10 | ], 11 | }; 12 | 13 | module.exports = config; 14 | -------------------------------------------------------------------------------- /packages/paneforge/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | declare global { 4 | namespace App { 5 | // interface Error {} 6 | // interface Locals {} 7 | // interface PageData {} 8 | // interface PageState {} 9 | // interface Platform {} 10 | } 11 | } 12 | 13 | export {}; 14 | -------------------------------------------------------------------------------- /packages/paneforge/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/paneforge/src/app.pcss: -------------------------------------------------------------------------------- 1 | /* Write your global styles here, in PostCSS syntax */ 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | -------------------------------------------------------------------------------- /packages/paneforge/src/index.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from "vitest"; 2 | 3 | describe("sum test", () => { 4 | it("adds 1 + 2 to equal 3", () => { 5 | expect(1 + 2).toBe(3); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/components/ctx.ts: -------------------------------------------------------------------------------- 1 | import { createPaneForge, type CreatePaneForgeProps } from "$lib/internal/paneforge.js"; 2 | import { getContext, hasContext, setContext } from "svelte"; 3 | import { removeUndefined, getOptionUpdater } from "$lib/internal/utils/index.js"; 4 | 5 | const PF_GROUP_CTX = Symbol("PF_GROUP_CTX"); 6 | 7 | export function setCtx(props: CreatePaneForgeProps) { 8 | const paneForge = createPaneForge(removeUndefined(props)); 9 | const updateOption = getOptionUpdater(paneForge.options); 10 | 11 | const ctxValue = { ...paneForge, updateOption }; 12 | 13 | setContext(PF_GROUP_CTX, ctxValue); 14 | return ctxValue; 15 | } 16 | 17 | export function getCtx(componentName: string) { 18 | if (!hasContext(PF_GROUP_CTX)) { 19 | throw new Error(`${componentName} components must be rendered with a container`); 20 | } 21 | return getContext>(PF_GROUP_CTX); 22 | } 23 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as PaneGroup } from "./pane-group.svelte"; 2 | export { default as Pane } from "./pane.svelte"; 3 | export { default as PaneResizer } from "./pane-resizer.svelte"; 4 | export type * from "./types.js"; 5 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/components/pane-group.svelte: -------------------------------------------------------------------------------- 1 | 50 | 51 |
52 | 53 |
54 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/components/pane-group.ts: -------------------------------------------------------------------------------- 1 | import type { PaneGroupStorage } from "$lib/internal/utils/storage.js"; 2 | import { type DragState, type Direction } from "../internal/types.js"; 3 | import type { Writable } from "svelte/store"; 4 | 5 | export type PaneGroupOnLayout = (layout: number[]) => void; 6 | 7 | export type CommittedValues = { 8 | autoSaveId: string | null; 9 | direction: Direction; 10 | dragState: Writable; 11 | id: string; 12 | keyboardResizeBy: number | null; 13 | onLayout: PaneGroupOnLayout | null; 14 | storage: PaneGroupStorage; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/components/pane-resizer.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | PaneResizeHandleOnDragging, 3 | ResizeEvent, 4 | ResizeHandler, 5 | } from "$lib/internal/types.js"; 6 | import { chain } from "$lib/internal/utils/chain.js"; 7 | import { addEventListener } from "$lib/internal/utils/event.js"; 8 | 9 | type ResizerActionParams = { 10 | disabled?: boolean; 11 | resizeHandler: ResizeHandler | null; 12 | isDragging?: boolean; 13 | onDragging?: PaneResizeHandleOnDragging; 14 | stopDragging: () => void; 15 | }; 16 | 17 | /** 18 | * A Svelte action that adds resize handle functionality to an element. 19 | * This action is used to handle the dragging of a resize handle. 20 | */ 21 | export function resizeHandleAction(node: HTMLElement, params: ResizerActionParams) { 22 | let unsub = () => {}; 23 | function update(params: ResizerActionParams) { 24 | unsub(); 25 | const { disabled, resizeHandler, isDragging, stopDragging, onDragging = undefined } = params; 26 | if (disabled || resizeHandler === null || !isDragging) return; 27 | 28 | const onMove = (event: ResizeEvent) => { 29 | resizeHandler(event); 30 | }; 31 | 32 | const onMouseLeave = (event: ResizeEvent) => { 33 | resizeHandler(event); 34 | }; 35 | 36 | const stopDraggingAndBlur = () => { 37 | node.blur(); 38 | 39 | stopDragging(); 40 | 41 | if (onDragging) { 42 | onDragging(false); 43 | } 44 | }; 45 | 46 | unsub = chain( 47 | addEventListener(document.body, "contextmenu", stopDraggingAndBlur), 48 | addEventListener(document.body, "mousemove", onMove), 49 | addEventListener(document.body, "touchmove", onMove, { passive: false }), 50 | addEventListener(document.body, "mouseleave", onMouseLeave), 51 | addEventListener(window, "mouseup", stopDraggingAndBlur), 52 | addEventListener(window, "touchend", stopDraggingAndBlur) 53 | ); 54 | } 55 | update(params); 56 | 57 | return { 58 | update, 59 | onDestroy() { 60 | unsub(); 61 | }, 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/components/pane.svelte: -------------------------------------------------------------------------------- 1 | 93 | 94 |
95 | 96 |
97 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/index.ts: -------------------------------------------------------------------------------- 1 | import type { PaneGroupStorage } from "$lib/internal/utils/storage.js"; 2 | 3 | export * from "./components/index.js"; 4 | export type { PaneGroupStorage }; 5 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/constants.ts: -------------------------------------------------------------------------------- 1 | export const LOCAL_STORAGE_DEBOUNCE_INTERVAL = 100; 2 | export const PRECISION = 10; 3 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/svecosystem/paneforge/afc7a83d428965731a8ab29a1e459b723e2ae6da/packages/paneforge/src/lib/internal/index.ts -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/types.ts: -------------------------------------------------------------------------------- 1 | export type Direction = "horizontal" | "vertical"; 2 | 3 | export type PaneOnCollapse = () => void; 4 | export type PaneOnExpand = () => void; 5 | export type PaneOnResize = (size: number, prevSize: number | undefined) => void; 6 | 7 | export type PaneCallbacks = { 8 | onCollapse?: PaneOnCollapse; 9 | onExpand?: PaneOnExpand; 10 | onResize?: PaneOnResize; 11 | }; 12 | 13 | export type PaneConstraints = { 14 | collapsedSize?: number | undefined; 15 | collapsible?: boolean | undefined; 16 | defaultSize?: number | undefined; 17 | maxSize?: number | undefined; 18 | minSize?: number | undefined; 19 | }; 20 | 21 | export type PaneData = { 22 | callbacks: PaneCallbacks; 23 | constraints: PaneConstraints; 24 | id: string; 25 | idIsFromProps: boolean; 26 | order: number | undefined; 27 | }; 28 | 29 | export type DragState = { 30 | dragHandleId: string; 31 | dragHandleRect: DOMRect; 32 | initialCursorPosition: number; 33 | initialLayout: number[]; 34 | }; 35 | 36 | export type ResizeEvent = KeyboardEvent | MouseEvent | TouchEvent; 37 | export type ResizeHandler = (event: ResizeEvent) => void; 38 | 39 | export type PaneResizeHandleOnDragging = (isDragging: boolean) => void; 40 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/aria.ts: -------------------------------------------------------------------------------- 1 | import type { PaneData } from "../types.js"; 2 | 3 | /** 4 | * A utility function that calculates the `aria-valuemax`, `aria-valuemin`, 5 | * and `aria-valuenow` values for a pane based on its layout and constraints. 6 | */ 7 | export function calculateAriaValues({ 8 | layout, 9 | panesArray, 10 | pivotIndices, 11 | }: { 12 | layout: number[]; 13 | panesArray: PaneData[]; 14 | pivotIndices: number[]; 15 | }) { 16 | let currentMinSize = 0; 17 | let currentMaxSize = 100; 18 | let totalMinSize = 0; 19 | let totalMaxSize = 0; 20 | 21 | const firstIndex = pivotIndices[0]; 22 | 23 | // A pane's effective min/max sizes also need to account for other pane's sizes. 24 | for (let i = 0; i < panesArray.length; i++) { 25 | const { constraints } = panesArray[i]; 26 | const { maxSize = 100, minSize = 0 } = constraints; 27 | 28 | if (i === firstIndex) { 29 | currentMinSize = minSize; 30 | currentMaxSize = maxSize; 31 | } else { 32 | totalMinSize += minSize; 33 | totalMaxSize += maxSize; 34 | } 35 | } 36 | 37 | const valueMax = Math.min(currentMaxSize, 100 - totalMinSize); 38 | const valueMin = Math.max(currentMinSize, 100 - totalMaxSize); 39 | 40 | const valueNow = layout[firstIndex]; 41 | 42 | return { 43 | valueMax, 44 | valueMin, 45 | valueNow, 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/assert.ts: -------------------------------------------------------------------------------- 1 | export function assert( 2 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 3 | expectedCondition: any, 4 | message: string = "Assertion failed!" 5 | ): asserts expectedCondition { 6 | if (!expectedCondition) { 7 | // eslint-disable-next-line no-console 8 | console.error(message); 9 | throw Error(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/chain.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A callback function that takes an array of arguments of type `T` and returns `void`. 3 | * @template T The types of the arguments that the callback function takes. 4 | */ 5 | export type Callback = (...args: T) => void; 6 | 7 | type NonEmptyArray = [T, ...T[]]; 8 | 9 | /** 10 | * Executes an array of callback functions with the same arguments. 11 | * @template T The types of the arguments that the callback functions take. 12 | * @param n array of callback functions to execute. 13 | * @returns A new function that executes all of the original callback functions with the same arguments. 14 | */ 15 | export function chain( 16 | ...callbacks: NonEmptyArray> 17 | ): (...args: T) => void { 18 | return (...args) => { 19 | for (const callback of callbacks) { 20 | if (typeof callback === "function") { 21 | callback(...args); 22 | } 23 | } 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/compare.ts: -------------------------------------------------------------------------------- 1 | import { PRECISION } from "../constants.js"; 2 | 3 | /** 4 | * Compares two numbers for equality with a given fractional precision. 5 | */ 6 | export function areNumbersAlmostEqual( 7 | actual: number, 8 | expected: number, 9 | fractionDigits: number = PRECISION 10 | ): boolean { 11 | return compareNumbersWithTolerance(actual, expected, fractionDigits) === 0; 12 | } 13 | 14 | /** 15 | * Compares two numbers with a given tolerance. 16 | * 17 | * @returns `-1` if `actual` is less than `expected`, `0` if they are equal, 18 | * and `1` if `actual` is greater than `expected`. 19 | */ 20 | export function compareNumbersWithTolerance( 21 | actual: number, 22 | expected: number, 23 | fractionDigits: number = PRECISION 24 | ): number { 25 | const roundedActual = roundTo(actual, fractionDigits); 26 | const roundedExpected = roundTo(expected, fractionDigits); 27 | 28 | return Math.sign(roundedActual - roundedExpected); 29 | } 30 | 31 | /** 32 | * Compares two arrays for equality. 33 | */ 34 | export function areArraysEqual>(arrA: T, arrB: T): boolean { 35 | if (arrA.length !== arrB.length) return false; 36 | 37 | for (let index = 0; index < arrA.length; index++) { 38 | if (arrA[index] !== arrB[index]) return false; 39 | } 40 | 41 | return true; 42 | } 43 | 44 | /** 45 | * Rounds a number to a given number of decimal places. 46 | */ 47 | function roundTo(value: number, decimals: number): number { 48 | return parseFloat(value.toFixed(decimals)); 49 | } 50 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/event.ts: -------------------------------------------------------------------------------- 1 | export type GeneralEventListener = (evt: E) => unknown; 2 | 3 | export function addEventListener( 4 | target: Window, 5 | event: E, 6 | handler: (this: Window, ev: HTMLElementEventMap[E]) => unknown, 7 | options?: boolean | AddEventListenerOptions 8 | ): VoidFunction; 9 | 10 | export function addEventListener( 11 | target: Document, 12 | event: E, 13 | handler: (this: Document, ev: HTMLElementEventMap[E]) => unknown, 14 | options?: boolean | AddEventListenerOptions 15 | ): VoidFunction; 16 | 17 | export function addEventListener( 18 | target: EventTarget, 19 | event: E, 20 | handler: GeneralEventListener, 21 | options?: boolean | AddEventListenerOptions 22 | ): VoidFunction; 23 | /** 24 | * Adds an event listener to the specified target element(s) for the given event(s), and returns a function to remove it. 25 | * @param target The target element(s) to add the event listener to. 26 | * @param event The event(s) to listen for. 27 | * @param handler The function to be called when the event is triggered. 28 | * @param options An optional object that specifies characteristics about the event listener. 29 | * @returns A function that removes the event listener from the target element(s). 30 | */ 31 | export function addEventListener( 32 | target: Window | Document | EventTarget, 33 | event: string | string[], 34 | handler: EventListenerOrEventListenerObject, 35 | options?: boolean | AddEventListenerOptions 36 | ) { 37 | const events = Array.isArray(event) ? event : [event]; 38 | 39 | // Add the event listener to each specified event for the target element(s). 40 | events.forEach((_event) => target.addEventListener(_event, handler, options)); 41 | 42 | // Return a function that removes the event listener from the target element(s). 43 | return () => { 44 | events.forEach((_event) => target.removeEventListener(_event, handler, options)); 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/id.ts: -------------------------------------------------------------------------------- 1 | import { nanoid } from "nanoid/non-secure"; 2 | 3 | /** 4 | * If an id is provided return it, otherwise generate a new id and return that. 5 | */ 6 | export function generateId(idFromProps: string | undefined | null = null): string { 7 | if (idFromProps == null) return nanoid(10); 8 | return idFromProps; 9 | } 10 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./lifecycle.js"; 2 | export * from "./store.js"; 3 | export * from "./style.js"; 4 | export * from "./aria.js"; 5 | export * from "./id.js"; 6 | export * from "./storage.js"; 7 | export * from "./object.js"; 8 | export * from "./chain.js"; 9 | export * from "./event.js"; 10 | export * from "./compare.js"; 11 | export * from "./resize.js"; 12 | export * from "./adjust-layout.js"; 13 | export * from "./is.js"; 14 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/is.ts: -------------------------------------------------------------------------------- 1 | import type { ResizeEvent } from "../types.js"; 2 | 3 | export const isBrowser = typeof document !== "undefined"; 4 | 5 | export function isHTMLElement(element: unknown): element is HTMLElement { 6 | return element instanceof HTMLElement; 7 | } 8 | 9 | export function isKeyDown(event: ResizeEvent): event is KeyboardEvent { 10 | return event.type === "keydown"; 11 | } 12 | 13 | export function isMouseEvent(event: ResizeEvent): event is MouseEvent { 14 | return event.type.startsWith("mouse"); 15 | } 16 | 17 | export function isTouchEvent(event: ResizeEvent): event is TouchEvent { 18 | return event.type.startsWith("touch"); 19 | } 20 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/lifecycle.ts: -------------------------------------------------------------------------------- 1 | import { onDestroy } from "svelte"; 2 | 3 | /** 4 | * Safely calls `onDestroy` and catches any errors that occur. 5 | */ 6 | export function safeOnDestroy(fn: (...args: unknown[]) => unknown) { 7 | try { 8 | onDestroy(fn); 9 | } catch { 10 | return fn(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/object.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Removes all undefined properties from the given object. 3 | */ 4 | export function removeUndefined(obj: T): T { 5 | const result = {} as T; 6 | for (const key in obj) { 7 | const value = obj[key]; 8 | if (value !== undefined) { 9 | result[key] = value; 10 | } 11 | } 12 | return result; 13 | } 14 | -------------------------------------------------------------------------------- /packages/paneforge/src/lib/internal/utils/resize.ts: -------------------------------------------------------------------------------- 1 | import { PRECISION } from "../constants.js"; 2 | import type { PaneConstraints } from "../types.js"; 3 | import { assert } from "./assert.js"; 4 | import { compareNumbersWithTolerance } from "./compare.js"; 5 | 6 | /** 7 | * Resizes a pane based on its constraints. 8 | */ 9 | export function resizePane({ 10 | paneConstraints: paneConstraintsArray, 11 | paneIndex, 12 | initialSize, 13 | }: { 14 | paneConstraints: PaneConstraints[]; 15 | paneIndex: number; 16 | initialSize: number; 17 | }): number { 18 | const paneConstraints = paneConstraintsArray[paneIndex]; 19 | assert(paneConstraints != null, "Pane constraints should not be null."); 20 | 21 | const { collapsedSize = 0, collapsible, maxSize = 100, minSize = 0 } = paneConstraints; 22 | 23 | let newSize = initialSize; 24 | 25 | if (compareNumbersWithTolerance(newSize, minSize) < 0) { 26 | newSize = getAdjustedSizeForCollapsible(newSize, collapsible, collapsedSize, minSize); 27 | } 28 | 29 | newSize = Math.min(maxSize, newSize); 30 | return parseFloat(newSize.toFixed(PRECISION)); 31 | } 32 | 33 | /** 34 | * Adjusts the size of a pane based on its collapsible state. 35 | * 36 | * If the pane is collapsible, the size will be snapped to the collapsed size 37 | * or the minimum size based on the halfway point. 38 | */ 39 | function getAdjustedSizeForCollapsible( 40 | size: number, 41 | collapsible: boolean | undefined, 42 | collapsedSize: number, 43 | minSize: number 44 | ): number { 45 | if (!collapsible) return minSize; 46 | 47 | // Snap collapsible panes closed or open based on the halfway point. 48 | const halfwayPoint = (collapsedSize + minSize) / 2; 49 | return compareNumbersWithTolerance(size, halfwayPoint) < 0 ? collapsedSize : minSize; 50 | } 51 | -------------------------------------------------------------------------------- /packages/paneforge/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from "@sveltejs/adapter-auto"; 2 | import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors 7 | // for more information about preprocessors 8 | preprocess: [vitePreprocess({})], 9 | 10 | kit: { 11 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. 12 | // If your environment is not supported or you settled on a specific environment, switch out the adapter. 13 | // See https://kit.svelte.dev/docs/adapters for more information about adapters. 14 | adapter: adapter(), 15 | }, 16 | }; 17 | 18 | export default config; 19 | -------------------------------------------------------------------------------- /packages/paneforge/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config}*/ 2 | const config = { 3 | content: ["./src/**/*.{html,js,svelte,ts}"], 4 | 5 | theme: { 6 | extend: {}, 7 | }, 8 | 9 | plugins: [], 10 | }; 11 | 12 | module.exports = config; 13 | -------------------------------------------------------------------------------- /packages/paneforge/tests/test.ts: -------------------------------------------------------------------------------- 1 | import { expect, it } from "vitest"; 2 | 3 | it("should work", () => { 4 | expect(1 + 1).toBe(2); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/paneforge/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "module": "NodeNext", 13 | "moduleResolution": "NodeNext" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/paneforge/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from "@sveltejs/kit/vite"; 2 | import { defineConfig } from "vitest/config"; 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()], 6 | test: { 7 | include: ["src/**/*.{test,spec}.{js,ts}"], 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/*" 3 | - "sites/*" 4 | -------------------------------------------------------------------------------- /sites/docs/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | CHANGELOG.md 15 | /.contentlayer 16 | -------------------------------------------------------------------------------- /sites/docs/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type { import("eslint").Linter.Config } */ 2 | module.exports = { 3 | root: true, 4 | extends: [ 5 | "eslint:recommended", 6 | "plugin:@typescript-eslint/recommended", 7 | "plugin:svelte/recommended", 8 | "prettier", 9 | ], 10 | parser: "@typescript-eslint/parser", 11 | plugins: ["@typescript-eslint"], 12 | parserOptions: { 13 | sourceType: "module", 14 | ecmaVersion: "latest", 15 | extraFileExtensions: [".svelte"], 16 | }, 17 | env: { 18 | browser: true, 19 | es2024: true, 20 | node: true, 21 | }, 22 | globals: { $$Generic: "readable", NodeJS: true }, 23 | rules: { 24 | "no-console": "warn", 25 | "@typescript-eslint/no-unused-vars": [ 26 | "warn", 27 | { 28 | argsIgnorePattern: "^_", 29 | varsIgnorePattern: "^_", 30 | }, 31 | ], 32 | "svelte/no-immutable-reactive-statements": "error", 33 | "svelte/no-reactive-literals": "error", 34 | "svelte/no-useless-mustaches": "error", 35 | "svelte/button-has-type": "off", 36 | "svelte/require-each-key": "off", 37 | "svelte/no-at-html-tags": "off", 38 | "svelte/no-unused-svelte-ignore": "off", 39 | "svelte/require-stores-init": "off", 40 | }, 41 | overrides: [ 42 | { 43 | files: ["*.svelte"], 44 | parser: "svelte-eslint-parser", 45 | parserOptions: { 46 | parser: "@typescript-eslint/parser", 47 | }, 48 | rules: { 49 | "@typescript-eslint/no-unused-vars": [ 50 | "warn", 51 | { 52 | argsIgnorePattern: "^_", 53 | varsIgnorePattern: "^\\$\\$(Props|Events|Slots|Generic)$", 54 | }, 55 | ], 56 | }, 57 | }, 58 | { 59 | files: ["*.ts"], 60 | parser: "@typescript-eslint/parser", 61 | rules: { 62 | "@typescript-eslint/ban-types": [ 63 | "error", 64 | { 65 | extendDefaults: true, 66 | types: { 67 | "{}": false, 68 | }, 69 | }, 70 | ], 71 | }, 72 | }, 73 | ], 74 | }; 75 | -------------------------------------------------------------------------------- /sites/docs/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | vite.config.js.timestamp-* 10 | vite.config.ts.timestamp-* 11 | .contentlayer 12 | .contentlayer/ 13 | /.contentlayer 14 | .vercel -------------------------------------------------------------------------------- /sites/docs/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /sites/docs/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore files for PNPM, NPM and YARN 2 | pnpm-lock.yaml 3 | package-lock.json 4 | yarn.lock 5 | CHANGELOG.md 6 | .svelte-kit 7 | /.svelte-kit 8 | /.contentlayer -------------------------------------------------------------------------------- /sites/docs/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": false, 4 | "trailingComma": "es5", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], 7 | "overrides": [ 8 | { 9 | "files": "*.svelte", 10 | "options": { "parser": "svelte" } 11 | }, 12 | { "files": "*.md", "options": { "parser": "markdown", "printWidth": 85 } } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /sites/docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # docs 2 | 3 | ## 0.0.3 4 | 5 | ### Patch Changes 6 | 7 | - Updated dependencies [[`e30a0c1df0add8f0f3eb8e25944e9482b274a4fa`](https://github.com/svecosystem/paneforge/commit/e30a0c1df0add8f0f3eb8e25944e9482b274a4fa)]: 8 | - paneforge@0.0.2 9 | 10 | ## 0.0.2 11 | 12 | ### Patch Changes 13 | 14 | - Updated dependencies [[`35e4f87d79c2b8dfd174e2a8ba627ce23cbebc20`](https://github.com/svecosystem/paneforge/commit/35e4f87d79c2b8dfd174e2a8ba627ce23cbebc20)]: 15 | - paneforge@0.0.1 16 | 17 | ## 0.0.1 18 | 19 | ### Patch Changes 20 | 21 | - Updated dependencies [[`790f8d4c55d21826b873f185080b110c7dc7121a`](https://github.com/huntabyte/formsnap/commit/790f8d4c55d21826b873f185080b110c7dc7121a)]: 22 | - formsnap@0.5.0 23 | -------------------------------------------------------------------------------- /sites/docs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Hunter Johnston 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /sites/docs/README.md: -------------------------------------------------------------------------------- 1 | # Paneforge Documentation 2 | -------------------------------------------------------------------------------- /sites/docs/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://shadcn-svelte.com/schema.json", 3 | "style": "default", 4 | "tailwind": { 5 | "config": "tailwind.config.js", 6 | "css": "src/app.pcss", 7 | "baseColor": "slate" 8 | }, 9 | "aliases": { 10 | "components": "$lib/components", 11 | "utils": "$lib/utils" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /sites/docs/content/components/pane-resizer.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: PaneResizer 3 | description: A draggable handle between two panes that allows the user to resize them. 4 | tagline: Components 5 | --- 6 | 7 | The `PaneResizer` component is used to create a draggable handle between two panes that allows the user to resize them. 8 | 9 | ## Usage 10 | 11 | ```svelte {7} 12 | 15 | 16 | 17 | Pane 1 18 | 19 | Pane 2 20 | 21 | ``` 22 | 23 | ## Props 24 | 25 | Here are the props available for the `PaneResizer` component: 26 | 27 | ```ts 28 | export type PaneResizerProps = { 29 | /** 30 | * Whether the resize handle is disabled. 31 | * 32 | * @defaultValue `false` 33 | */ 34 | disabled?: boolean; 35 | 36 | /** 37 | * A callback that is called when the resize handle's dragging state changes. 38 | */ 39 | onDraggingChange?: (isDragging: boolean) => void; 40 | 41 | /** 42 | * The tabIndex of the resize handle. 43 | */ 44 | tabIndex?: number; 45 | 46 | /** 47 | * The underlying DOM element of the resize handle. You can `bind` to this 48 | * prop to get a reference to the element. 49 | */ 50 | el?: HTMLElement | null; 51 | } & HTMLAttributes; 52 | ``` 53 | 54 | ## Data Attributes 55 | 56 | The following data attributes are available for the `PaneResizer` component: 57 | 58 | ```ts 59 | export type PaneResizerAttributes = { 60 | /** The direction of the pane group the handle belongs to. */ 61 | "data-direction": "horizontal" | "vertical"; 62 | /** The ID of the pane group the handle belongs to. */ 63 | "data-pane-group-id": string; 64 | /** Whether the resize handle is active or not. */ 65 | "data-active"?: "pointer" | "keyboard"; 66 | /** Whether the resize handle is enabled or not. */ 67 | "data-enabled"?: boolean; 68 | /** The ID of the resize handle. */ 69 | "data-pane-resizer-id": string; 70 | /** Present on all resizer elements */ 71 | "data-pane-resizer": ""; 72 | }; 73 | ``` 74 | -------------------------------------------------------------------------------- /sites/docs/content/examples/collapsible-panes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Collapsible Panes 3 | description: An example of how to create collapsible panes. 4 | --- 5 | 6 | 10 | 11 | You can use the `collapsedSize` and `collapsible` props to create collapsible panes. The `collapsedSize` prop sets the size of the pane when it is in a collapsed state, and the `collapsible` prop determines whether the pane can be collapsed. 12 | 13 | You can also use the `onCollapse` and `onExpand` callbacks to perform actions when the pane is collapsed or expanded, along with the `pane` prop to get a reference to the `Pane` component's API to programmatically collapse or expand the pane. 14 | 15 |
16 | 17 |
18 | 19 | 20 | 21 | ## Anatomy 22 | 23 | Here's the high-level structure of the example above: 24 | 25 | ```svelte 26 | 32 | 33 | {#if collapsed} 34 | 41 | {:else} 42 | 49 | {/if} 50 | 51 | (collapsed = true)} 58 | onExpand={() => (collapsed = false)} 59 | /> 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | ``` 70 | -------------------------------------------------------------------------------- /sites/docs/content/examples/conditional-panes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Conditional Panes 3 | description: An example of how to handle conditional panes. 4 | --- 5 | 6 | 10 | 11 | When conditionally rendering panes, you need to use the `order` prop to ensure the panes are rendered in the correct order when they are displayed. 12 | 13 |
14 | 15 |
16 | 17 | 18 | 19 | ## Anatomy 20 | 21 | Here's the high-level structure of the example above: 22 | 23 | ```svelte 24 | 30 | 31 | 34 | 37 | 38 | 39 | {#if showPaneOne} 40 | 41 | 42 | {/if} 43 | 44 | {#if showPaneThree} 45 | 46 | 47 | {/if} 48 | 49 | ``` 50 | -------------------------------------------------------------------------------- /sites/docs/content/examples/horizontal-groups.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Horizontal Groups 3 | description: An example of a horizontal group of panes. 4 | --- 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | ## Anatomy 16 | 17 | Here's the high-level structure of the example above: 18 | 19 | ```svelte 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ``` 30 | -------------------------------------------------------------------------------- /sites/docs/content/examples/nested-groups.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Nested Groups 3 | description: An example of nesting groups of panes for more complex layouts. 4 | --- 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | ## Anatomy 16 | 17 | Here's the high-level structure of the example above: 18 | 19 | ```svelte 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | ``` 36 | -------------------------------------------------------------------------------- /sites/docs/content/examples/overflowing-panes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overflowing Panes 3 | description: An example of how panes with overflowing content are handled. 4 | --- 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | ## Anatomy 16 | 17 | Here's the high-level structure of the example above: 18 | 19 | ```svelte 20 | 23 | 24 | 25 | 26 |
27 | 28 |
29 |
30 | 31 | 32 | 33 | 34 |
35 | 36 |
37 |
38 | 39 | 40 |
41 | 42 |
43 |
44 |
45 |
46 |
47 | ``` 48 | -------------------------------------------------------------------------------- /sites/docs/content/examples/persistent-layouts.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Persistent Layouts 3 | description: Examples of persisting layouts across page loads. 4 | --- 5 | 6 | 11 | 12 | ## Local Storage 13 | 14 | The `PaneGroup` component has an `autoSaveId` prop that can be used to uniquely identify the layout of the panes within the group. When provided, the layout of the panes will be saved to local storage and restored when the page is reloaded. 15 | 16 | 17 | 18 | 19 | 20 | ### Anatomy 21 | 22 | Here's the high-level structure of the example above: 23 | 24 | ```svelte title="+page.svelte" 25 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ``` 35 | 36 | ## Cookies (SSR-friendly) 37 | 38 | Local storage is not available on the server, so you can use cookies to persist the layout of the panes across page loads, ensuring no layout flicker when the page is first loaded. 39 | 40 | 41 | 42 | 43 | 44 | ### Anatomy 45 | 46 | Here's the high-level structure of the example above: 47 | 48 | ```ts title="+page.server.ts" 49 | import type { PageServerLoad } from "./$types"; 50 | 51 | export const load: PageServerLoad = async (event) => { 52 | let layout = event.cookies.get("PaneForge:layout"); 53 | if (layout) { 54 | layout = JSON.parse(layout); 55 | } 56 | 57 | return { 58 | layout, 59 | }; 60 | }; 61 | ``` 62 | 63 | ```svelte 64 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | ``` 79 | -------------------------------------------------------------------------------- /sites/docs/content/examples/vertical-groups.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vertical Groups 3 | description: An example of a vertical group of panes. 4 | --- 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | ## Anatomy 16 | 17 | Here's the high-level structure of the example above: 18 | 19 | ```svelte 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ``` 30 | -------------------------------------------------------------------------------- /sites/docs/content/getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting Started 3 | description: Learn how to install and use Paneforge in your projects. 4 | --- 5 | 6 | ## Installation 7 | 8 | Install Paneforge using your favorite package manager: 9 | 10 | ```bash 11 | npm install paneforge 12 | ``` 13 | 14 | ## Basic Usage 15 | 16 | Here's a simple example of how to use Paneforge to create a horizontal pane group with two panes: 17 | 18 | ```svelte 19 | 22 | 23 | 24 | Pane 1 25 | 26 | Pane 2 27 | 28 | ``` 29 | 30 | The `PaneGroup` component is used to initialize a pane group, and the `Pane` component is used to create a pane. The `PaneResizer` component is used to create a resizer that can be dragged to resize the panes. 31 | 32 | The components ship only with the styles necessary to position the panes in the appropriate layout. The rest of the styling is up to you. 33 | -------------------------------------------------------------------------------- /sites/docs/content/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | description: What this project is all about. 4 | --- 5 | 6 | 9 | 10 | PaneForge provides components that make it easy to create resizable panes in your Svelte apps. It's designed to be simple to use, and to work well with other Svelte components and libraries. This project has taken a lot of inspiration and code from the work done by [Bryan Vaughn](https://github.com/bvaughn) and [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels) and seeks to provide a similar experience for Svelte developers. 11 | 12 | Here's an example of the functionality you can expect from PaneForge: 13 | 14 | 15 | 16 | ## Features 17 | 18 | - **Simple API**: PaneForge is designed to be easy to use. It provides a small set of components that can be combined to create complex layouts. 19 | - **Resizable Panes**: Panes can be resized by dragging the resizer between them. 20 | - **Nested Groups**: Groups of panes can be nested inside other groups to create complex layouts. 21 | - **Customizable**: The appearance and behavior of the panes can be customized using CSS and Svelte props. 22 | - **Persistent Layouts**: PaneForge can be used with LocalStorage or cookies to persist the layout of the panes between page loads. 23 | - **Accessible**: PaneForge is designed to be accessible to all users, including those who use assistive technologies. 24 | - **Community-driven**: PaneForge is an open-source project that welcomes contributions from the community. If you have an idea for a new feature or an improvement, we'd love to hear from you! 25 | 26 | ## Next Steps 27 | 28 | Start using PaneForge in your Svelte app by following the [Getting Started](/docs/getting-started) guide. If you have any questions or need help, feel free to ask in the [Discord](https://discord.gg/hbAGu6akVy)! 29 | -------------------------------------------------------------------------------- /sites/docs/content/styling.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Styling 3 | description: Easily style the various parts of your panes. 4 | --- 5 | -------------------------------------------------------------------------------- /sites/docs/contentlayer.config.js: -------------------------------------------------------------------------------- 1 | import { defineDocumentType, makeSource } from "contentlayer/source-files"; 2 | import path from "path"; 3 | 4 | /** @type {import('contentlayer/source-files').ComputedFields} */ 5 | const computedFields = { 6 | slug: { 7 | type: "string", 8 | resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"), 9 | }, 10 | slugFull: { 11 | type: "string", 12 | resolve: (doc) => `/${doc._raw.flattenedPath}`, 13 | }, 14 | fileName: { 15 | type: "string", 16 | resolve: (doc) => path.parse(doc._raw.sourceFilePath.split("/").slice(-1).join("/")).name, 17 | }, 18 | suffix: { 19 | type: "string", 20 | resolve: (doc) => path.parse(doc._raw.sourceFilePath.split("/").slice(-1).join("/")).ext, 21 | }, 22 | }; 23 | 24 | export const Doc = defineDocumentType(() => ({ 25 | name: "Doc", 26 | filePathPattern: `**/*.md`, 27 | fields: { 28 | title: { 29 | type: "string", 30 | required: true, 31 | }, 32 | description: { 33 | type: "string", 34 | required: true, 35 | }, 36 | tagline: { 37 | type: "string", 38 | required: false, 39 | }, 40 | }, 41 | computedFields, 42 | })); 43 | 44 | export default makeSource({ 45 | contentDirPath: "./content", 46 | documentTypes: [Doc], 47 | disableImportAliasWarning: true, 48 | }); 49 | -------------------------------------------------------------------------------- /sites/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "description": "Docs for Paneforge", 4 | "version": "0.0.3", 5 | "private": true, 6 | "scripts": { 7 | "dev": "concurrently \"pnpm:dev:content\" \"pnpm:dev:svelte\"", 8 | "dev:content": "contentlayer dev", 9 | "dev:svelte": "vite dev --host", 10 | "build": "contentlayer build && vite build", 11 | "build:all": "pnpm -w build", 12 | "build:content": "contentlayer build", 13 | "build:content-cachebust": "contentlayer build --clearCache", 14 | "preview": "vite preview", 15 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 16 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 17 | "test": "vitest", 18 | "lint": "prettier --check . && eslint .", 19 | "format": "prettier --write .", 20 | "sync": "svelte-kit sync" 21 | }, 22 | "license": "MIT", 23 | "author": { 24 | "name": "Huntabyte", 25 | "url": "https://github.com/huntabyte" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "https://github.com/svecosystem/paneforge" 30 | }, 31 | "devDependencies": { 32 | "@sveltejs/adapter-cloudflare": "^4.1.0", 33 | "@sveltejs/kit": "^2.5.0", 34 | "@sveltejs/vite-plugin-svelte": "^3.0.2", 35 | "@tailwindcss/typography": "^0.5.10", 36 | "@types/eslint": "8.56.2", 37 | "@types/hast": "^3.0.4", 38 | "@types/mdast": "^4.0.3", 39 | "@typescript-eslint/eslint-plugin": "^7.0.1", 40 | "@typescript-eslint/parser": "^7.0.1", 41 | "autoprefixer": "^10.4.17", 42 | "clsx": "^2.1.0", 43 | "concurrently": "^8.2.2", 44 | "contentlayer": "^0.3.4", 45 | "eslint": "^8.56.0", 46 | "eslint-config-prettier": "^9.1.0", 47 | "eslint-plugin-svelte": "^2.35.1", 48 | "mdsx": "^0.0.5", 49 | "phosphor-svelte": "^1.4.2", 50 | "postcss": "^8.4.35", 51 | "postcss-load-config": "^5.0.3", 52 | "prettier": "^3.2.5", 53 | "prettier-plugin-svelte": "^3.2.1", 54 | "prettier-plugin-tailwindcss": "^0.5.11", 55 | "rehype-pretty-code": "^0.13.0", 56 | "remark-gfm": "^4.0.0", 57 | "shiki": "^1.1.3", 58 | "svelte": "^4.2.11", 59 | "svelte-check": "^3.6.4", 60 | "tailwind-merge": "^2.2.1", 61 | "tailwind-variants": "^0.2.0", 62 | "tailwindcss": "^3.4.1", 63 | "tslib": "^2.6.2", 64 | "typescript": "^5.3.3", 65 | "unified": "^11.0.4", 66 | "unist-builder": "^4.0.0", 67 | "unist-util-visit": "^5.0.0", 68 | "vite": "^5.1.3", 69 | "vitest": "^1.3.0", 70 | "zod": "^3.22.4" 71 | }, 72 | "type": "module", 73 | "dependencies": { 74 | "@melt-ui/svelte": "^0.74.0", 75 | "bits-ui": "^0.18.1", 76 | "mode-watcher": "^0.2.1", 77 | "paneforge": "workspace:^", 78 | "rehype-slug": "^6.0.0", 79 | "svelte-sonner": "^0.3.17", 80 | "vaul-svelte": "^0.2.3" 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /sites/docs/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | "tailwindcss/nesting": {}, 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /sites/docs/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | declare global { 4 | namespace App { 5 | // interface Error {} 6 | // interface Locals {} 7 | // interface PageData {} 8 | // interface PageState {} 9 | // interface Platform {} 10 | } 11 | } 12 | 13 | export {}; 14 | -------------------------------------------------------------------------------- /sites/docs/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /sites/docs/src/index.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from "vitest"; 2 | 3 | describe("sum test", () => { 4 | it("adds 1 + 2 to equal 3", () => { 5 | expect(1 + 2).toBe(3); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/callout.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | {#if title} 23 | 24 | {title} 25 | 26 | {/if} 27 | 28 | 29 |

30 | 31 |

32 |
33 |
34 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/copy-code-button.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 26 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/demos/collapsible-demo.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | {#if collapsed} 13 | 21 | {:else} 22 | 30 | {/if} 31 |
32 | 33 | (collapsed = true)} 40 | onExpand={() => (collapsed = false)} 41 | > 42 |
43 | One 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 | 52 | 53 | 54 |
55 | Two 56 |
57 |
58 | 59 |
60 | 61 |
62 |
63 | 64 |
65 | Three 66 |
67 |
68 |
69 |
70 |
71 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/demos/conditional-demo.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 | 19 | 27 |
28 | 29 | 30 | {#if showPaneOne} 31 | 32 |
33 | One 34 |
35 |
36 | 37 |
38 | 39 |
40 |
41 | {/if} 42 | 43 |
44 | Two 45 |
46 |
47 | {#if showPaneThree} 48 | 49 |
50 | 51 |
52 |
53 | 54 |
55 | Three 56 |
57 |
58 | {/if} 59 |
60 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/demos/cookie-demo.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 |
14 | Left 15 |
16 |
17 | 18 |
19 | 20 |
21 |
22 | 23 |
24 | Right 25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/demos/horizontal-demo.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 |
12 | Left 13 |
14 |
15 | 16 |
17 | 18 |
19 |
20 | 21 |
22 | Right 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/demos/index.ts: -------------------------------------------------------------------------------- 1 | export { default as NestedGroupsDemo } from "./nested-groups-demo.svelte"; 2 | export { default as HorizontalDemo } from "./horizontal-demo.svelte"; 3 | export { default as VerticalDemo } from "./vertical-demo.svelte"; 4 | export { default as OverflowDemo } from "./overflow-demo.svelte"; 5 | export { default as CollapsibleDemo } from "./collapsible-demo.svelte"; 6 | export { default as ConditionalDemo } from "./conditional-demo.svelte"; 7 | export { default as CookieDemo } from "./cookie-demo.svelte"; 8 | export { default as StorageDemo } from "./storage-demo.svelte"; 9 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/demos/nested-groups-demo.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 |
9 | One 10 |
11 |
12 | 13 |
14 | 15 |
16 |
17 | 18 | 19 | 20 |
21 | Two 22 |
23 |
24 | 25 |
26 | 27 |
28 |
29 | 30 |
31 | Three 32 |
33 |
34 |
35 |
36 |
37 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/demos/storage-demo.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 |
9 | Left 10 |
11 |
12 | 13 |
14 | 15 |
16 |
17 | 18 |
19 | Right 20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/demos/vertical-demo.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 | 8 | 9 |
10 | Top 11 |
12 |
13 | 14 |
15 | 16 |
17 |
18 | 19 |
20 | Bottom 21 |
22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/dev/tw-indicator.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | {#if dev} 7 |
10 |
xs
11 | 12 | 13 | 14 | 15 | 16 |
17 | {/if} 18 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/feature-card.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | {title} 15 | 16 |

17 | 18 |

19 |
20 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/icon-grid.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
12 | {#each iconKeys as icon} 13 |
14 |
15 | 16 |
17 |
{icon}
18 |
19 | {/each} 20 |
21 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Callout } from "./callout.svelte"; 2 | export { default as Metadata } from "./metadata.svelte"; 3 | export { default as CopyCodeButton } from "./copy-code-button.svelte"; 4 | export * from "./tabs/index.js"; 5 | export { default as Step } from "./step.svelte"; 6 | export { default as Steps } from "./steps.svelte"; 7 | export { default as IconGrid } from "./icon-grid.svelte"; 8 | export { default as LoadingCard } from "./loading-card.svelte"; 9 | export { default as ViewExampleCode } from "./view-example-code.svelte"; 10 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/footer/footer-icons.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 18 | 28 | 29 |
30 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/footer/footer.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/index.ts: -------------------------------------------------------------------------------- 1 | export * as PageHeader from "./page-header/index.js"; 2 | export { default as Footer } from "./footer/footer.svelte"; 3 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/mobile-nav/mobile-nav-item.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | {#if navItem.items.length} 12 |
{navItem.title}
13 |
    14 | {#each navItem.items as item} 15 | {@const isActive = isTitleActive(currentPath, item.title)} 16 |
  • 17 | 24 | {item.title} 25 | 26 |
  • 27 | {/each} 28 |
29 | {:else} 30 | 34 | {navItem.title} 35 | 36 | {/if} 37 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/mobile-nav/mobile-nav-link.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 26 | 27 | {#if external} 28 | 29 | {/if} 30 | 31 | 32 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/mobile-nav/mobile-nav.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 24 |
25 |
26 |
27 | Navigation 28 | 47 |
48 |
49 |
50 |
51 | 56 | GitHub 57 | 58 |
59 |
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/navbar/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Navbar } from "./navbar.svelte"; 2 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/navbar/navbar-icons.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 | 11 | 20 | 30 | 31 |
32 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/navbar/navbar-logo.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 15 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/navbar/navbar-nav.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 30 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/navbar/navbar.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |
9 | 10 | 11 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/navbar/theme-dropdown.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 15 | 16 | 17 | 18 | {#each modes as themeMode} 19 | setMode(themeMode)} class="capitalize" 20 | >{themeMode} 22 | {/each} 23 | 24 | 25 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/page-header/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Description } from "./page-header-description.svelte"; 2 | export { default as Heading } from "./page-header-heading.svelte"; 3 | export { default as Tagline } from "./page-header-tagline.svelte"; 4 | export { default as Root } from "./page-header.svelte"; 5 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/page-header/page-header-description.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

8 | 9 |

10 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/page-header/page-header-heading.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

8 | 9 |

10 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/page-header/page-header-tagline.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

8 | 9 |

10 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/page-header/page-header.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/sidebar/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Sidebar } from "./sidebar.svelte"; 2 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/sidebar/sidebar-nav-item.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | {#if navItem.items.length} 18 | 19 | {@const titleClasses = 20 | "mb-6 inline-flex w-full items-center justify-between font-medium lg:mb-3 lg:text-sm"} 21 | {#if notCollapsible} 22 |
23 | {navItem.title} 24 |
25 | {:else} 26 | 27 | {navItem.title} 28 | 29 | 30 | {/if} 31 |
    32 | 33 | {#each navItem.items as item} 34 | {@const isActive = item.href 35 | ? isTitleActive(currentPath, slugFromPathname(item.href)) 36 | : false} 37 |
  • 38 | {item.title} 47 |
  • 48 | {/each} 49 |
    50 |
51 |
52 | {:else} 53 | 54 | {navItem.title} 55 | 56 | {/if} 57 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/sidebar/sidebar-nav.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | {#each navigation.sidebar as navItem} 8 |
  • 9 | 10 |
  • 11 | {/each} 12 |
13 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/sidebar/sidebar.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 13 |
14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/toc/index.ts: -------------------------------------------------------------------------------- 1 | export { default as TableOfContents } from "./table-of-contents.svelte"; 2 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/toc/table-of-contents.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 | {#if !$page.error && $headingsTree.length} 24 |
25 | 37 |
38 | {/if} 39 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/layout/toc/tree.svelte: -------------------------------------------------------------------------------- 1 | 35 | 36 |
    37 | {#if tree && tree.length} 38 | {#each tree as heading, i (i)} 39 | {@const node = heading.node.innerHTML} 40 | {@const nodeWithoutSpan = node.replace(//g, "")} 41 |
  • 42 | 59 | 60 | {#if heading.children && heading.children.length} 61 | 68 | {/if} 69 |
  • 70 | {/each} 71 | {/if} 72 |
73 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/loading-card.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 18 |
19 | 20 |
21 |
22 |
23 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/logos/index.ts: -------------------------------------------------------------------------------- 1 | export { default as SvecosystemDark } from "./svecosystem-dark.svelte"; 2 | export { default as SvecosystemLight } from "./svecosystem-light.svelte"; 3 | export { default as PaneforgeDark } from "./paneforge-dark.svelte"; 4 | export { default as PaneforgeLight } from "./paneforge-light.svelte"; 5 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/a.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/blockquote.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 10 |
11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/blueprint.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/code.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/h1.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |

9 | 10 |

11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/h2.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |

12 | 13 |

14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/h3.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |

12 | 13 |

14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/h4.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |

9 | 10 |

11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/h5.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 10 |
11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/h6.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
12 | 13 |
14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/hr.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/img.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/index.ts: -------------------------------------------------------------------------------- 1 | export { default as a } from "./a.svelte"; 2 | export { default as blockquote } from "./blockquote.svelte"; 3 | export { default as h1 } from "./h1.svelte"; 4 | export { default as h2 } from "./h2.svelte"; 5 | export { default as h3 } from "./h3.svelte"; 6 | export { default as h4 } from "./h4.svelte"; 7 | export { default as h5 } from "./h5.svelte"; 8 | export { default as h6 } from "./h6.svelte"; 9 | export { default as hr } from "./hr.svelte"; 10 | export { default as img } from "./img.svelte"; 11 | export { default as li } from "./li.svelte"; 12 | export { default as ol } from "./ol.svelte"; 13 | export { default as p } from "./p.svelte"; 14 | export { default as pre } from "./pre.svelte"; 15 | export { default as table } from "./table.svelte"; 16 | export { default as td } from "./td.svelte"; 17 | export { default as th } from "./th.svelte"; 18 | export { default as tr } from "./tr.svelte"; 19 | export { default as ul } from "./ul.svelte"; 20 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/li.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
  • 9 | 10 |
  • 11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/ol.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
      9 | 10 |
    11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/p.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |

    9 | 10 |

    11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/pre.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
     9 | 		
    10 | 
    11 | 12 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/table.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
    9 | 10 | 11 |
    12 |
    13 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/td.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/th.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/tr.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/markdown/ul.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
      9 | 10 |
    11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/metadata.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | {title} 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | {#if !dev} 38 | 39 | {/if} 40 | 41 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/step.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

    9 | 10 |

    11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/steps.svelte: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/tabs/index.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from "$lib/utils/contextify"; 2 | import type { Writable } from "svelte/store"; 3 | 4 | export const [getTabsCtx, setTabsCtx] = createContext<{ items: Writable }>(); 5 | 6 | export { default as Tabs } from "./tabs.svelte"; 7 | export { default as TabItem } from "./tabs-item.svelte"; 8 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/tabs/tabs-item.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/tabs/tabs.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | {#each $items as item} 14 | 18 | {item} 19 | 20 | {/each} 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/alert/alert-description.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
    12 | 13 |
    14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/alert/alert-title.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/alert/alert.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/alert/index.ts: -------------------------------------------------------------------------------- 1 | import { tv, type VariantProps } from "tailwind-variants"; 2 | 3 | import Root from "./alert.svelte"; 4 | import Description from "./alert-description.svelte"; 5 | import Title from "./alert-title.svelte"; 6 | 7 | export const alertVariants = tv({ 8 | base: "relative w-full rounded-tr-lg rounded-br-lg border-l-4 px-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-6 [&>svg+div]:translate-y-[-3px] pb-4 pt-[22px]", 9 | 10 | variants: { 11 | variant: { 12 | note: "text-foreground [&>svg]:text-sky-800 bg-sky-200 [&>h5]:text-sky-800 border-sky-600 dark:[&>svg]:text-sky-400 dark:bg-sky-500/20 dark:[&>h5]:text-sky-400 dark:border-sky-600", 13 | danger: 14 | "text-foreground [&>svg]:text-red-800 bg-rose-200 [&>h5]:text-red-800 border-rose-600 dark:[&>svg]:text-red-300 dark:bg-rose-500/20 dark:[&>h5]:text-red-300 dark:border-rose-600", 15 | tip: "text-foreground [&>svg]:text-fuchsia-800 bg-fuchsia-200 [&>h5]:text-fuchsia-800 border-fuchsia-600 dark:[&>svg]:text-fuchsia-400 dark:bg-fuchsia-500/20 dark:[&>h5]:text-fuchsia-400 dark:border-fuchsia-600", 16 | warning: 17 | "text-foreground [&>svg]:text-amber-800 bg-amber-200 [&>h5]:text-amber-800 border-amber-600 dark:[&>svg]:text-amber-400 dark:bg-amber-500/20 dark:[&>h5]:text-amber-400 dark:border-amber-600", 18 | }, 19 | }, 20 | defaultVariants: { 21 | variant: "note", 22 | }, 23 | }); 24 | 25 | export type Variant = VariantProps["variant"]; 26 | export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; 27 | 28 | export { 29 | Root, 30 | Description, 31 | Title, 32 | // 33 | Root as Alert, 34 | Description as AlertDescription, 35 | Title as AlertTitle, 36 | }; 37 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/button/button.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/button/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./button.svelte"; 2 | import { tv, type VariantProps } from "tailwind-variants"; 3 | import type { Button as ButtonPrimitive } from "bits-ui"; 4 | 5 | const buttonVariants = tv({ 6 | base: "inline-flex items-center justify-center rounded-md text-sm font-medium whitespace-nowrap ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 active:scale-98", 7 | variants: { 8 | variant: { 9 | default: "bg-primary text-primary-foreground hover:bg-primary/90", 10 | destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", 11 | outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground", 12 | secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", 13 | ghost: "hover:bg-accent hover:text-accent-foreground", 14 | link: "text-primary underline-offset-4 hover:underline", 15 | subtle: "text-muted-foreground hover:text-foreground", 16 | brand: "bg-brand text-background hover:bg-brand/90 font-semibold", 17 | }, 18 | size: { 19 | default: "h-10 px-4 py-2", 20 | sm: "h-9 rounded-md px-3", 21 | lg: "h-11 rounded-md px-8", 22 | icon: "h-10 w-10", 23 | }, 24 | }, 25 | defaultVariants: { 26 | variant: "default", 27 | size: "default", 28 | }, 29 | }); 30 | 31 | type Variant = VariantProps["variant"]; 32 | type Size = VariantProps["size"]; 33 | 34 | type Props = ButtonPrimitive.Props & { 35 | variant?: Variant; 36 | size?: Size; 37 | }; 38 | 39 | type Events = ButtonPrimitive.Events; 40 | 41 | export { 42 | Root, 43 | type Props, 44 | type Events, 45 | // 46 | Root as Button, 47 | type Props as ButtonProps, 48 | type Events as ButtonEvents, 49 | buttonVariants, 50 | }; 51 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/card/card-content.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
    12 | 13 |
    14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/card/card-description.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |

    12 | 13 |

    14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/card/card-footer.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
    12 | 13 |
    14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/card/card-header.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
    12 | 13 |
    14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/card/card-title.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/card/card.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
    15 | 16 |
    17 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/card/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./card.svelte"; 2 | import Content from "./card-content.svelte"; 3 | import Description from "./card-description.svelte"; 4 | import Footer from "./card-footer.svelte"; 5 | import Header from "./card-header.svelte"; 6 | import Title from "./card-title.svelte"; 7 | 8 | export { 9 | Root, 10 | Content, 11 | Description, 12 | Footer, 13 | Header, 14 | Title, 15 | // 16 | Root as Card, 17 | Content as CardContent, 18 | Description as CardDescription, 19 | Footer as CardFooter, 20 | Header as CardHeader, 21 | Title as CardTitle, 22 | }; 23 | 24 | export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; 25 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/checkbox/checkbox.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | 28 | {#if isChecked} 29 | 30 | {:else if isIndeterminate} 31 | 32 | {/if} 33 | 34 | 35 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./checkbox.svelte"; 2 | export { 3 | Root, 4 | // 5 | Root as Checkbox, 6 | }; 7 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/collapsible/collapsible-content.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/collapsible/index.ts: -------------------------------------------------------------------------------- 1 | import { Collapsible as CollapsiblePrimitive } from "bits-ui"; 2 | import Content from "./collapsible-content.svelte"; 3 | 4 | const Root = CollapsiblePrimitive.Root; 5 | const Trigger = CollapsiblePrimitive.Trigger; 6 | 7 | export { 8 | Root, 9 | Content, 10 | Trigger, 11 | // 12 | Root as Collapsible, 13 | Content as CollapsibleContent, 14 | Trigger as CollapsibleTrigger, 15 | }; 16 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/dropdown-menu/index.ts: -------------------------------------------------------------------------------- 1 | import { DropdownMenu as DropdownMenuPrimitive } from "bits-ui"; 2 | import Item from "./dropdown-menu-item.svelte"; 3 | import Label from "./dropdown-menu-label.svelte"; 4 | import Content from "./dropdown-menu-content.svelte"; 5 | import Shortcut from "./dropdown-menu-shortcut.svelte"; 6 | import RadioItem from "./dropdown-menu-radio-item.svelte"; 7 | import Separator from "./dropdown-menu-separator.svelte"; 8 | import RadioGroup from "./dropdown-menu-radio-group.svelte"; 9 | import SubContent from "./dropdown-menu-sub-content.svelte"; 10 | import SubTrigger from "./dropdown-menu-sub-trigger.svelte"; 11 | import CheckboxItem from "./dropdown-menu-checkbox-item.svelte"; 12 | 13 | const Sub = DropdownMenuPrimitive.Sub; 14 | const Root = DropdownMenuPrimitive.Root; 15 | const Trigger = DropdownMenuPrimitive.Trigger; 16 | const Group = DropdownMenuPrimitive.Group; 17 | 18 | export { 19 | Sub, 20 | Root, 21 | Item, 22 | Label, 23 | Group, 24 | Trigger, 25 | Content, 26 | Shortcut, 27 | Separator, 28 | RadioItem, 29 | SubContent, 30 | SubTrigger, 31 | RadioGroup, 32 | CheckboxItem, 33 | // 34 | Root as DropdownMenu, 35 | Sub as DropdownMenuSub, 36 | Item as DropdownMenuItem, 37 | Label as DropdownMenuLabel, 38 | Group as DropdownMenuGroup, 39 | Content as DropdownMenuContent, 40 | Trigger as DropdownMenuTrigger, 41 | Shortcut as DropdownMenuShortcut, 42 | RadioItem as DropdownMenuRadioItem, 43 | Separator as DropdownMenuSeparator, 44 | RadioGroup as DropdownMenuRadioGroup, 45 | SubContent as DropdownMenuSubContent, 46 | SubTrigger as DropdownMenuSubTrigger, 47 | CheckboxItem as DropdownMenuCheckboxItem, 48 | }; 49 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/input/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./input.svelte"; 2 | 3 | type FormInputEvent = T & { 4 | currentTarget: EventTarget & HTMLInputElement; 5 | }; 6 | export type InputEvents = { 7 | blur: FormInputEvent; 8 | change: FormInputEvent; 9 | click: FormInputEvent; 10 | focus: FormInputEvent; 11 | focusin: FormInputEvent; 12 | focusout: FormInputEvent; 13 | keydown: FormInputEvent; 14 | keypress: FormInputEvent; 15 | keyup: FormInputEvent; 16 | mouseover: FormInputEvent; 17 | mouseenter: FormInputEvent; 18 | mouseleave: FormInputEvent; 19 | paste: FormInputEvent; 20 | input: FormInputEvent; 21 | }; 22 | 23 | export { 24 | Root, 25 | // 26 | Root as Input, 27 | }; 28 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/input/input.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 36 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/label/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./label.svelte"; 2 | 3 | export const labelClasses = 4 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"; 5 | 6 | export { 7 | Root, 8 | // 9 | Root as Label, 10 | }; 11 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/label/label.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/radio-group/index.ts: -------------------------------------------------------------------------------- 1 | import { RadioGroup as RadioGroupPrimitive } from "bits-ui"; 2 | 3 | import Root from "./radio-group.svelte"; 4 | import Item from "./radio-group-item.svelte"; 5 | const Input = RadioGroupPrimitive.Input; 6 | 7 | export { 8 | Root, 9 | Input, 10 | Item, 11 | // 12 | Root as RadioGroup, 13 | Input as RadioGroupInput, 14 | Item as RadioGroupItem, 15 | }; 16 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/radio-group/radio-group-item.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 |
    24 | 25 | 26 | 27 |
    28 |
    29 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/radio-group/radio-group.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/select/index.ts: -------------------------------------------------------------------------------- 1 | import { Select as SelectPrimitive } from "bits-ui"; 2 | 3 | import Label from "./select-label.svelte"; 4 | import Item from "./select-item.svelte"; 5 | import Content from "./select-content.svelte"; 6 | import Trigger from "./select-trigger.svelte"; 7 | import Separator from "./select-separator.svelte"; 8 | 9 | const Root = SelectPrimitive.Root; 10 | const Group = SelectPrimitive.Group; 11 | const Input = SelectPrimitive.Input; 12 | const Value = SelectPrimitive.Value; 13 | 14 | export { 15 | Root, 16 | Group, 17 | Input, 18 | Label, 19 | Item, 20 | Value, 21 | Content, 22 | Trigger, 23 | Separator, 24 | // 25 | Root as Select, 26 | Group as SelectGroup, 27 | Input as SelectInput, 28 | Label as SelectLabel, 29 | Item as SelectItem, 30 | Value as SelectValue, 31 | Content as SelectContent, 32 | Trigger as SelectTrigger, 33 | Separator as SelectSeparator, 34 | }; 35 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/select/select-content.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 | 36 |
    37 | 38 |
    39 |
    40 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/select/select-item.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | {label} 39 | 40 | 41 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/select/select-label.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/select/select-separator.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/select/select-trigger.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | span]:line-clamp-1", 16 | className 17 | )} 18 | {...$$restProps} 19 | let:builder 20 | on:click 21 | on:keydown 22 | > 23 | 24 |
    25 | 26 |
    27 |
    28 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/separator/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./separator.svelte"; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Separator, 7 | }; 8 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/separator/separator.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 23 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/skeleton/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./skeleton.svelte"; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Skeleton, 7 | }; 8 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/skeleton/skeleton.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 |
    12 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/slider/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./slider.svelte"; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Slider, 7 | }; 8 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/slider/slider.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | 19 | 20 | 21 | {#each thumbs as thumb} 22 | 26 | {/each} 27 | 28 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/sonner/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Toaster } from "./sonner.svelte"; 2 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/sonner/sonner.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 22 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/switch/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./switch.svelte"; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Switch, 7 | }; 8 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/switch/switch.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 20 | 25 | 26 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/tabs/index.ts: -------------------------------------------------------------------------------- 1 | import { Tabs as TabsPrimitive } from "bits-ui"; 2 | import Content from "./tabs-content.svelte"; 3 | import List from "./tabs-list.svelte"; 4 | import Trigger from "./tabs-trigger.svelte"; 5 | 6 | const Root = TabsPrimitive.Root; 7 | 8 | export { 9 | Root, 10 | Content, 11 | List, 12 | Trigger, 13 | // 14 | Root as Tabs, 15 | Content as TabsContent, 16 | List as TabsList, 17 | Trigger as TabsTrigger, 18 | }; 19 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/tabs/tabs-content.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/tabs/tabs-list.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/tabs/tabs-trigger.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/textarea/index.ts: -------------------------------------------------------------------------------- 1 | import Root from "./textarea.svelte"; 2 | 3 | type FormTextareaEvent = T & { 4 | currentTarget: EventTarget & HTMLTextAreaElement; 5 | }; 6 | 7 | type TextareaEvents = { 8 | blur: FormTextareaEvent; 9 | change: FormTextareaEvent; 10 | click: FormTextareaEvent; 11 | focus: FormTextareaEvent; 12 | keydown: FormTextareaEvent; 13 | keypress: FormTextareaEvent; 14 | keyup: FormTextareaEvent; 15 | mouseover: FormTextareaEvent; 16 | mouseenter: FormTextareaEvent; 17 | mouseleave: FormTextareaEvent; 18 | paste: FormTextareaEvent; 19 | input: FormTextareaEvent; 20 | }; 21 | 22 | export { 23 | Root, 24 | // 25 | Root as Textarea, 26 | type TextareaEvents, 27 | type FormTextareaEvent, 28 | }; 29 | -------------------------------------------------------------------------------- /sites/docs/src/lib/components/ui/textarea/textarea.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |