Coder Social home page Coder Social logo

svelte-splitpanes's Introduction

logo

Svelte-Splitpanes

npm publish size minified size deps contributors

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).

screenshot

Why?

"To be sucessful, a good framework must come with good components."

Unfortunatly, we couldn't find any decent splitpane widget in the Svelte eco-system. But we did find one written for vue.js...

This library started as a port of vue-splitpanes and through feature enhancements, became one of the best splitpane implementation.

Special thanks to all contributors and in particular Tal500

Features

  • Support both dynamic horizontal and vertical splits
  • Support defaults, min and max sizes
  • Support multiple splits
  • Support lifecyle events
  • Support custom divider size and overlay (css)
  • Support splitter pane pushing
  • Support RTL rendering with auto-detection
  • Support first splitter on/off
  • Support pane toggle
  • Support edge snapping
  • Support programmatic resizing and two-way size binding
  • Support programmatic panes add/remove
  • Support programmatic panes reordering by Svelte keyed each blocks
  • Support for legacy browser such as IE 11
  • Support for touch devices
  • Support for fixed splitters
  • Sveltekit & Typescript friendly

Browser Support

Chrome Firefox Safari Opera Edge IE
Latest ✔ Latest ✔ Latest ✔ Latest ✔ Latest ✔ 11 ✔

Star History

Star History Chart

Demo & Documentation

Installation

$ npm i svelte-splitpanes

Usage

<script>
	import { Pane, Splitpanes } from 'svelte-splitpanes';
</script>

<Splitpanes style="height: 400px">
	<Pane minSize={20}>1<br /><em class="specs">I have a min width of 20%</em></Pane>
	<Pane>
		<Splitpanes horizontal={true}>
			<Pane minSize={15}>2<br /><em class="specs">I have a min height of 15%</em></Pane>
			<Pane>3</Pane>
			<Pane>4</Pane>
		</Splitpanes>
	</Pane>
	<Pane>5</Pane>
</Splitpanes>

API

Here is the list of properties that apply to <Splitpanes>

Parameter name Type Default Comments
horizontal boolean false (Vertical by default) The orientation of the split panes.
pushOtherPanes boolean true Whether a splitter should push the next splitter when dragging.
dblClickSplitter boolean true Double click on splitter to maximize the next pane
rtl boolean|"auto" "auto" Supports Right to left, by default will auto detect
firstSplitter boolean false Displays the first splitter when set to true. This allows maximizing the first pane on splitter double click
id string undefined Provide an optional id attribute to the component for styling/other reasons
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
class string undefined Any additional css classes to be added to the component

Properties that apply to <Pane>

Parameter name Type Default Comments
minSize number 0 minimum pane size constraint in %
maxSize number 100 maximum pane size constraint in %
size number|null null pane size in %, will autosize if not defined
snapSize number 0(disabled) edge snap size constraint in %
class string undefined any additional css classes to be added to the component

Styling

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.

/* The following classes can be used to style the splitter, see demos*/

.splitpanes {
	background-color: #f8f8f8;
}

.splitpanes__splitter {
	background-color: #ccc;
	position: relative;
}
.splitpanes__splitter:before {
	content: '';
	position: absolute;
	left: 0;
	top: 0;
	transition: opacity 0.4s;
	background-color: rgba(255, 0, 0, 0.3);
	opacity: 0;
	z-index: 1;
}
.splitpanes__splitter:hover:before {
	opacity: 1;
}
.splitpanes--vertical > .splitpanes__splitter:before {
	left: -30px;
	right: -30px;
	height: 100%;
}
.splitpanes--horizontal > .splitpanes__splitter:before {
	top: -30px;
	bottom: -30px;
	width: 100%;
}

Events

The component raises the following events:

name description data
ready fires when splitpanes is ready none
resize fires while resizing (on mousemove/touchmove) returns an array of all the panes objects with their dimensions
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
pane-click when clicking (or touching) a pane returns the clicked pane object with its dimensions
pane-maximize fires when the pane is maximized (ie. typically by double clicking the splitter) returns the maximized pane object with its dimensions
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
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)
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

Events are easy to trap

<script>
	import { Splitpanes } from 'svelte-splitpanes';

	function handleMessage(event) {
		console.log(JSON.stringify(event));
	}
</script>

<Splitpanes
	on:ready={handleMessage}
	on:resize={handleMessage}
	on:resized={handleMessage}
	on:pane-click={handleMessage}
	on:pane-maximize={handleMessage}
	on:pane-add={handleMessage}
	on:pane-remove={handleMessage}
	on:splitter-click={handleMessage}
/>

Contributing

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.

Building

We recommend to use pnpm package manager as it is tightly integrated with our CICD pipeline.

To setup (or update) the project, process as such:

  1. Install PNPM (if not already installed), for example via npm install -g pnpm
  2. Run pnpm install

To build the exported library, run pnpm package.

To build the docs for production-ready version, you need to run pnpm build, and you may display the result by pnpm preview.

Developing

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 (hot reload).

Commiting changes

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.

The enforcement is made possible by the enablement of several tools which, when put together, enable strict goverance.

Commits are accepted, as long as they comply to the commit message format described below.

We also require the code to be well-formatted and to pass linting(i.e. minimal ts&svelte checks, plus additional code styling rules). Don't worry, the code is automatically being formatted and verified every time you commit your changes. In addition, 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 even more checks.

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:

  1. Make sure your environment is up to date, by running periodically pnpm install.
  2. Make sure that all the relevant changes are staged.
  3. (Optional) Run pnpm build && pnpm test to execute Playwright tests.
  4. Run pnpm commit.
    • If linting or svelte checks are failed, the commit process will abort and you'll have to fix them.
    • Otherwise, you will procceed to the commitment interactive terminal, and just follow the instructions to commit your changes.

Commit Message Format

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 :

type(scope?)!?: subject
body?
footer?

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.

Type

Must be one of the following:

  • build: Changes that affect the build system or external dependencies (example scopes: npm)
  • ci: Changes to the CI configuration files and scripts
  • docs: Documentation only changes
  • feat: A new feature, increments X.9.X
  • fix: A bug fix, increments X.X.9
  • wip: To mark a work in progress
  • perf: A code change that improves performance
  • refactor: A code change that neither fixes a bug nor adds a feature
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semicolons, etc.)
  • test: Adding missing tests or correcting existing tests
  • revert: for a revert commit

adding a tailing '!' marks the commit as a BREAKING CHANGE - and will affect version numbering.

Subject

The subject contains a succinct description of the change:

  • use the imperative, present tense: "change" not "changed" nor "changes"
  • don't capitalize the first letter
  • no dot (.) at the end

GH Pages (demo site)

GH Pages hold the demo site. The pages are automatically generated by every push to master.

Publishing a new release

The source code releasing cycle works by the automated bot Release Please.

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.

When a maintainer wish to publish a new release, he must perform the following tasks, in this specific order:

  1. Merge all the relevant changes to master, and make sure that all Github actions checks passed and the auto-generated docs are fine.
  2. 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.
  3. 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).
  4. 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 ):
$ pnpm login https://registry.npmjs.org/
$ git checkout master
$ git fetch
$ pnpm fetch-and-publish <NPM_OTP>

The purpose of this process is to streamline the release process, free from any human mistakes.

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.

More control about Release Please

Controling the version number and forcing a release PR

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):

git commit --allow-empty -m "chore: release VERSION (you may change the title)" -m "Release-As: VERSION"

Source: https://github.com/googleapis/release-please#how-do-i-change-the-version-number

Controlling contribution PR

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:

feat: adds v4 UUID to crypto

This adds support for v4 UUIDs to the library.

fix(utils): unicode no longer throws exception
  PiperOrigin-RevId: 345559154
  BREAKING-CHANGE: encode method no longer throws.
  Source-Link: googleapis/googleapis@5e0dcb2

feat(utils): update encode to support unicode
  PiperOrigin-RevId: 345559182
  Source-Link: googleapis/googleapis@e5eef86

Source: https://github.com/googleapis/release-please#what-if-my-pr-contains-multiple-fixes-or-features

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:

BEGIN_COMMIT_OVERRIDE
feat: add ability to override merged commit message

fix: another message
chore: a third message
END_COMMIT_OVERRIDE

Source: https://github.com/googleapis/release-please#how-can-i-fix-release-notes

svelte-splitpanes's People

Contributors

beartocode avatar dependabot[bot] avatar e0 avatar github-actions[bot] avatar mrwokkel avatar orefalo avatar tal500 avatar wtachau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

svelte-splitpanes's Issues

Pass objects as details for all the events

This is a breaking change, but gives us:

  • Better typing capabilities of the parameters.
  • API stability: Adding more parameters will be possible without breaking the API.

Add a license

This project does not have a license.

Would it be possible to release it under an MIT license? If so, I think more people would consider using it, or contributing to it.

RTL (right to left) drag direction issue

First, thanks for this amazing package.

However, I need to support right to left(RTL) text direction, for languages like Hebrew or Arabic for example.
This REPL shows what goes wrong in RTL and split pane.
When dragging, it drag to the opposite direction (try).

Basically, for fixing this issue, I think you need to switch the following line from

x: clientX - rect.left,

to

x: getComputedStyle(container).direction !== 'rtl' ? clientX - rect.left : rect.width - (clientX - rect.left),

Sources:

dark theme

Is there a built in dark theme? Im playing around with a bare bones setup from npm init vite, and it looks quite horrible:

image

white text on white background!

  <div class="card">
    <Splitpanes style="height: 20em; width: 50em">
      <Pane>left</Pane>
      <Pane>right</Pane>
    </Splitpanes>
  </div>

github action

Morning @Tal500 ,

the action fails with

[tests](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#logs)
failed 2 minutes ago in 13s
Search logs
2s
1s
4s
5s
Run bahmutov/npm-install@v[1](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:1).4.5
running npm-install GitHub Action
trying to restore cached NPM modules
Received 2169[3](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:4)288[4](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:5) of 216932884 (100.0%), 19[5](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:6).7 MBs/sec
Cache Size: ~207 MB (21[6](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:7)932884 B)
/usr/bin/tar --use-compress-program zstd -d -xf /home/runner/work/_temp/9322d40a-9bd6-4622-9d52-4[7](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:8)d62ff2b534/cache.tzst -P -C /home/runner/work/svelte-splitpanes/svelte-splitpanes
npm cache hit yarn-linux-x64-363[8](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:9)[9](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:10)9fee4314ee5ad7ab93cb474dbe7d5725f9e50acd68d577ea2c160ea4e2119ddf3ec0db42aaa0efdc02d7ce374bbc0afb464ce99201cf79f2cb2b0b8130b
installing NPM dependencies using Yarn
yarn at "/usr/local/bin/yarn"
/usr/local/bin/yarn --frozen-lockfile
yarn install v1.22.19
[1/4] Resolving packages...
error Your lockfile needs to be updated, but yarn was run with `--frozen-lockfile`.
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
Error: The process '/usr/local/bin/yarn' failed with exit code 1
    at ExecState._setResult (/home/runner/work/_actions/bahmutov/npm-install/v1.4.5/dist/index.js:962:25)
    at ExecState.CheckComplete (/home/runner/work/_actions/bahmutov/npm-install/v1.4.5/dist/index.js:945:18)
    at ChildProcess.<anonymous> (/home/runner/work/_actions/bahmutov/npm-install/v1.4.5/dist/index.js:839:27)
    at ChildProcess.emit (events.js:314:20)
    at maybeClose (internal/child_process.js:[10](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:11)22:[16](https://github.com/orefalo/svelte-splitpanes/runs/7086398111?check_suite_focus=true#step:4:17))
    at Process.ChildProcess._handle.onexit (internal/child_process.js:287:5)
Error: The process '/usr/local/bin/yarn' failed with exit code 1

I did update a yarn which did change the lockfile, then pushed the change.
however, this is still breaking.

any idea?

[docs] link this project to Vercel

Vercel has a great DX experience with open source, Github, and SvelteKit.

In addition to Github Pages deployment of the "master" branch, I think it will be preferable to link this project to Vercel (it should be very very easy, just few clicks).

The reason I think it is needed in addition to Github Pages, is that Vercel can build&preview in parallel all branches, PR and historical commits (per push build). This will give us a preview of the final output, instead of the need to build&test locally.

@orefalo I think you should do it as the maintainer.

Alternative: Use Cloudflare instead. This has better "edge" covering, but has also less good DX experience and features.

Middle pane snaps to zero after third pane appears and first pane resizes

ok, slightly complex, but the app starts out with two panes shown, the left and middle panes. the user can opt to show the third pane on the right, which pops up at 10%. So far so good. However, if you touch the slider between the left and middle panes, the middle pane snaps to zero size. The only way to re-adjust it is to drag the right pane just a bit. Then, it's possible to adjust the size of the left and middle panes. It's far from fatal - and I won't stop using the package - it's great - but it's not ideal.
Here's the bit of code I'm using:

<Splitpanes on:resized={resize} >
  <Pane size={initialPaneSize} >
    <canvas id="renderCanvas" touch-action="pan-x pan-y pinch-zoom" bind:this={canvas}> </canvas>
    <div class="tinfo"  bind:this={tinfo}> 
      <TurtleInfo/>
    </div>
  </Pane>
  <Pane snapSize=20>
    <LSExplorer/>
  </Pane>
  {#if $showExamples}
    <Pane size=10 maxSize=20>
      <Examples/>
    </Pane>
  {/if}
</Splitpanes>

image
When right pane opens:
image
After trying to adjust left and middle panes:
image

Native style snap

First of all, thanks for porting this to Svelte! It's really great, my only quibble is the snapping mechanism. It's not as good as it could be. I want to make app UIs that feel as solid as native apps, and it's worth looking at how they do snapping.

Two good examples are VS Code and Apple's Finder. The sidebar's splitter has a (fixed) "minSize". If you keep resizing below that size, you reach a threshold at about half the width of the pane, causing it to collapse (or expand again).

I tried playing around with snapSize and minSize, but apparently the snap mechanism of svelte-splitpanes is the opposite of VS Code and Finder. Instead of snapping to 0 when below a certain threshold, it snaps to minSize when below snapSize. To me, at least, that's not very intuitive. It feels more flimsy than professional UIs.

To fully replicate VS Code style splitpanes, fixed sizes would also have to be supported (discussed in #33). I think it's not just a nice to have. A good use case is exactly that of UIs where the sidebar should be collapsible, while still having a fixed "minSize" that keeps the sidebar visible until it snaps.

Need to toggle a special class for the "active" splitter

And then I was shocked, I didn't notice this before.

It make sense to style the currently "dragged" splitter differently, but right now there is not an easy way for this.

Should be easy, just to toggle some class name on the "splitter" div element, which reports if it's active or not.
What should be the name? (to avoid collision)

Add/Remove Panes issues

In the Adding splitters programmatically demo at https://orefalo.github.io/svelte-splitpanes/

Remove all splitters in the panel by clicking the remove button well beyond the number of active sub panes.

Then add the panels back

Two issues:

  1. It takes several clicks to get the first panel to show -> the counter needs to be bounded
  2. First panel doesn't show, the splitpane shows on the 2nd iteration, but it's closed
Screen.Recording.2022-06-21.at.3.57.03.PM.mov

!

Browser detection possible issue

In b6d4a28, you change the browser detection to be based on

import { browser } from '$app/env';

While this is the recommended way in SvelteKit, I'm not sure it's good for a library.
The reason is the way SvelteKit bundle things trough Vite. The environment variables are set by the bundler, however, when exporting as a library, the library could be used outside of SvelteKit, with a bundler(e.g. regular Svelte project) that doesn't export this environment variable.

Maybe SvelteKit is smarter when exporting as a library specifically, but I'm not sure. All I say is that we need to test the output library files and to bundle a Svelte project using this library without setting this environment, and check.

Unsafe event binding

The event binding on the following lines are unsafe:

function bindEvents() {
document.addEventListener('mousemove', onMouseMove, { passive: false });
document.addEventListener('mouseup', onMouseUp);
// Passive: false to prevent scrolling while touch dragging.
if ('ontouchstart' in window) {
document.addEventListener('touchmove', onMouseMove, { passive: false });
document.addEventListener('touchend', onMouseUp);
}
}
function unbindEvents() {
//@ts-ignore
document.removeEventListener('mousemove', onMouseMove, { passive: false });
document.removeEventListener('mouseup', onMouseUp);
if ('ontouchstart' in window) {
//@ts-ignore
document.removeEventListener('touchmove', onMouseMove, { passive: false });
document.removeEventListener('touchend', onMouseUp);
}
}
function onMouseDown(_event: TouchEvent | MouseEvent, splitterIndex: number) {
bindEvents();
isMouseDown = true;
activeSplitter = splitterIndex;
}
function onMouseMove(event: MouseEvent | TouchEvent) {
if (isMouseDown) {
// Prevent scrolling while touch dragging (only works with an active event, eg. passive: false).
event.preventDefault();
isDragging = true;
calculatePanesSize(getCurrentMouseDrag(event));
dispatchSizeEvent('resize');
}
}
function onMouseUp() {
if (isDragging) {
dispatchSizeEvent('resized');
}
isMouseDown = false;
// Keep dragging flag until click event is finished (click happens immediately after mouseup)
// in order to prevent emitting `splitter-click` event if splitter was dragged.
setTimeout(() => {
isDragging = false;
unbindEvents();
}, 100);
}

Why? Because the Svelte component might be destroyed while the user start the splitter dragging.

Solution 1

Add a Boolean variable indicating if the events are bounded or not, and do the following:

onDestroy(() => {
    if (eventsBounded) {
        unbindEvents();
    }
});

Solution 2

Use <svelte:window>.
Indeed, see the following quote from Svelte docs:

The svelte:window element allows you to add event listeners to the window object without worrying about removing them when > the component is destroyed, or checking for the existence of window when server-side rendering.
Unlike svelte:self, this element may only appear at the top level of your component and must never be inside a block or element.

It is a simple solution, but I think it fails to detect if ontouchstart is an available window event or not, as this lines checks:

if ('ontouchstart' in window) {
document.addEventListener('touchmove', onMouseMove, { passive: false });
document.addEventListener('touchend', onMouseUp);
}

This also requires redesigning the events handling, to check the current state (e.g. isReady).

Solution 3

Like Solution 2, but better. This is experimental, didn't check it at all.
You might be able to condition svelte:window tag based on some JS condition. The result should be:

<svelte:window on:... />
{#if browser && ('ontouchstart' in window)}
<svelte:window on:... />
{/if}

lock or unlock editing of layouts

thank you for the awesome package!

I am making a midi controller app where people will be able to create their own layouts and play. I want to use this package for that. but, only if there were something like "lock layout editing" feature. so, when they play, they will not be able to accidentally mess up their layouts. Please implement a boolean prop for editability of pane. e.g. editable={false}

Also, it will be helpful if the event listeners for editability of panes are removed when editable=false (less computational load) and when the value is set to true, panes will have their event listeners.

thanks in advance!

[Setting Change] Allow all workflows to run during PR

When a non-collaborator publishes PR, GitHub requires by default to approve running the workflow for his PRs.
I suggest changing this strict security to a more lenient by the project settings/actions/general as described here. Specifically, I think we should pick the first bullet, the least restrictive, since the workflows that are activated by PR are secured:
תמונה

TypeError: Cannot read properties of undefined (reading 'Splitpanes')

Hey I just installed this package and tried to use it in its simplest form but I get an error:

TypeError: Cannot read properties of undefined (reading 'Splitpanes')
     at eval (/src/routes/(root)/+page.svelte:13:66)
     at Object.$$render (/node_modules/svelte/internal/index.mjs:1878:22)
     at Object.default (/.svelte-kit/generated/root.svelte:58:134)
     at eval (/src/routes/+layout.svelte:55:146)
     at Object.$$render (/node_modules/svelte/internal/index.mjs:1878:22)
     at eval (/.svelte-kit/generated/root.svelte:56:126)
     at $$render (/node_modules/svelte/internal/index.mjs:1878:22)
     at Object.render (/node_modules/svelte/internal/index.mjs:1886:26)
     at render_response 

My Code:

<script>
  import { Pane, Splitpanes } from "svelte-splitpanes";
</script>

<Splitpanes theme="" class="" id="panes">
  <Pane class="p-4">Hello</Pane>
  <Pane class="p-4">World</Pane>
</Splitpanes>

Set not only the cursor of the splitter

Continuing PR #6, I think still that something is missing, and Split.js does it better.
Recall last video in #6 (the demo after fix):

svelte-splitpane-pointer-events-issue-after.mov

You can see that cursor: col-resize; or cursor: row-resize; is set only to the splitter, meaning it's not showing the cursor on the container at all (when the user escapes the splitter as shown in the video), nor showing the cursor on the whole document.body element.

You can see how natural it feels in the Split.js demo. In the following video, the whole time the user is dragging the splitter:

split-js-good-cursor.mov

Indeed, you can see in their code they set the cursor not only to the splitter, but also to the container and the body elements (source):

// Set the cursor at multiple levels
self.gutter.style.cursor = cursor
self.parent.style.cursor = cursor
document.body.style.cursor = cursor

I suggest to do the same in this project.

Accessability

Following #9, we need to have accessibility for the splitter, by ARIA attributes and by keyboard interaction.

  1. MDN on separator role
  2. W3 on windows splitter.
  3. See also the list of proposed examples in this issue. I'd personally think that this one is the clearest.

There are two types of splitters - non-focusable(i.e. static) and focusable(interactive). Read source 1 for telling which aria attributes should be on each on.
I believe that a splitter in this library is consider to be non-focusable(i.e. static) if and only if minSize===maxSize, as you can see the example in this library docs.

Focusable (interactive) splitter in this library

  • Should have the HTML attribute tabindex = 0. Notice that non-focusable(i.e. static) splitters should not be focusable at all!
  • I believe that default style when it's focused should be like in hover.
  • I believe we should implement all the keyboard binding the same as described in Source 2 (including the optional ones). The keys should be as what described there by default, but allow the user to change the key binding he prefer. Notice that if we're in RTL, the right arrow key should point to the previous pane!
  • Notice in Source 2 the key binding of F6(cycle between panes) is a really cool one in my opinion. I think that each pane should have the HTML attribute tabindex = -1(meaning focusable, but only by script), and pressing F6 will detect which pane has the current focus, and will cycle through the panes and set the focus on the next one. I believe, although not written by the official standards, the if the user press Shift + F6, then it should cycle backwards, as the Shift key invert the operation.
  • Continuing the previous bullet on F6, I believe that a special care should be for nested panes. I think the correct way to deal with this issue is to cycle only through the leaf panes(meaning, on on panes which don't have a nested SplitPanes component inside of them).

I think we need to be careful and clever for dealing with Svelte context API for passing sizes data from SplitPanes to Pane components.

I have an idea how to implement it, just need a green light to do so.

Set min height and width in px

Hey, I think it would be cool to set the min height and width in px, could be useful in some cases where u want to use a custom element as the splitter :)

Using with keyed each blocks?

Looking for some advice for using this library with keyed each blocks:

<Splitpanes>
  {#each array as object (object.id)}
    <Pane>
      <InnerComponent value={object.value}/>
    </Pane>
  {/each}
</Splitpanes>

I want to change the order of the array (and resulting panes) without re-rendering the InnerComponent.

When I use the above code, the InnerComponent does not re-render (good).

Neither do the Panes (bad): the splitters act as if the Pane was in it's original position (e.g. resizing effects the wrong Pane).

expand arbitrary pane

is there a way to expand an arbitrary pane?

imagine the following scenario:

<script lang="ts">
  import { Splitpanes, Pane } from 'svelte-splitpanes';
</script>

<Splitpanes>
  <!-- pane1 -->
  <Pane size={25} snapSize={18}>
    ...
  </Pane>

  <!-- pane2 -->
  <Pane size={75}>
    ....
  </Pane>
</Splitpanes>

i would like to add a button on the page, which when clicked, would expand pane1 to its set size (25).

is this possible?

perhaps a way of doing this would be to export the IPane instance from the Pane, so that the consumer could bind to it, and use the setSz function (im not sure if this function means setSize, just taking my chances lol)

How do you style/theme using native CSS?

I can't get the homepage styling examples to work at all. I don't have SCSS.

<main class="container">
           <button > button </button>
    <Splitpanes>
        <Pane minSize={10}>
    <button > button </button>
        </Pane>
        <Pane minSize={10} >
            <button > button </button>
        </Pane>
    </Splitpanes>
</main>

<style >

    .splitpanes .default-theme .splitpanes__splitter {

        background-color: #c44c4c;
        box-sizing: border-box;
        position: relative;
        flex-shrink: 0;
    }
    .splitpanes__splitter {
        background-color: #c44c4c;
        box-sizing: border-box;
        position: relative;
        flex-shrink: 0;
    }
</style >

Trying to change some basic colors but nothing happens. Any tips?

Don't resize one pane when container size changes

As far as I can tell, there's no way to create a sidebar that the user can resize, but that stays a fixed size (in pixels) when the window is resized. This is a common sidebar or panel configuration, so I think it should be possible in a library like this.

Is this already possible?

Error when using with sveltekit 1.0

When I attempt to implement this in +layout.svelte or +page.svelte I get the below error;

is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules. Otherwise you may need to fix a .
Error: is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules. Otherwise you may need to fix a .

Splitter Jiggler

A little video is better than a long speach -
plz be patient....

Screen.Recording.2022-06-21.at.3.59.54.PM.mov

Typescript Issues in Svelte

I freshly installed and am getting an error on the Pane component:

Argument of type 'typeof Pane' is not assignable to parameter of type 'ConstructorOfATypedSvelteComponent'.
Types of construct signatures are incompatible.
Type 'new (options: ComponentConstructorOptions<{ size?: number | null | undefined; minSize?: number | undefined; maxSize?: number | undefined; snapSize?: number | undefined; class?: string | undefined; }>) => Pane' is not assignable to type 'new (args: { target: any; props?: any; }) => ATypedSvelteComponent'.
Construct signature return types 'Pane' and 'ATypedSvelteComponent' are incompatible.
The types of '$on' are incompatible between these types.
Type '(type: K, callback: (e: {}[K]) => void) => () => void' is not assignable to type '(event: string, handler: ((e: any) => any) | null | undefined) => () => void'.
Types of parameters 'callback' and 'handler' are incompatible.
Type '((e: any) => any) | null | undefined' is not assignable to type '(e: never) => void'.
Type 'undefined' is not assignable to type '(e: never) => void'.

Possible causes:

  • You use the instance type of a component where you should use the constructor type
  • Type definitions are missing for this Svelte Component. If you are using Svelte 3.31+, use SvelteComponentTyped to add a definition:
    import type { SvelteComponentTyped } from "svelte";
    class ComponentName extends SvelteComponentTyped<{propertyName: string;}> {}ts(2345)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.