├── .commitlintrc.cjs ├── .cz-config.cjs ├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ ├── ci.yml │ ├── conventional-pr-title.yml │ ├── docs.yml │ ├── packaging-check.yml │ └── release-please.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── eslint.config.js ├── example ├── .gitignore ├── .npmrc ├── README.md ├── package.json ├── src │ ├── app.d.ts │ ├── app.html │ └── routes │ │ ├── +layout.ts │ │ └── +page.svelte ├── static │ └── favicon.png ├── svelte.config.js ├── tsconfig.json └── vite.config.ts ├── package.json ├── playwright.config.ts ├── pnpm-lock.yaml ├── scripts ├── create-minified-size-badges.js ├── example │ ├── pnpm-install-project-in-example-temp.js │ └── verify-example-build.js ├── fetch-and-publish.js ├── package-clean-copy.js └── vite │ ├── example-import.js │ ├── highlight-languages.d.ts │ └── minified-size-analyzing.js ├── src ├── app.d.ts ├── app.html ├── comp │ ├── Button.svelte │ ├── Contents.svelte │ ├── ExampleArea.svelte │ ├── Highlighted.svelte │ ├── PrerenderedArea.svelte │ ├── RTLToggle.svelte │ ├── Ripple.svelte │ ├── TextAreaAutosize.svelte │ ├── ToggleButton.svelte │ ├── example.d.ts │ └── examples-loading.d.ts ├── lib │ ├── Pane.svelte │ ├── Splitpanes.svelte │ ├── index.ts │ └── internal │ │ ├── .npmignore │ │ ├── GatheringRound.svelte │ │ ├── default-theme.scss │ │ ├── env.ts │ │ └── utils │ │ ├── array.ts │ │ ├── functions.ts │ │ ├── position.ts │ │ ├── sizing.ts │ │ └── styling.ts ├── routes │ ├── +layout.svelte │ ├── +layout.ts │ ├── +page.svelte │ ├── +page.ts │ ├── examples │ │ ├── add-remove-panes │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── change-orientation │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── default-size │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── disable-dbl-click │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── listen-to-events │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── lock-layout │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── min-max │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── prog-resize │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── push-other-panes │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── reordering-panes │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ │ ├── snap │ │ │ ├── middle │ │ │ │ ├── +page.svelte │ │ │ │ ├── +page.ts │ │ │ │ └── code.svelte │ │ │ ├── min-max │ │ │ │ ├── +page.svelte │ │ │ │ ├── +page.ts │ │ │ │ └── code.svelte │ │ │ └── simple │ │ │ │ ├── +page.svelte │ │ │ │ ├── +page.ts │ │ │ │ └── code.svelte │ │ ├── styling │ │ │ ├── app-layout │ │ │ │ ├── +page.svelte │ │ │ │ ├── +page.ts │ │ │ │ └── code.svelte │ │ │ └── splitters │ │ │ │ ├── +page.svelte │ │ │ │ ├── +page.ts │ │ │ │ └── code.svelte │ │ └── toggle-panes │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ └── code.svelte │ ├── minified-size │ │ └── +page.svelte │ ├── pathUtils.ts │ └── test │ │ ├── +page.svelte │ │ └── +page.ts └── type_decl.d.ts ├── static ├── .nojekyll ├── favicon.png ├── favicon.svg ├── minified-size-badge.svg ├── robots.txt └── screenshot.jpg ├── svelte.config.js ├── tests └── addRemoveSplitter.spec.ts ├── tsconfig.json └── vite.config.js /.commitlintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'header-max-length': [0, 'always', 100], 5 | 'scope-case': [0, 'always', 'pascal-case'] 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /.cz-config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | types: [ 3 | { value: 'feat', name: '✨ feat:\tAdding a new feature' }, 4 | { value: 'fix', name: '🐛 fix:\tFixing a bug' }, 5 | { value: 'docs', name: '📝 docs:\tAdd or update documentation' }, 6 | { 7 | value: 'style', 8 | name: '💄 style:\tAdd or update styles, ui or ux' 9 | }, 10 | { 11 | value: 'refactor', 12 | name: '♻️ refactor:\tCode change that neither fixes a bug nor adds a feature' 13 | }, 14 | { 15 | value: 'perf', 16 | name: '⚡️ perf:\tCode change that improves performance' 17 | }, 18 | { 19 | value: 'test', 20 | name: '✅ test:\tAdding tests cases' 21 | }, 22 | { 23 | value: 'chore', 24 | name: '🚚 chore:\tChanges to the build process or auxiliary tools\n\t\tand libraries such as documentation generation' 25 | }, 26 | { value: 'revert', name: '⏪️ revert:\tRevert to a commit' }, 27 | { 28 | value: 'build', 29 | name: '👷 build:\tAdd or update regards to build process' 30 | }, 31 | { 32 | value: 'ci', 33 | name: '💚 ci:\tAdd or update regards to build process' 34 | } 35 | ], 36 | scopes: [], 37 | 38 | scopeOverrides: { 39 | fix: [{ name: 'merge' }, { name: 'style' }, { name: 'test' }, { name: 'hotfix' }] 40 | }, 41 | 42 | allowCustomScopes: true, 43 | allowBreakingChanges: ['feat', 'fix'], 44 | // skip any questions you want 45 | skipQuestions: ['scope', 'footer', 'breaking'], 46 | subjectLimit: 100 47 | }; 48 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Make sure the line ending is in LF format (/n), for linting consistency 2 | * text eol=lf -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: orefalo 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | tests: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 15 9 | 10 | steps: 11 | # Checkout 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | 15 | # The whole Node.js and pnpm installation and caching 16 | # Based on https://github.com/pnpm/action-setup/tree/6e1964dde3397a825e79e4607ad57f3f7ca2c7cb#use-cache-to-reduce-installation-time 17 | 18 | - name: Install Node.js 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: 20 22 | 23 | - uses: pnpm/action-setup@v4 24 | name: Install pnpm 25 | id: pnpm-install 26 | with: 27 | version: 9 28 | run_install: false 29 | 30 | - name: Get pnpm store directory 31 | id: pnpm-cache 32 | run: | 33 | echo "pnpm_cache_dir=$(pnpm store path)" >> ${GITHUB_OUTPUT} 34 | 35 | - uses: actions/cache@v4 36 | name: Setup pnpm cache 37 | with: 38 | path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} 39 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 40 | restore-keys: | 41 | ${{ runner.os }}-pnpm-store- 42 | 43 | - name: Install dependencies 44 | run: pnpm install --frozen-lockfile 45 | 46 | - name: SvelteKit Sync 47 | run: npx svelte-kit sync 48 | 49 | - name: Lint 50 | run: pnpm run lint 51 | 52 | - name: Svelte Sync 53 | if: success() || failure() # Run even if previous failed 54 | run: npx svelte-kit sync 55 | 56 | - name: Svelte Check 57 | if: success() || failure() # Run even if previous failed 58 | run: pnpm run check 59 | 60 | # Build Frontend 61 | - name: Build Frontend 62 | if: success() || failure() # Run even if previous failed 63 | run: pnpm run build 64 | 65 | # Cache Playwright 66 | - name: Cache Playwright 67 | if: success() || failure() # Run even if previous failed 68 | uses: actions/cache@v4 69 | id: playwright_cache 70 | with: 71 | path: ~/.cache/ms-playwright 72 | key: ${{ runner.os }} # (not a good key) 73 | 74 | # Install Playwright 75 | - name: Install Playwright 76 | # if: steps.cache.outputs.cache-hit != 'true' 77 | run: npx playwright install --with-deps 78 | 79 | # Run Tests 80 | - name: Test 81 | run: pnpm run test 82 | env: 83 | DEBUG: pw:webserver 84 | 85 | # Upload test results 86 | - name: Upload test results 87 | uses: actions/upload-artifact@v4 88 | with: 89 | name: test-results 90 | path: test-results 91 | -------------------------------------------------------------------------------- /.github/workflows/conventional-pr-title.yml: -------------------------------------------------------------------------------- 1 | name: Check PR title 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - reopened 8 | - edited 9 | - synchronize 10 | 11 | jobs: 12 | lint: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: aslafy-z/conventional-pr-title-action@v3 16 | env: 17 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Generating Docs 2 | 3 | permissions: 4 | contents: write 5 | 6 | on: 7 | push: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build-and-deploy: 13 | concurrency: ci-${{ github.ref }} # Recommended if you intend to make multiple deployments in quick succession. 14 | runs-on: ubuntu-latest 15 | timeout-minutes: 15 16 | 17 | steps: 18 | # Checkout 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | 22 | # The whole Node.js and pnpm installation and caching 23 | # Based on https://github.com/pnpm/action-setup/tree/6e1964dde3397a825e79e4607ad57f3f7ca2c7cb#use-cache-to-reduce-installation-time 24 | 25 | - name: Install Node.js 26 | uses: actions/setup-node@v4 27 | with: 28 | node-version: 20 29 | 30 | - uses: pnpm/action-setup@v4 31 | name: Install pnpm 32 | id: pnpm-install 33 | with: 34 | version: 9 35 | run_install: false 36 | 37 | - name: Get pnpm store directory 38 | id: pnpm-cache 39 | run: | 40 | echo "pnpm_cache_dir=$(pnpm store path)" >> ${GITHUB_OUTPUT} 41 | 42 | - uses: actions/cache@v4 43 | name: Setup pnpm cache 44 | with: 45 | path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} 46 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 47 | restore-keys: | 48 | ${{ runner.os }}-pnpm-store- 49 | 50 | - name: Install dependencies 51 | run: pnpm install --frozen-lockfile 52 | 53 | - name: Svelte Sync 54 | run: npx svelte-kit sync 55 | 56 | # Build Frontend 57 | - name: Build Frontend 58 | run: pnpm run build 59 | env: 60 | BASE_PATH: /svelte-splitpanes 61 | 62 | # Deploy Docs 63 | - name: Deploy Docs 🚀 64 | uses: JamesIves/github-pages-deploy-action@v4 65 | with: 66 | folder: docs 67 | target-folder: docs 68 | -------------------------------------------------------------------------------- /.github/workflows/packaging-check.yml: -------------------------------------------------------------------------------- 1 | name: Packaging Check 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | tests: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 15 9 | 10 | steps: 11 | # Checkout 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | 15 | # The whole Node.js and pnpm installation and caching 16 | # Based on https://github.com/pnpm/action-setup/tree/6e1964dde3397a825e79e4607ad57f3f7ca2c7cb#use-cache-to-reduce-installation-time 17 | 18 | - name: Install Node.js 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: 20 22 | 23 | - uses: pnpm/action-setup@v4 24 | name: Install pnpm 25 | id: pnpm-install 26 | with: 27 | version: 9 28 | run_install: false 29 | 30 | - name: Get pnpm store directory 31 | id: pnpm-cache 32 | run: | 33 | echo "pnpm_cache_dir=$(pnpm store path)" >> ${GITHUB_OUTPUT} 34 | 35 | - uses: actions/cache@v4 36 | name: Setup pnpm cache 37 | with: 38 | path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} 39 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 40 | restore-keys: | 41 | ${{ runner.os }}-pnpm-store- 42 | 43 | - name: Install dependencies 44 | run: pnpm install --frozen-lockfile 45 | 46 | - name: SvelteKit Sync 47 | run: npx svelte-kit sync 48 | 49 | - name: Package the lib 50 | run: pnpm run package 51 | 52 | - name: Setup example test 53 | run: pnpm run example-build:setup 54 | 55 | - name: Build example 56 | run: pnpm run example-build:build 57 | 58 | - name: Simple test 59 | run: pnpm run example-build:test 60 | 61 | # Upload test results 62 | - name: Upload example build 63 | uses: actions/upload-artifact@v3 64 | with: 65 | name: example-build 66 | path: example-temp/demo 67 | -------------------------------------------------------------------------------- /.github/workflows/release-please.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | name: release-please 6 | jobs: 7 | release-please: 8 | if: github.repository == 'orefalo/svelte-splitpanes' # Prevent running on forks 9 | runs-on: ubuntu-latest 10 | steps: 11 | # Checkout 12 | - name: Checkout 13 | uses: actions/checkout@v4 14 | 15 | # The whole Node.js and pnpm installation and caching 16 | # Based on https://github.com/pnpm/action-setup/tree/6e1964dde3397a825e79e4607ad57f3f7ca2c7cb#use-cache-to-reduce-installation-time 17 | 18 | - name: Install Node.js 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: 20 22 | 23 | - uses: pnpm/action-setup@v4 24 | name: Install pnpm 25 | id: pnpm-install 26 | with: 27 | version: 9 28 | run_install: false 29 | 30 | - name: Get pnpm store directory 31 | id: pnpm-cache 32 | run: | 33 | echo "pnpm_cache_dir=$(pnpm store path)" >> ${GITHUB_OUTPUT} 34 | - uses: actions/cache@v4 35 | name: Setup pnpm cache 36 | with: 37 | path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} 38 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 39 | restore-keys: | 40 | ${{ runner.os }}-pnpm-store- 41 | - name: Install dependencies 42 | run: pnpm install --frozen-lockfile 43 | 44 | - name: SvelteKit Sync 45 | run: npx svelte-kit sync 46 | 47 | - name: Svelte Package 48 | run: pnpm run package 49 | 50 | - name: Release Please 51 | uses: googleapis/release-please-action@v4 52 | id: release 53 | with: 54 | release-type: node 55 | 56 | - name: Upload the packed package 57 | uses: actions/upload-release-asset@v1 58 | if: ${{ steps.release.outputs.release_created }} 59 | env: 60 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 61 | with: 62 | node-version: 20 63 | upload_url: ${{ steps.release.outputs.upload_url }} 64 | asset_path: package/svelte-splitpanes-${{ steps.release.outputs.version }}.tgz 65 | asset_name: svelte-splitpanes-${{ steps.release.outputs.version }}.tgz 66 | asset_content_type: application/gzip 67 | 68 | - name: Publish to NPM 69 | uses: JS-DevTools/npm-publish@v3 70 | with: 71 | token: ${{ secrets.NPM_TOKEN }} 72 | package: package/ 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | **/node_modules/* 3 | /build 4 | /.svelte-kit 5 | /package 6 | /docs 7 | /example-temp 8 | /test-results 9 | .env 10 | .env.* 11 | !.env.example 12 | *.log 13 | .eslintcache 14 | vite.config.js.timestamp-* -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | npx --no -- commitlint --edit "${1}" -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | # pnpm test 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore files for PNPM, NPM and YARN 2 | pnpm-lock.yaml 3 | package-lock.json 4 | yarn.lock 5 | **/.svelte-kit -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": false, 3 | "tabWidth": 2, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte"], 7 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }], 8 | "htmlWhitespaceSensitivity": "ignore", 9 | "bracketSameLine": true, 10 | "semi": true, 11 | "singleQuote": true, 12 | "arrowParens": "avoid" 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.svn": true, 5 | "**/.hg": true, 6 | "**/CVS": true, 7 | "**/.DS_Store": true, 8 | "**/Thumbs.db": true 9 | }, 10 | "hide-files.files": [], 11 | "files.eol": "\n", 12 | "editor.insertSpaces": false, 13 | "[typescript]": { 14 | "editor.tabSize": 4 15 | }, 16 | "[javascript]": { 17 | "editor.tabSize": 4 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ## [8.0.9](https://github.com/orefalo/svelte-splitpanes/compare/v8.0.8...v8.0.9) (2024-10-30) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * support for svelte5 ([91b395f](https://github.com/orefalo/svelte-splitpanes/commit/91b395f179ec89679dd5e845f49dce94faa23462)) 11 | 12 | ## [8.0.8](https://github.com/orefalo/svelte-splitpanes/compare/v8.0.7...v8.0.8) (2024-10-05) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * a regression related to safe callbacks which could generate a 0 width upon certain race conditions ([af34b41](https://github.com/orefalo/svelte-splitpanes/commit/af34b41a9974cd7203d3a0be2cb567666fbcf124)) 18 | 19 | ## [8.0.7](https://github.com/orefalo/svelte-splitpanes/compare/v8.0.6...v8.0.7) (2024-10-05) 20 | 21 | 22 | ### Bug Fixes 23 | 24 | * better handling of empty attributes ([7c9c4ad](https://github.com/orefalo/svelte-splitpanes/commit/7c9c4add390f1025c68b13ee9a3e6fa1df706754)) 25 | 26 | ## [8.0.6](https://github.com/orefalo/svelte-splitpanes/compare/v8.0.5...v8.0.6) (2024-09-24) 27 | 28 | 29 | ### Bug Fixes 30 | 31 | * fix panel pushing bug introduct in 0.8.3 ([b4c71f8](https://github.com/orefalo/svelte-splitpanes/commit/b4c71f8a22c512d77eed0ad533f7b7989f69db61)) 32 | 33 | ## [8.0.5](https://github.com/orefalo/svelte-splitpanes/compare/v8.0.4...v8.0.5) (2024-06-16) 34 | 35 | 36 | ### Miscellaneous Chores 37 | 38 | * release 8.0.5 ([9f7ec2e](https://github.com/orefalo/svelte-splitpanes/commit/9f7ec2e317594b4079ccb39a5c1292fb3c705bba)) 39 | 40 | ## [8.0.4](https://github.com/orefalo/svelte-splitpanes/compare/v0.8.3...v8.0.4) (2024-06-16) 41 | 42 | 43 | ### Miscellaneous Chores 44 | 45 | * release 8.0.4 ([fbd210a](https://github.com/orefalo/svelte-splitpanes/commit/fbd210a0a598f7c70c98f34fc51d7201fc7288b1)) 46 | 47 | ## [0.8.3](https://github.com/orefalo/svelte-splitpanes/compare/v0.8.2...v0.8.3) (2024-06-15) 48 | 49 | 50 | ### Bug Fixes 51 | 52 | * events are now passive by default, remove preventDefaults() in the code ([1bc9045](https://github.com/orefalo/svelte-splitpanes/commit/1bc90455c558e40b174c2270d19ea0e4636d912e)) 53 | 54 | ## [0.8.2](https://github.com/orefalo/svelte-splitpanes/compare/v0.8.1...v0.8.2) (2024-06-10) 55 | 56 | 57 | ### Miscellaneous Chores 58 | 59 | * release 0.8.1 ([14170b6](https://github.com/orefalo/svelte-splitpanes/commit/14170b6fe0c842f9016b26d1aaddc91fa3eae061)) 60 | * release 0.8.2 ([19e6b20](https://github.com/orefalo/svelte-splitpanes/commit/19e6b207ad8a179d6c9a05c49d07a45c2ebb25c0)) 61 | 62 | ## [0.8.1](https://github.com/orefalo/svelte-splitpanes/compare/v0.8.1...v0.8.1) (2024-06-10) 63 | 64 | 65 | ### Miscellaneous Chores 66 | 67 | * release 0.8.1 ([14170b6](https://github.com/orefalo/svelte-splitpanes/commit/14170b6fe0c842f9016b26d1aaddc91fa3eae061)) 68 | 69 | ## [0.8.1](https://github.com/orefalo/svelte-splitpanes/compare/v0.8.0...v0.8.1) (2024-06-10) 70 | 71 | 72 | ### Bug Fixes 73 | 74 | * now efficiently identify if client supports passive events, fixes [#74](https://github.com/orefalo/svelte-splitpanes/issues/74) ([f2d7ed1](https://github.com/orefalo/svelte-splitpanes/commit/f2d7ed1da856386287a2065d66c79f9fb63706c3)) 75 | 76 | ## [0.8.0](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.15...v0.8.0) (2023-07-03) 77 | 78 | 79 | ### Miscellaneous Chores 80 | 81 | * update to svelte 4 ([ddb4402](https://github.com/orefalo/svelte-splitpanes/commit/ddb44027ef8a15f63ae01dbcdea8c957e4c82662)) 82 | 83 | ## [0.7.15](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.14...v0.7.15) (2023-06-14) 84 | 85 | 86 | ### Bug Fixes 87 | 88 | * fix issue 69 - dblClickSplitter={false} does not disable auto-resizing ([8e38809](https://github.com/orefalo/svelte-splitpanes/commit/8e38809b59fb28bbe89816300f3325347e1d6424)) 89 | * set-output is deprecated ([451509b](https://github.com/orefalo/svelte-splitpanes/commit/451509b4f83b39de6f0cbc36c8a7dcde9a495796)) 90 | 91 | ## [0.7.14](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.13...v0.7.14) (2023-06-03) 92 | 93 | 94 | ### Bug Fixes 95 | 96 | * fix github actions to support node16 ([47ee00c](https://github.com/orefalo/svelte-splitpanes/commit/47ee00c01a9afb55e4ed922123a57be81295e713)) 97 | 98 | ## [0.7.13](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.12...v0.7.13) (2023-02-27) 99 | 100 | 101 | ### Bug Fixes 102 | 103 | * ignoring the annoying Svelte `a11y-click-events-have-key-events` warnings ([7d9b872](https://github.com/orefalo/svelte-splitpanes/commit/7d9b872f3fc2848310124e96ed220da7f2ffe934)) 104 | 105 | ## [0.7.12](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.11...v0.7.12) (2023-01-25) 106 | 107 | 108 | ### Bug Fixes 109 | 110 | * avoid equalizing on the edge case that there is not even a single pane ([0adb387](https://github.com/orefalo/svelte-splitpanes/commit/0adb38772490d61e84af4eb893af33c1483c4319)) 111 | * cleaner dragging calculation, and omit the buggy `margin-left: -1px;` from the splitter ([b453d74](https://github.com/orefalo/svelte-splitpanes/commit/b453d74ee7aff3c4812a3de2f2bbd2372ad597f3)) 112 | 113 | ## [0.7.11](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.10...v0.7.11) (2023-01-09) 114 | 115 | 116 | ### Features 117 | 118 | * add the \`strictEvents\` attribute to components, so the user will know that no other events happen ([db15de3](https://github.com/orefalo/svelte-splitpanes/commit/db15de3f79994690e5a259ca78e7b603c0012e2c)) 119 | 120 | 121 | ### Bug Fixes 122 | 123 | * require svelte to be installed as a peer dependency ([ec13655](https://github.com/orefalo/svelte-splitpanes/commit/ec136552979b37f28f25edb16c62fa19f2928a9c)) 124 | * ssr issue on partially defined sizes ([5fb6661](https://github.com/orefalo/svelte-splitpanes/commit/5fb6661b7bd5d1b388a9e4ecd390a528eccce281)) 125 | 126 | 127 | ### Miscellaneous Chores 128 | 129 | * release 0.7.11 ([1df8854](https://github.com/orefalo/svelte-splitpanes/commit/1df8854bcf66365c39cd04ece32d6a5ce5a92287)) 130 | 131 | ## [0.7.10](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.9...v0.7.10) (2023-01-02) 132 | 133 | ### Miscellaneous Chores 134 | 135 | - release 0.7.10 (you may change the title) ([c23db34](https://github.com/orefalo/svelte-splitpanes/commit/c23db34b446e361bd89a8db694b5682c1303b964)) 136 | 137 | ## [0.7.9](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.3...v0.7.9) (2022-12-28) 138 | 139 | ### Bug Fixes 140 | 141 | - pane object not being returned ([#45](https://github.com/orefalo/svelte-splitpanes/issues/45)) ([118a1ad](https://github.com/orefalo/svelte-splitpanes/commit/118a1ad1a19682feaf7175136bdc6c796fb6a542)) 142 | 143 | ### Miscellaneous Chores 144 | 145 | - bump version to 0.7.9 ([16b7fab](https://github.com/orefalo/svelte-splitpanes/commit/16b7fab73cd011b5dba1dcfdd0b00a1f2c8d486d)) 146 | 147 | ### [0.7.8](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.7...v0.7.8) (2022-12-28) 148 | 149 | - npm re-releasing only 150 | 151 | ### [0.7.7](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.4...v0.7.7) (2022-12-28) 152 | 153 | ### Features 154 | 155 | - finally allow a correct two-way binding to the pane sizes 156 | - reimplement splitter double click expansion 157 | - support panes reordering by keyed each blocks, closes #35 158 | 159 | ### Bug Fixes 160 | 161 | - fix pane object not being returned ([#45](https://github.com/orefalo/svelte-splitpanes/issues/45)) ([118a1ad](https://github.com/orefalo/svelte-splitpanes/commit/118a1ad1a19682feaf7175136bdc6c796fb6a542)) 162 | 163 | ### [0.7.6](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.5...v0.7.6) (2022-12-20) 164 | 165 | - simpler and more intuitive sizing after panes adding/removing 166 | - code optimizations 167 | 168 | ### [0.7.5](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.4...v0.7.5) (2022-12-20) 169 | 170 | - demo site now has a cleaner layout 171 | - implemented proper browser detection client side 172 | - code optimizations 173 | 174 | ### [0.7.4](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.3...v0.7.4) (2022-12-12) 175 | 176 | - attempt to fix browser detection in library mode, seems to be an issue with sveltekit 177 | 178 | ### [0.7.3](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.2...v0.7.3) (2022-08-04) 179 | 180 | - active splitter is now styled with a class 181 | - improved dragging precission 182 | 183 | ### [0.7.2](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.1...v0.7.2) (2022-08-01) 184 | 185 | - fix jitter issue on double clicks 186 | 187 | ### [0.7.1](https://github.com/orefalo/svelte-splitpanes/compare/v0.7.0...v0.7.1) (2022-06-30) 188 | 189 | - fix #31 - incorrect single pane width calculation when removing panes and resizing sliders 190 | - in the "Pragramatic resizing demo", fix the double slider buttons 191 | 192 | ## [0.7.0](https://github.com/orefalo/svelte-splitpanes/compare/v0.6.12...v0.7.0) (2022-06-29) 193 | 194 | ### Features 195 | 196 | - add edge snapping ([b6cb06d](https://github.com/orefalo/svelte-splitpanes/commit/b6cb06d94cec4027971322c92a151aee0130d601)) 197 | - add License and Code of conduct ([c8e9ecd](https://github.com/BearToCode/svelte-splitpanes/commit/c8e9ecd9809a749df75198456cac4c70b7a88bba)) 198 | 199 | ### Bug Fixes 200 | 201 | - dragging the splitter fast flickers the cursor ([288acd9](https://github.com/BearToCode/svelte-splitpanes/commit/288acd92583fc906b9625ee3b66ed9f9ba72af1e)) 202 | - improved snap, fixed bug ([903ad71](https://github.com/orefalo/svelte-splitpanes/commit/903ad71b8d64a30b8333661fbb1833cc34e4d526)) 203 | - read panes push ([a61f101](https://github.com/orefalo/svelte-splitpanes/commit/a61f101dff9a1cdf216744139ff789ba9a3e75dd)) 204 | - snap with multiple panes ([01f93a7](https://github.com/orefalo/svelte-splitpanes/commit/01f93a7a45188f3e0d2d2257d3570db12327c899)) 205 | 206 | ### 0.6.12 (2022-06-28) 207 | 208 | ### Features 209 | 210 | - add License and Code of conduct ([c8e9ecd](https://github.com/orefalo/svelte-splitpanes/commit/c8e9ecd9809a749df75198456cac4c70b7a88bba)) 211 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | - Demonstrating empathy and kindness toward other people 21 | - Being respectful of differing opinions, viewpoints, and experiences 22 | - Giving and gracefully accepting constructive feedback 23 | - Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | - Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | - The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | - Trolling, insulting or derogatory comments, and personal or political attacks 33 | - Public or private harassment 34 | - Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | - Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | tecnobertinfo@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Antoni Andre 4 | Copyright (c) 2022 Olivier Refalo (Svelte port) 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![logo](./static/favicon.svg) 2 | 3 | # Svelte-Splitpanes 4 | 5 | [![npm](https://badgen.net/npm/v/svelte-splitpanes)](https://www.npmjs.com/package/svelte-splitpanes) 6 | ![publish size](https://badgen.net/packagephobia/publish/svelte-splitpanes) 7 | [![minified size](https://orefalo.github.io/svelte-splitpanes/minified-size-badge.svg)](https://orefalo.github.io/svelte-splitpanes/minified-size) 8 | ![deps](https://badgen.net/bundlephobia/dependency-count/svelte-splitpanes) 9 | ![contributors](https://badgen.net/github/contributors/orefalo/svelte-splitpanes) 10 | 11 | A _predictable_ responsive component to layout resizable view panels supporting an multitude of advanced features (min/max bounderies, snap, expand on double click, fixed size, rtl). 12 | 13 | ![screenshot](./static/screenshot.jpg) 14 | 15 | ## Why? 16 | 17 | _"To be sucessful, a good framework must come with good components."_ 18 | 19 | Unfortunatly, we couldn't find any decent splitpane widget in the Svelte eco-system. 20 | But we did find one written for vue.js... 21 | 22 | > This library started as a port of [vue-splitpanes](https://antoniandre.github.io/splitpanes/) and through feature enhancements, became one of the best splitpane implementation. 23 | 24 | Special thanks to all contributors and in particular [Tal500](https://github.com/Tal500) 25 | 26 | ## Features 27 | 28 | - Support both dynamic horizontal and vertical splits 29 | - Support defaults, min and max sizes 30 | - Support multiple splits 31 | - Support lifecyle events 32 | - Support custom divider size and overlay (css) 33 | - Support splitter pane pushing 34 | - Support RTL rendering with auto-detection 35 | - Support first splitter on/off 36 | - Support pane toggle 37 | - Support edge snapping 38 | - Support programmatic resizing and two-way size binding 39 | - Support programmatic panes add/remove 40 | - Support programmatic panes reordering by Svelte keyed each blocks 41 | - Support for legacy browser such as IE 11 42 | - Support for touch devices 43 | - Support for fixed splitters 44 | - Sveltekit & Typescript friendly 45 | 46 | ## Browser Support 47 | 48 | | ![Chrome](https://raw.github.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/src/safari/safari_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/src/opera/opera_48x48.png) | ![Edge](https://raw.github.com/alrra/browser-logos/master/src/edge/edge_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png) | 49 | | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | 50 | | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 11 ✔ | 51 | 52 | ## Star History 53 | 54 | [![Star History Chart](https://api.star-history.com/svg?repos=orefalo/svelte-splitpanes&type=Date)](https://star-history.com/#orefalo/svelte-splitpanes&Date) 55 | 56 | ## Demo & Documentation 57 | 58 | - [REPL Demo](https://svelte.dev/repl/1e96cbd4bcd148e3b85a4c8ca76d7309) 59 | - [More complex demos and examples](https://orefalo.github.io/svelte-splitpanes/) 60 | 61 | ## Installation 62 | 63 | ```shell 64 | $ npm i svelte-splitpanes 65 | ``` 66 | 67 | ## Usage 68 | 69 | ```svelte 70 | 73 | 74 | 75 | 76 | 1 77 |
78 | I have a min width of 20% 79 |
80 | 81 | 82 | 83 | 2 84 |
85 | I have a min height of 15% 86 |
87 | 3 88 | 4 89 |
90 |
91 | 5 92 |
93 | ``` 94 | 95 | ### API 96 | 97 | Here is the list of properties that apply to `` 98 | 99 | | Parameter name | Type | Default | Comments | 100 | | ---------------- | --------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 101 | | horizontal | boolean | false (Vertical by default) | The orientation of the split panes. | 102 | | pushOtherPanes | boolean | true | Whether a splitter should push the next splitter when dragging. | 103 | | dblClickSplitter | boolean | true | Double click on splitter to maximize the next pane | 104 | | rtl | boolean\|"auto" | "auto" | Supports Right to left, by default will auto detect | 105 | | firstSplitter | boolean | false | Displays the first splitter when set to true. This allows maximizing the first pane on splitter double click | 106 | | id | string | undefined | Provide an optional id attribute to the component for styling/other reasons | 107 | | theme | string | 'default-theme' | Used to styles the splitters using a different css class, if different then the default value 'default-theme'. see the styling examples in the demo site for more info | 108 | | class | string | undefined | Any additional css classes to be added to the component | 109 | 110 | Properties that apply to `` 111 | 112 | | Parameter name | Type | Default | Comments | 113 | | -------------- | ------------ | ----------- | ------------------------------------------------------- | 114 | | minSize | number | 0 | minimum pane size constraint in % | 115 | | maxSize | number | 100 | maximum pane size constraint in % | 116 | | size | number\|null | null | pane size in %, will autosize if not defined | 117 | | snapSize | number | 0(disabled) | edge snap size constraint in % | 118 | | class | string | undefined | any additional css classes to be added to the component | 119 | 120 | ### Styling 121 | 122 | The component can be further styled after the props have been defined by overriding the default css styling. The best way to do this is to use a class differenciator or the id="" prop and then scope your global css with this class/id. 123 | 124 | ```css 125 | /* The following classes can be used to style the splitter, see demos*/ 126 | 127 | .splitpanes { 128 | background-color: #f8f8f8; 129 | } 130 | 131 | .splitpanes__splitter { 132 | background-color: #ccc; 133 | position: relative; 134 | } 135 | .splitpanes__splitter:before { 136 | content: ''; 137 | position: absolute; 138 | left: 0; 139 | top: 0; 140 | transition: opacity 0.4s; 141 | background-color: rgba(255, 0, 0, 0.3); 142 | opacity: 0; 143 | z-index: 1; 144 | } 145 | .splitpanes__splitter:hover:before { 146 | opacity: 1; 147 | } 148 | .splitpanes--vertical > .splitpanes__splitter:before { 149 | left: -30px; 150 | right: -30px; 151 | height: 100%; 152 | } 153 | .splitpanes--horizontal > .splitpanes__splitter:before { 154 | top: -30px; 155 | bottom: -30px; 156 | width: 100%; 157 | } 158 | ``` 159 | 160 | ### Events 161 | 162 | The component raises the following events: 163 | 164 | | name | description | data | 165 | | ---------------- | ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 166 | | `ready` | fires when splitpanes is ready | none | 167 | | `resize` | fires while resizing (on mousemove/touchmove) | returns an array of all the panes objects with their dimensions | 168 | | `resized` | fires once when the resizing stops after user drag (on mouseup/touchend) or when adding or removing a pane. | returns an array of all the panes objects with their dimensions | 169 | | `pane-click` | when clicking (or touching) a pane | returns the clicked pane object with its dimensions | 170 | | `pane-maximize` | fires when the pane is maximized (ie. typically by double clicking the splitter) | returns the maximized pane object with its dimensions | 171 | | `pane-add` | fires when a pane is added | returns an object containing the index of the added pane and the new array of panes after resize | 172 | | `pane-remove` | fires when a pane is removed | returns an object containing the removed pane and an array of all the remaining pane objects with their dimensions (after resize) | 173 | | `splitter-click` | fires when you click a splitter | returns the next pane object (with its dimensions) directly after the clicked splitter. This event is only emitted if dragging did not occur between mousedown and mouseup | 174 | 175 | Events are easy to trap 176 | 177 | ```svelte 178 | 185 | 186 | 195 | ``` 196 | 197 | ## Contributing 198 | 199 | If you have a great feature, feel free to open a discussion on GitHub to discuss the ideae, you may also fork Splitpanes and submit your changes back as a PR. 200 | 201 | ### Building 202 | 203 | We recommend to use `pnpm` package manager as it is tightly integrated with our CICD pipeline. 204 | 205 | To setup (or update) the project, process as such: 206 | 207 | 1. Install PNPM (if not already installed), for example via `npm install -g pnpm` 208 | 2. Run `pnpm install` 209 | 210 | To build the exported library, run `pnpm package`. 211 | 212 | To build the docs for production-ready version, you need to run `pnpm build`, and you may display the result by `pnpm preview`. 213 | 214 | ### Developing 215 | 216 | After setting (or update) the environment (discussed in the previous section), you may also excecute SvelteKit in development mode by running `pnpm dev`. This will open a Vite server that automatically changes the result in the browser when the code is updated. 217 | 218 | ### Commiting changes 219 | 220 | - run `pnpm commit` 221 | 222 | We have very precise rules over how our git commit messages are formatted. This leads to **more readable messages** that are easy to follow when looking through the **project history**. We use the git messages to **auto-generate the change log**. 223 | 224 | Commits are accepted, as long as they comply to the _commit message format_ described below. 225 | 226 | When you push your commits to Github (by a PR or directly to the repo), your code will be verfied again by Github Actions with code formatting and linting checks. be sure to properly use `pnpm format` and `pnpm lint` 227 | 228 | To ease the development and to enforce the process of formatting the code, perform checks and formatting the commit message, you're advised to commit using the following steps: 229 | 230 | 0. Make sure your environment is up to date, by running periodically `pnpm install`. 231 | 1. Make sure that all the relevant changes are staged. 232 | 2. (Optional) Run `pnpm build && pnpm test` to execute Playwright tests. 233 | 3. Run `pnpm commit`. 234 | - If linting or svelte checks are failed, the commit process will abort and you'll have to fix them. 235 | - Otherwise, you will procceed to the commitment interactive terminal, and just follow the instructions to commit your changes. 236 | 237 | #### Commit Message Format 238 | 239 | Each commit message consists of a **header**, a **body** and a **footer**. The header is _mandatory_ and has a special format that includes a **type**, a **subject** and an optional **scope** : 240 | 241 | ``` 242 | type(scope?)!?: subject 243 | body? 244 | footer? 245 | ``` 246 | 247 | Any line of the commit message cannot be longer than 100 characters. This allows the message to be easy to read on GitHub and various other git tools. 248 | 249 | ###### Type 250 | 251 | Must be one of the following: 252 | 253 | - **build**: Changes that affect the build system or external dependencies (example scopes: npm) 254 | - **ci**: Changes to the CI configuration files and scripts 255 | - **docs**: Documentation only changes 256 | - **feat**: A new feature, increments X.9.X 257 | - **fix**: A bug fix, increments X.X.9 258 | - **wip**: To mark a work in progress 259 | - **perf**: A code change that improves performance 260 | - **refactor**: A code change that neither fixes a bug nor adds a feature 261 | - **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.) 262 | - **test**: Adding missing tests or correcting existing tests 263 | - **revert:** for a revert commit 264 | 265 | adding a tailing **'!'** marks the commit as a **BREAKING CHANGE** - and will affect version numbering. 266 | 267 | ###### Subject 268 | 269 | The subject contains a succinct description of the change: 270 | 271 | - use the imperative, present tense: "change" not "changed" nor "changes" 272 | - don't capitalize the first letter 273 | - no dot (.) at the end 274 | 275 | ### GH Pages (demo site) 276 | 277 | GH Pages hold the demo site. The pages are automatically generated by every push to `master`. 278 | 279 | ### Publishing a new release 280 | 281 | The source code releasing cycle works by the automated bot [Release Please](https://github.com/googleapis/release-please). 282 | 283 | Every time a new important commit is merged to master, this bot will create/update a PR for a new version proposal, containing an updated `CHANGELOG.md` file and an increased version number for the next release. 284 | 285 | When a maintainer wish to publish a new release, he must perform the following tasks, **in this specific order**: 286 | 287 | 0. Merge all the relevant changes to master, and make sure that all Github actions checks passed and the auto-generated docs are fine. 288 | 1. Create a source code release, simply by merging the PR created by the Release Please bot. You have a chance right before the merging to modify the changelog: Modifying the PR body will change what will be displayed on the Github release page, and modifying the file changes to the `CHANGELOG.md` file of the PR let you change the automated changes to this file. **Important**: If you don't merge this release PR immediately after your manual modifications, your modifications will be lost by the next invocation of the Release Please action, which executes whenever committing to the master branch. 289 | 2. After the merging, wait until the Github Actions job named `release-please` is done. You should see now an auto-generated Github release on the main Github page, containing the compiled package with the source code (no need to download it manually). 290 | 3. Fetch the changes from **master** and publish to NPM the newly auto-generated release, by executing the following: (get the `NPM_OTP` from Google authenticator ): 291 | 292 | ```shell 293 | $ pnpm login https://registry.npmjs.org/ 294 | $ git checkout master 295 | $ git fetch 296 | $ pnpm fetch-and-publish 297 | ``` 298 | 299 | The purpose of this process is to streamline the release process, free from any human mistakes. 300 | 301 | We run step 3 manually, and not automated on Github Actions, because we don't want to share NPM credentials as part of the Github project. 302 | 303 | ### More control about Release Please 304 | 305 | #### Controling the version number and forcing a release PR 306 | 307 | **Release Please** actions follows semantic versioning to generate the version number. If you want to change the version number of the new release, or that Release Please bot didn't generate a PR (because there is no _important_ change) and you want to force a new version, you may bump(or downgrade) the version by adding a new commit (replacing `VERSION` to a version number in the format of `X.Y.Z`): 308 | 309 | ```shell 310 | git commit --allow-empty -m "chore: release VERSION (you may change the title)" -m "Release-As: VERSION" 311 | ``` 312 | 313 | Source: https://github.com/googleapis/release-please#how-do-i-change-the-version-number 314 | 315 | #### Controlling contribution PR 316 | 317 | You can specify additional messages in the PR body that will be included in the changelog (if relevant). An example to a body of PR containing additional messages: 318 | 319 | ``` 320 | feat: adds v4 UUID to crypto 321 | 322 | This adds support for v4 UUIDs to the library. 323 | 324 | fix(utils): unicode no longer throws exception 325 | PiperOrigin-RevId: 345559154 326 | BREAKING-CHANGE: encode method no longer throws. 327 | Source-Link: googleapis/googleapis@5e0dcb2 328 | 329 | feat(utils): update encode to support unicode 330 | PiperOrigin-RevId: 345559182 331 | Source-Link: googleapis/googleapis@e5eef86 332 | ``` 333 | 334 | Source: https://github.com/googleapis/release-please#what-if-my-pr-contains-multiple-fixes-or-features 335 | 336 | In the case that a contribution PR was already merged and you want to change the messages for release please, you can edit the body of the merged pull requests and add a section like: 337 | 338 | ``` 339 | BEGIN_COMMIT_OVERRIDE 340 | feat: add ability to override merged commit message 341 | 342 | fix: another message 343 | chore: a third message 344 | END_COMMIT_OVERRIDE 345 | ``` 346 | 347 | Source: https://github.com/googleapis/release-please#how-can-i-fix-release-notes 348 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js'; 2 | import ts from 'typescript-eslint'; 3 | import svelte from 'eslint-plugin-svelte'; 4 | import prettier from 'eslint-config-prettier'; 5 | import globals from 'globals'; 6 | 7 | const __dirname = import.meta.dirname; 8 | 9 | import pkg from 'eslint-gitignore'; 10 | const { readGitignoreFiles } = pkg; 11 | 12 | function removeDuplicates(arr) { 13 | return arr.filter((value, index, self) => self.indexOf(value) === index); 14 | } 15 | 16 | /** @type {import('eslint').Linter.FlatConfig[]} */ 17 | export default [ 18 | js.configs.recommended, 19 | ...ts.configs.recommended, 20 | ...svelte.configs['flat/recommended'], 21 | prettier, 22 | ...svelte.configs['flat/prettier'], 23 | { 24 | languageOptions: { 25 | globals: { 26 | ...globals.browser, 27 | ...globals.node, 28 | NodeJS: true 29 | } 30 | } 31 | }, 32 | { 33 | files: ['**/*.svelte'], 34 | languageOptions: { 35 | parserOptions: { 36 | parser: ts.parser 37 | } 38 | } 39 | }, 40 | { 41 | ignores: removeDuplicates([ 42 | ...readGitignoreFiles({ cwd: __dirname }), 43 | 'build/', 44 | '**/.svelte-kit/', 45 | 'dist/', 46 | 'package/', 47 | '**/_app/' 48 | ]) 49 | }, 50 | { 51 | rules: { 52 | // eqeqeq: 'error', 53 | 'prefer-const': ['error', { ignoreReadBeforeAssign: true }], 54 | '@typescript-eslint/no-explicit-any': 'off', 55 | // const _a = 'unused, with underscore, no warning' 56 | // const b = 'unused, no underscore, warning' 57 | // note you must disable the base rule 58 | // as it can report incorrect errors 59 | 'no-unused-vars': 'off', 60 | '@typescript-eslint/no-unused-vars': [ 61 | 'warn', // or "error" 62 | { 63 | argsIgnorePattern: '^_', 64 | varsIgnorePattern: '^_', 65 | caughtErrorsIgnorePattern: '^_' 66 | } 67 | ], 68 | // We need to use {@html} in the demo site for code highlight 69 | 'svelte/no-at-html-tags': 'off', 70 | // css is global and incorrectly reported as unused by the linter 71 | 'svelte/valid-compile': 'off', 72 | '@typescript-eslint/ban-ts-comment': 'off' 73 | } 74 | } 75 | ]; 76 | -------------------------------------------------------------------------------- /example/.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 | demo -------------------------------------------------------------------------------- /example/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # create-svelte 2 | 3 | Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). 4 | 5 | ## Creating a project 6 | 7 | If you're seeing this, you've probably already done this step. Congrats! 8 | 9 | ```bash 10 | # create a new project in the current directory 11 | npm create svelte@latest 12 | 13 | # create a new project in my-app 14 | npm create svelte@latest my-app 15 | ``` 16 | 17 | ## Developing 18 | 19 | Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: 20 | 21 | ```bash 22 | npm run dev 23 | 24 | # or start the server and open the app in a new browser tab 25 | npm run dev -- --open 26 | ``` 27 | 28 | ## Building 29 | 30 | To create a production version of your app: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | You can preview the production build with `npm run preview`. 37 | 38 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. 39 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "build": "vite build", 8 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 9 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 10 | "dev": "vite dev", 11 | "preview": "vite preview" 12 | }, 13 | "devDependencies": { 14 | "@sveltejs/adapter-static": "^3.0.5", 15 | "@sveltejs/kit": "^2.5.28", 16 | "@sveltejs/vite-plugin-svelte": "^3.1.2", 17 | "svelte": "^4.2.19", 18 | "svelte-check": "^3.8.6", 19 | "svelte-splitpanes": "^8.0.6", 20 | "tslib": "^2.7.0", 21 | "typescript": "^5.6.2", 22 | "vite": "^5.4.8" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/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 Platform {} 9 | } 10 | } 11 | 12 | export {}; 13 | -------------------------------------------------------------------------------- /example/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /example/src/routes/+layout.ts: -------------------------------------------------------------------------------- 1 | export const prerender = true; 2 | -------------------------------------------------------------------------------- /example/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

Welcome to Svelte-Splitpanes Minimal Demo!

8 |

9 | Visit {url} 10 | to read the documentation and for more examples. 11 |

12 | 13 | 14 | First Pane 15 | Second Pane 16 | 17 | -------------------------------------------------------------------------------- /example/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orefalo/svelte-splitpanes/25d41a3967f35e26917f0ec2bf5579c5008a82b1/example/static/favicon.png -------------------------------------------------------------------------------- /example/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-static'; 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: adapter({ 12 | pages: 'demo', 13 | assets: 'demo', 14 | fallback: undefined 15 | }) 16 | } 17 | }; 18 | 19 | export default config; 20 | -------------------------------------------------------------------------------- /example/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 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /example/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import { defineConfig } from 'vite'; 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()] 6 | }); 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-splitpanes", 3 | "version": "8.0.9", 4 | "private": false, 5 | "description": "A full featured resizable pane layout splitter, ported from vue-splitpanes and enhanced", 6 | "keywords": [ 7 | "svelte", 8 | "layout", 9 | "split", 10 | "splitter", 11 | "pane", 12 | "panel", 13 | "resizable" 14 | ], 15 | "homepage": "https://orefalo.github.io/svelte-splitpanes/", 16 | "bugs": "https://github.com/orefalo/svelte-splitpanes/issues", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/orefalo/svelte-splitpanes" 20 | }, 21 | "license": "MIT", 22 | "author": { 23 | "name": "Olivier Refalo", 24 | "url": "https://github.com/orefalo" 25 | }, 26 | "type": "module", 27 | "exports": { 28 | "./package.json": "./package.json", 29 | ".": { 30 | "types": "./dist/index.d.ts", 31 | "svelte": "./dist/index.js" 32 | } 33 | }, 34 | "svelte": "./dist/index.js", 35 | "types": "./dist/index.d.ts", 36 | "files": [ 37 | "dist" 38 | ], 39 | "scripts": { 40 | "build": "vite build && node ./scripts/create-minified-size-badges.js", 41 | "check": "svelte-check --tsconfig ./tsconfig.json", 42 | "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", 43 | "commit": "cross-env node ./node_modules/cz-customizable/standalone.js", 44 | "dev": "cross-env DEV=1 vite dev --port 3000", 45 | "example-build:build": "cd example-temp && svelte-kit sync && pnpm run build", 46 | "example-build:setup": "rimraf -g \"./example-temp/!(node_modules)*\" && copyfiles -u 1 \"./example/!(node_modules)*/**/*\" \"./example/!(node_modules)*\" ./example-temp && node ./scripts/example/pnpm-install-project-in-example-temp.js", 47 | "example-build:test": "node ./scripts/example/verify-example-build.js", 48 | "fetch-and-publish": "node scripts/fetch-and-publish.js", 49 | "format": "prettier --ignore-path .gitignore --write --cache !**/pnpm-lock.yaml !./CHANGELOG.md .", 50 | "lint": "pnpm run format && pnpm run lint-es", 51 | "lint-es": "eslint --cache .", 52 | "package": "pnpm run package:build && npm run package:pack", 53 | "package:build": "rimraf -g ./package/* && svelte-package -o ./package/dist && copyfiles ./README.md ./LICENSE ./package/ && node scripts/package-clean-copy.js", 54 | "package:pack": "cd package && npm pack", 55 | "prepare": "husky", 56 | "preview": "vite preview --port 3000", 57 | "static-serv": "serve -l 3000 --no-clipboard docs", 58 | "test": "playwright test" 59 | }, 60 | "config": { 61 | "cz-customizable": { 62 | "config": ".cz-config.cjs" 63 | } 64 | }, 65 | "dependencies": { 66 | "esm-env-robust": "0.0.3" 67 | }, 68 | "devDependencies": { 69 | "@commitlint/cli": "^19.5.0", 70 | "@commitlint/config-conventional": "^19.5.0", 71 | "@playwright/test": "^1.48.2", 72 | "@sveltejs/adapter-static": "^3.0.6", 73 | "@sveltejs/kit": "^2.7.3", 74 | "@sveltejs/package": "^2.3.7", 75 | "@sveltejs/vite-plugin-svelte": "^4.0.0", 76 | "@types/eslint": "^9.6.1", 77 | "@types/node": "^22.8.4", 78 | "@typescript-eslint/eslint-plugin": "^8.12.2", 79 | "@typescript-eslint/parser": "^8.12.2", 80 | "badge-maker": "^4.1.0", 81 | "copyfiles": "^2.4.1", 82 | "cross-env": "^7.0.3", 83 | "cz-customizable": "^7.2.1", 84 | "eslint": "^9.13.0", 85 | "eslint-config-prettier": "^9.1.0", 86 | "eslint-gitignore": "^0.1.0", 87 | "eslint-plugin-markdown": "^5.1.0", 88 | "eslint-plugin-svelte": "^2.46.0", 89 | "globals": "^15.11.0", 90 | "highlight.js": "^11.10.0", 91 | "husky": "^9.1.6", 92 | "prettier": "^3.3.3", 93 | "prettier-plugin-svelte": "^3.2.7", 94 | "rimraf": "^6.0.1", 95 | "sass": "^1.80.5", 96 | "serve": "^14.2.4", 97 | "svelte-check": "^4.0.5", 98 | "svelte-highlight": "^7.7.0", 99 | "svelte-preprocess": "^6.0.3", 100 | "svelte-range-slider-pips": "^3.1.2", 101 | "tslib": "^2.8.0", 102 | "typescript": "^5.6.3", 103 | "typescript-eslint": "^8.12.2", 104 | "vite": "^5.4.10", 105 | "vitest": "^2.1.4" 106 | }, 107 | "peerDependencies": { 108 | "svelte": "^4.2.19 || ^5.1.0" 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { type PlaywrightTestConfig, devices } from '@playwright/test'; 2 | 3 | const config: PlaywrightTestConfig = { 4 | forbidOnly: !!process.env.CI, 5 | retries: process.env.CI ? 2 : 0, 6 | timeout: 5 * 60 * 1000, 7 | webServer: { 8 | command: 'pnpm run static-serv', 9 | port: 3000 10 | }, 11 | use: { 12 | trace: 'on', 13 | video: 'on' 14 | }, 15 | projects: [ 16 | { 17 | name: 'chromium', 18 | use: { ...devices['Desktop Chrome'] } 19 | }, 20 | { 21 | name: 'firefox', 22 | use: { ...devices['Desktop Firefox'] } 23 | }, 24 | { 25 | name: 'webkit', 26 | use: { ...devices['Desktop Safari'] } 27 | } 28 | ] 29 | }; 30 | 31 | export default config; 32 | -------------------------------------------------------------------------------- /scripts/create-minified-size-badges.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | import { makeBadge } from 'badge-maker'; 4 | 5 | /** 6 | * 7 | * @param {string} name 8 | */ 9 | const formatSize = name => 10 | `${name}: ${( 11 | parseInt( 12 | fs.readFileSync(`./.svelte-kit/output/minified-size-${name}.txt`, { encoding: 'utf-8' }) 13 | ) / 1024 14 | ).toFixed(1)} KB`; 15 | 16 | const format = { 17 | label: 'minified size', 18 | message: ['client', 'server'].map(formatSize).join(', '), 19 | color: '#08C' 20 | }; 21 | 22 | const svg = makeBadge(format); 23 | 24 | fs.writeFileSync('./docs/minified-size-badge.svg', svg); 25 | -------------------------------------------------------------------------------- /scripts/example/pnpm-install-project-in-example-temp.js: -------------------------------------------------------------------------------- 1 | import child_process from 'node:child_process'; 2 | import os from 'node:os'; 3 | import path from 'node:path'; 4 | import { fileURLToPath } from 'node:url'; 5 | import packageJson from '../../package.json' assert { type: 'json' }; 6 | 7 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 8 | 9 | const exampleTempDir = path.resolve(__dirname, '../../example-temp'); 10 | 11 | const version = packageJson.version; 12 | const fileToInstall = path.resolve(exampleTempDir, `../package/svelte-splitpanes-${version}.tgz`); 13 | 14 | console.log(`Installing with the file package: ${fileToInstall}`); 15 | 16 | const npmPostfixCommand = name => (os.platform() === 'win32' ? `${name}.cmd` : name); 17 | 18 | const npmProc = child_process.spawn( 19 | npmPostfixCommand('pnpm'), 20 | ['install', '--save-dev', fileToInstall], 21 | { 22 | cwd: exampleTempDir 23 | } 24 | ); 25 | 26 | npmProc.stdout.on('data', data => { 27 | console.log(data.toString()); 28 | }); 29 | 30 | npmProc.stderr.on('data', data => { 31 | console.error(data.toString()); 32 | }); 33 | -------------------------------------------------------------------------------- /scripts/example/verify-example-build.js: -------------------------------------------------------------------------------- 1 | import { readFileSync } from 'node:fs'; 2 | import path from 'node:path'; 3 | import assert from 'node:assert/strict'; 4 | import { fileURLToPath } from 'url'; 5 | import packageJson from '../../package.json' assert { type: 'json' }; 6 | import exampleTempPackageJson from '../../example-temp/package.json' assert { type: 'json' }; 7 | 8 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 9 | 10 | const exampleTempDir = path.resolve(__dirname, '../../example-temp'); 11 | 12 | const version = packageJson.version; 13 | const fileToInstall = path.resolve(exampleTempDir, `../package/svelte-splitpanes-${version}.tgz`); 14 | 15 | const packageInstallationSource = exampleTempPackageJson['devDependencies']['svelte-splitpanes']; 16 | const packageInstallationSourceExpected = `file:${fileToInstall.replaceAll('\\', '/')}`; 17 | if (packageInstallationSource !== packageInstallationSourceExpected) { 18 | throw ( 19 | "Error: Example temp package installation wasn't successful! Instead, the value is " + 20 | packageInstallationSource + 21 | ' but was expected to be: ' + 22 | packageInstallationSourceExpected 23 | ); 24 | } 25 | 26 | const fileDirPath = path.dirname(fileURLToPath(import.meta.url)); 27 | 28 | const htmlFilePath = path.resolve(fileDirPath, '../../example-temp/demo/index.html'); 29 | const htmlContent = readFileSync(htmlFilePath, { encoding: 'utf-8' }); 30 | 31 | // Assertations 32 | 33 | assert(htmlContent.search('Welcome to Svelte-Splitpanes Minimal Demo!') >= 0, 'check head title'); 34 | 35 | assert(htmlContent.search('First Pane') >= 0, 'check first pane'); 36 | 37 | assert(htmlContent.search('Second Pane') >= 0, 'check second pane'); 38 | -------------------------------------------------------------------------------- /scripts/fetch-and-publish.js: -------------------------------------------------------------------------------- 1 | import child_process from 'node:child_process'; 2 | import os from 'node:os'; 3 | import packageJson from '../package.json' assert { type: 'json' }; 4 | 5 | if (process.argv.length < 3) { 6 | console.error('Usage: fetch-and-publish '); 7 | process.exit(1); 8 | } 9 | 10 | const otp = process.argv[process.argv.length - 1]; 11 | const version = packageJson.version; 12 | 13 | const npmPostfixCommand = name => (os.platform() === 'win32' ? `${name}.cmd` : name); 14 | 15 | const npmProc = child_process.spawn(npmPostfixCommand('npm'), [ 16 | 'publish', 17 | `https://github.com/orefalo/svelte-splitpanes/releases/download/v${version}/svelte-splitpanes-${version}.tgz`, 18 | '--access', 19 | 'public', 20 | '--otp', 21 | otp 22 | ]); 23 | 24 | npmProc.stdout.on('data', data => { 25 | console.log(data.toString()); 26 | }); 27 | 28 | npmProc.stderr.on('data', data => { 29 | console.error(data.toString()); 30 | }); 31 | -------------------------------------------------------------------------------- /scripts/package-clean-copy.js: -------------------------------------------------------------------------------- 1 | import { writeFile } from 'node:fs'; 2 | import { fileURLToPath } from 'node:url'; 3 | import { dirname, resolve } from 'node:path'; 4 | 5 | import packageJson from '../package.json' assert { type: 'json' }; 6 | 7 | const __filename = fileURLToPath(import.meta.url); 8 | const __dirname = dirname(__filename); 9 | 10 | const packageJsonOutputPath = resolve(__dirname, '../package/package.json'); 11 | 12 | // Keys that we want to remove, which are not usefull for the final package that the user consumes. 13 | const keysToRemove = ['private', 'devDependencies', 'optionalDependencies', 'scripts', 'config']; 14 | for (const key of keysToRemove) { 15 | delete packageJson[key]; 16 | } 17 | 18 | writeFile(packageJsonOutputPath, JSON.stringify(packageJson, null, '\t') + '\n', error => { 19 | if (error) throw error; 20 | }); 21 | -------------------------------------------------------------------------------- /scripts/vite/example-import.js: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs/promises'; 2 | 3 | import * as sass from 'sass'; 4 | 5 | // This Highlight.js loading is based on the code in: 6 | // https://github.com/metonym/svelte-highlight/blob/master/src/Highlight.svelte 7 | import hljs from 'highlight.js/lib/core'; 8 | import xml from 'highlight.js/lib/languages/xml'; 9 | import javascript from 'highlight.js/lib/languages/javascript'; 10 | import css from 'highlight.js/lib/languages/css'; 11 | 12 | hljs.registerLanguage('xml', xml); 13 | hljs.registerLanguage('javascript', javascript); 14 | hljs.registerLanguage('css', css); 15 | 16 | // TODO: Export this Vite(&Rollup!) plugin to be universal in a different package. 17 | 18 | const apiQuery = 'example'; 19 | // Vite internally adds this parameter in build, so we must accept it if present. See this comment for info: 20 | // https://github.com/vitejs/vite/issues/12239#issuecomment-1466494704 21 | const apiQueryOptional = 'used'; 22 | 23 | const apiProxySuffix = '.example-safeguard-proxy'; // This is needed so other plugins wouldn't transform the file 24 | const idPrefix = '\0example-import-proxy"'; 25 | const encodeId = (/** @type {string} */ id) => idPrefix + id + apiProxySuffix; 26 | const decodeId = (/** @type {string} */ id) => id.slice(idPrefix.length, -apiProxySuffix.length); 27 | 28 | // TODO: Can we just modify some Prettier config to get this result in the straight way? 29 | /** 30 | * Change the ">" starting lines to just go to the line before. 31 | * This both looks nicer for examples, and additionally fix highlighting issues. 32 | * 33 | * @param {string} code 34 | * @returns {string} 35 | */ 36 | const fixTrailingEnds = code => code.replaceAll(/\n>/gm, '>'); 37 | 38 | /** 39 | * A Vite plugin that computes the actual minified size of the library. 40 | * 41 | * @returns {import('vite').PluginOption} 42 | */ 43 | export const exampleImportPlugin = () => ({ 44 | name: 'vite-plugin-example', 45 | enforce: 'pre', 46 | 47 | async resolveId(source, importer) { 48 | const [originalSource, sourceUrlSearchParamsStr] = source.split('?', 2); 49 | const sourceUrlSearchParams = new URLSearchParams(sourceUrlSearchParamsStr); 50 | 51 | if (!sourceUrlSearchParams.has(apiQuery) && !sourceUrlSearchParams.has(apiQueryOptional)) { 52 | return; 53 | } 54 | 55 | // otherwise 56 | const resolved = (await this.resolve(originalSource, importer))?.id; 57 | return resolved ? encodeId(resolved) : null; 58 | }, 59 | 60 | async load(id) { 61 | if (!id.startsWith(idPrefix)) { 62 | return; 63 | } 64 | // otherwise 65 | 66 | const originalId = decodeId(id); 67 | const isSvelte = originalId.endsWith('.svelte'); 68 | const isSass = ['scss', 'sass'].some(suffix => originalId.endsWith(`.${suffix}`)); 69 | const isCSS = isSass || originalId.endsWith(`.css`); 70 | 71 | let code = await fs.readFile(originalId, { encoding: 'utf8' }); 72 | if (isSvelte) { 73 | code = fixTrailingEnds(code); 74 | } 75 | const highlightedHTML = hljs.highlightAuto(code).value; 76 | 77 | const css = isCSS ? (isSass ? (await sass.compileAsync(originalId)).css : code) : undefined; 78 | const cssHighlightedHTML = css ? hljs.highlight(css, { language: 'css' }).value : undefined; 79 | 80 | const output = [ 81 | isSvelte ? `import component from ${JSON.stringify(originalId)};` : '', 82 | `export const code = ${JSON.stringify(code)};`, 83 | `export const highlightedHTML = ${JSON.stringify(highlightedHTML)};`, 84 | isSvelte ? `export { component };` : '', 85 | isCSS ? `export const css = ${JSON.stringify(css)};` : '', 86 | isCSS ? `export const cssHighlightedHTML = ${JSON.stringify(cssHighlightedHTML)};` : '', 87 | `export default { code, highlightedHTML${isSvelte ? ', component' : ''}${ 88 | isCSS ? ', css, cssHighlightedHTML' : '' 89 | } };` 90 | ].join('\n'); 91 | 92 | return output; 93 | } 94 | }); 95 | -------------------------------------------------------------------------------- /scripts/vite/highlight-languages.d.ts: -------------------------------------------------------------------------------- 1 | type LanguageFn = import('highlight.js').LanguageFn; 2 | 3 | declare module 'highlight.js/lib/languages/xml' { 4 | export default LanguageFn; 5 | } 6 | declare module 'highlight.js/lib/languages/javascript' { 7 | export default LanguageFn; 8 | } 9 | declare module 'highlight.js/lib/languages/css' { 10 | export default LanguageFn; 11 | } 12 | -------------------------------------------------------------------------------- /scripts/vite/minified-size-analyzing.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | 4 | const libPath = path.resolve('.', 'src/lib/'); 5 | 6 | /** @type {unknown} */ 7 | let ssr; 8 | 9 | /** 10 | * A Vite plugin that computes the actual minified size of the library. 11 | * 12 | * @returns {import('vite').PluginOption} 13 | */ 14 | export const minifiedSizeAnalyzingPlugin = () => ({ 15 | name: 'vite-plugin-minified-size-analyzing', 16 | enforce: 'pre', 17 | 18 | configResolved(config) { 19 | ssr = config.build?.ssr ?? false; 20 | }, 21 | 22 | generateBundle(_options, bundle) { 23 | // Notice that this stage happen only on build, and not on dev. 24 | 25 | let found = false; 26 | 27 | for (const chunkName in bundle) { 28 | const chunk = bundle[chunkName]; 29 | 30 | if ( 31 | chunk.type === 'chunk' && 32 | Object.keys(chunk.modules).find(fileSource => path.resolve(fileSource).startsWith(libPath)) 33 | ) { 34 | if (found) { 35 | throw 'Error: the library dependency was already found for minified size computation, so it is separated!'; 36 | } 37 | found = true; 38 | 39 | const size = chunk.code.length; 40 | 41 | if (!ssr) { 42 | console.log('\nClient minified library size (bytes): ' + size); 43 | fs.writeFileSync('./.svelte-kit/output/minified-size-client.txt', size.toString()); 44 | } else { 45 | console.log('\nServer minified library size (bytes): ' + size); 46 | fs.writeFileSync('./.svelte-kit/output/minified-size-server.txt', size.toString()); 47 | } 48 | } 49 | } 50 | 51 | if (!found) { 52 | throw "Error: the library dependency wasn't found for minified size computation!"; 53 | } 54 | } 55 | }); 56 | 57 | /** 58 | * The needed Rollup `manualChunks()` configuration function so the size analyzing would work. 59 | * 60 | * @param {string} id 61 | * @returns 62 | */ 63 | export const manualChunksForAnalyzing = id => { 64 | const resolvedPath = path.resolve(id); 65 | 66 | if (resolvedPath.search('node_modules') > 0) { 67 | // We need to separate the external deps so they won't be in the `svelte-splitpanes` chunk. 68 | return 'external'; 69 | } else if (resolvedPath.startsWith(libPath)) { 70 | return 'svelte-splitpanes'; 71 | } else { 72 | return undefined; 73 | } 74 | }; 75 | -------------------------------------------------------------------------------- /src/app.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // See https://kit.svelte.dev/docs/types#the-app-namespace 6 | // for information about these interfaces 7 | declare namespace App { 8 | // interface Locals {} 9 | // interface Platform {} 10 | // interface Session {} 11 | // interface Stuff {} 12 | } 13 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | %sveltekit.head% 9 | 10 | 11 |
%sveltekit.body%
12 | 13 | 14 | -------------------------------------------------------------------------------- /src/comp/Button.svelte: -------------------------------------------------------------------------------- 1 | 120 | 121 | 146 | 147 | 222 | -------------------------------------------------------------------------------- /src/comp/Contents.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | 22 | 47 | 48 | 169 | -------------------------------------------------------------------------------- /src/comp/ExampleArea.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 | 8 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /src/comp/Highlighted.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
{@html highlighted}
9 | -------------------------------------------------------------------------------- /src/comp/PrerenderedArea.svelte: -------------------------------------------------------------------------------- 1 | 51 | 52 | 57 | -------------------------------------------------------------------------------- /src/comp/RTLToggle.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 | Splitpane direction: 9 | 10 | 11 | 12 |
13 | 14 | 27 | -------------------------------------------------------------------------------- /src/comp/Ripple.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 29 | -------------------------------------------------------------------------------- /src/comp/TextAreaAutosize.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 | 28 |