feat: Phase 1 — extract the client (web SPA + desktop) to dtoro/oikos-web
Problem: the hexagonal refactor churns the backend tree for nine more phases; the UI delivery stack (web/ SPA, cmd/desktop Wails wrapper, compose/web image) must move to its own repo first so doc/layout rewrites land once on a backend-only tree. Change: - New repo git.hubris.network/dtoro/oikos-web (v0.33.0): web/, desktop/ (updateURL repointed to oikos-web releases), compose/, own CI (web + desktop jobs), own deploy script (CI-green gate, TOCTOU guard, version-tagged images, prune-to-3), own webhook receiver on :9798 + launchd unit, own compose project publishing the same 8091:80. - Cutover executed on mac-mini in order: oikos stack's web service stopped+removed, oikos-web project brought up on 8091; outer Caddy untouched (targets the published port) — serving + Authentik flow + /wails 404 quirk verified post-cutover. - Stripped from oikos: web/, cmd/desktop/, compose/web/, desktop CI workflow, ci.yml web job, Makefile ui/desktop/desktop-package/install targets, the compose web service, oikos-web from deploy.sh's fallback prune list; wails + go-keyring dropped from go.mod, vendor synced. - README / CONTRIBUTING / AGENTS.md / .agents dev+operations docs now point at the new repo; mbse + mascot design docs carry a path note. Risk: production SPA serving depends on the new pipeline now; rollback is versioned-image re-up of the old web service from a pre-split checkout (port 8091). Desktop builds installed before the split still check dtoro/oikos releases — one manual reinstall, noted in the oikos-web release notes. Verification: go vet, make test (race), make generate-check, golangci (no new findings; baseline down 400→365); post-cutover curls — localhost:8091 200, /wails/runtime.js 404, outer Caddy 302 Authentik.
This commit is contained in:
22
web/node_modules/svelte-splitpanes/LICENSE
generated
vendored
Normal file
22
web/node_modules/svelte-splitpanes/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Antoni Andre
|
||||
Copyright (c) 2022 Olivier Refalo (Svelte port)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
347
web/node_modules/svelte-splitpanes/README.md
generated
vendored
Normal file
347
web/node_modules/svelte-splitpanes/README.md
generated
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||

|
||||
|
||||
# Svelte-Splitpanes
|
||||
|
||||
[](https://www.npmjs.com/package/svelte-splitpanes)
|
||||

|
||||
[](https://orefalo.github.io/svelte-splitpanes/minified-size)
|
||||

|
||||

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

|
||||
|
||||
## 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](https://antoniandre.github.io/splitpanes/) and through feature enhancements, became one of the best splitpane implementation.
|
||||
|
||||
Special thanks to all contributors and in particular [Tal500](https://github.com/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
|
||||
|
||||
|  |  |  |  |  |  |
|
||||
| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | 11 ✔ |
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#orefalo/svelte-splitpanes&Date)
|
||||
|
||||
## Demo & Documentation
|
||||
|
||||
- [REPL Demo](https://svelte.dev/repl/1e96cbd4bcd148e3b85a4c8ca76d7309)
|
||||
- [More complex demos and examples](https://orefalo.github.io/svelte-splitpanes/)
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
$ npm i svelte-splitpanes
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```svelte
|
||||
<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.
|
||||
|
||||
```css
|
||||
/* 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
|
||||
|
||||
```svelte
|
||||
<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.
|
||||
|
||||
### Commiting changes
|
||||
|
||||
- run `pnpm commit`
|
||||
|
||||
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**.
|
||||
|
||||
Commits are accepted, as long as they comply to the _commit message format_ described below.
|
||||
|
||||
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`
|
||||
|
||||
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:
|
||||
|
||||
0. Make sure your environment is up to date, by running periodically `pnpm install`.
|
||||
1. Make sure that all the relevant changes are staged.
|
||||
2. (Optional) Run `pnpm build && pnpm test` to execute Playwright tests.
|
||||
3. 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](https://github.com/googleapis/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**:
|
||||
|
||||
0. Merge all the relevant changes to master, and make sure that all Github actions checks passed and the auto-generated docs are fine.
|
||||
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.
|
||||
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).
|
||||
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 ):
|
||||
|
||||
```shell
|
||||
$ 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`):
|
||||
|
||||
```shell
|
||||
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
|
||||
108
web/node_modules/svelte-splitpanes/dist/Pane.svelte
generated
vendored
Normal file
108
web/node_modules/svelte-splitpanes/dist/Pane.svelte
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
<script lang="ts">import { getContext, onMount, onDestroy, hasContext } from 'svelte';
|
||||
import { KEY } from './Splitpanes.svelte';
|
||||
import { browser } from './internal/env.js';
|
||||
import { gatheringKey } from './internal/GatheringRound.svelte';
|
||||
import { getDimensionName } from './internal/utils/sizing.js';
|
||||
import { carefullCallbackSource } from './internal/utils/functions';
|
||||
const { ssrRegisterPaneSize, onPaneInit, clientOnly: clientOnlyContext, isHorizontal, showFirstSplitter, veryFirstPaneKey } = getContext(KEY);
|
||||
// PROPS
|
||||
export let size = null;
|
||||
export let minSize = 0;
|
||||
export let maxSize = 100;
|
||||
export let snapSize = 0;
|
||||
// css class
|
||||
let clazz = '';
|
||||
export { clazz as class };
|
||||
// VARIABLES
|
||||
const key = {};
|
||||
const gathering = !browser && hasContext(gatheringKey);
|
||||
const { undefinedPaneInitSize } = (!gathering ? onPaneInit(key) : {});
|
||||
let element;
|
||||
let sz = size ?? undefinedPaneInitSize;
|
||||
let isSplitterActive = false;
|
||||
// CALLBACKS
|
||||
let clientCallbacks = undefined;
|
||||
/**
|
||||
* This is an object of callbacks that are safe to be called on browser even when the object `clientCallbacks`
|
||||
* isn't initialized yet (i.e. before `onPaneAdd()`).
|
||||
*
|
||||
* In the case of the object isn't initialized yet, calling this callbacks will do nothing.
|
||||
*/
|
||||
const carefullClientCallbacks = browser
|
||||
? carefullCallbackSource(() => clientCallbacks)
|
||||
: undefined;
|
||||
const reportGivenSizeChangeSafe = (size) => {
|
||||
// We put an extra check of `size != sz` here and not in the reactive statement, since we don't want a change
|
||||
// of `sz` to trigger report.
|
||||
if (clientCallbacks && size != sz) {
|
||||
carefullClientCallbacks?.('reportGivenSizeChange')(size);
|
||||
}
|
||||
};
|
||||
// REACTIVE
|
||||
$: {
|
||||
if (browser && typeof size === 'number') {
|
||||
reportGivenSizeChangeSafe(size);
|
||||
}
|
||||
}
|
||||
$: dimension = getDimensionName($isHorizontal);
|
||||
$: style = `${dimension}: ${sz}%;`;
|
||||
if (gathering && ssrRegisterPaneSize) {
|
||||
ssrRegisterPaneSize(size);
|
||||
}
|
||||
else if (browser) {
|
||||
onMount(() => {
|
||||
const inst = {
|
||||
index: 0,
|
||||
key,
|
||||
element: element,
|
||||
givenSize: size,
|
||||
sz: () => sz,
|
||||
setSz: v => {
|
||||
sz = v;
|
||||
if (typeof size === 'number' && size !== sz) {
|
||||
size = sz;
|
||||
}
|
||||
},
|
||||
min: () => minSize,
|
||||
max: () => maxSize,
|
||||
snap: () => snapSize,
|
||||
setSplitterActive: (isActive) => {
|
||||
isSplitterActive = isActive;
|
||||
},
|
||||
isReady: false
|
||||
};
|
||||
clientCallbacks = clientOnlyContext?.onPaneAdd(inst);
|
||||
});
|
||||
onDestroy(() => {
|
||||
clientOnlyContext?.onPaneRemove(key);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if !gathering}
|
||||
<!-- Splitter -->
|
||||
{#if $veryFirstPaneKey !== key || $showFirstSplitter}
|
||||
<!-- this a11y issue is known, and will be taken care of as part of the a11y feature issue in #11 -->
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class="splitpanes__splitter {isSplitterActive ? 'splitpanes__splitter__active' : ''}"
|
||||
on:mousedown={carefullClientCallbacks?.('onSplitterDown')}
|
||||
on:touchstart={carefullClientCallbacks?.('onSplitterDown')}
|
||||
on:click={carefullClientCallbacks?.('onSplitterClick')}
|
||||
on:dblclick={carefullClientCallbacks?.('onSplitterDblClick')}>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Pane -->
|
||||
<!-- this a11y issue is known, and will be taken care of as part of the a11y feature issue in #11 -->
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class={`splitpanes__pane ${clazz || ''}`}
|
||||
bind:this={element}
|
||||
on:click={carefullClientCallbacks?.('onPaneClick')}
|
||||
{style}>
|
||||
<slot />
|
||||
</div>
|
||||
{/if}
|
||||
33
web/node_modules/svelte-splitpanes/dist/Pane.svelte.d.ts
generated
vendored
Normal file
33
web/node_modules/svelte-splitpanes/dist/Pane.svelte.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
||||
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
||||
$$bindings?: Bindings;
|
||||
} & Exports;
|
||||
(internal: unknown, props: Props & {
|
||||
$$events?: Events;
|
||||
$$slots?: Slots;
|
||||
}): Exports & {
|
||||
$set?: any;
|
||||
$on?: any;
|
||||
};
|
||||
z_$$bindings?: Bindings;
|
||||
}
|
||||
type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
||||
default: any;
|
||||
} ? Props extends Record<string, never> ? any : {
|
||||
children?: any;
|
||||
} : {});
|
||||
declare const Pane: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
||||
size?: number | null;
|
||||
minSize?: number;
|
||||
maxSize?: number;
|
||||
snapSize?: number;
|
||||
class?: string;
|
||||
}, {
|
||||
default: {};
|
||||
}>, {
|
||||
[evt: string]: CustomEvent<any>;
|
||||
}, {
|
||||
default: {};
|
||||
}, {}, string>;
|
||||
type Pane = InstanceType<typeof Pane>;
|
||||
export default Pane;
|
||||
978
web/node_modules/svelte-splitpanes/dist/Splitpanes.svelte
generated
vendored
Normal file
978
web/node_modules/svelte-splitpanes/dist/Splitpanes.svelte
generated
vendored
Normal file
@@ -0,0 +1,978 @@
|
||||
<script context="module" lang="ts">export const KEY = {};
|
||||
// Constants for better maintainability
|
||||
const DOUBLE_CLICK_TIMEOUT = 500;
|
||||
const DRAG_FINISH_DELAY = 100;
|
||||
const SIZE_THRESHOLD = 0.1; // Minimum size threshold for calculations
|
||||
const FULL_SIZE = 100; // Full percentage size
|
||||
/**
|
||||
* the third argument for event bundler
|
||||
* @see https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
|
||||
*/
|
||||
const thirdEventArg = (() => {
|
||||
let result = false;
|
||||
try {
|
||||
const arg = Object.defineProperty({}, 'passive', {
|
||||
get() {
|
||||
result = { passive: true };
|
||||
return true;
|
||||
}
|
||||
});
|
||||
// @ts-expect-error no overload matches
|
||||
window.addEventListener('testpassive', arg, arg);
|
||||
// @ts-expect-error no overload matches
|
||||
window.remove('testpassive', arg, arg);
|
||||
}
|
||||
catch (_e) {
|
||||
/* */
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
/**
|
||||
* Type guard to check if an event is a TouchEvent.
|
||||
*/
|
||||
// function isTouchEvent(event: MouseEvent | TouchEvent): event is TouchEvent {
|
||||
// return 'touches' in event;
|
||||
// }
|
||||
</script>
|
||||
|
||||
<script lang="ts">import { onMount, onDestroy, setContext, createEventDispatcher, tick, afterUpdate } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import GatheringRound from './internal/GatheringRound.svelte';
|
||||
import { browser } from './internal/env.js';
|
||||
import { getDimensionName } from './internal/utils/sizing.js';
|
||||
import { elementRectWithoutBorder, getGlobalMousePosition, positionDiff, getElementRect } from './internal/utils/position.js';
|
||||
import { forEachPartial, sumPartial } from './internal/utils/array.js';
|
||||
import { calcComputedStyle } from './internal/utils/styling.js';
|
||||
// PROPS ----------------
|
||||
//@ts-expect-error undefined not assigned to string
|
||||
export let id = undefined;
|
||||
// horiz or verti?
|
||||
export let horizontal = false;
|
||||
// when true, moving a splitter can push other panes
|
||||
export let pushOtherPanes = true;
|
||||
// open/close on double click
|
||||
export let dblClickSplitter = true;
|
||||
// true if RTL
|
||||
export let rtl = 'auto';
|
||||
// true to display the first splitter
|
||||
export let firstSplitter = false;
|
||||
// css style
|
||||
export let style = null;
|
||||
// the splitter theme to use
|
||||
export let theme = 'default-theme';
|
||||
// css class
|
||||
let clazz = '';
|
||||
export { clazz as class };
|
||||
// VARIABLES ----------------
|
||||
//used to bubble events up
|
||||
const dispatch = createEventDispatcher();
|
||||
// the splitpane component
|
||||
let container;
|
||||
// true when component is ready, prevents emitting console warnings on hot reloading.
|
||||
let isReady = false;
|
||||
// true when pane reset is awaiting for the next tick, to avoid double call to pane reset.
|
||||
let isAwaitingPaneReset = false;
|
||||
// true after the initial timeout 0 waiting, prevents CSS transitions until then.
|
||||
let isAfterInitialTimeoutZero = false;
|
||||
// true when mouse is down
|
||||
let isMouseDown = false;
|
||||
// true when a splitter is being dragged
|
||||
let isDragging = false;
|
||||
// that's the splitter than is being dragged
|
||||
let activeSplitter = -1;
|
||||
// that's well the clicked splitter!
|
||||
let clickedSplitter = -1;
|
||||
// used to detect double clicks
|
||||
let timeoutId;
|
||||
// panes per insertion order (pane.index is the order index)
|
||||
let panes = new Array();
|
||||
// passed to the children via the context - writable to ensure proper reactivity
|
||||
const isHorizontal = writable(horizontal);
|
||||
const showFirstSplitter = writable(firstSplitter);
|
||||
// tells the key of the very first pane, or undefined if not recieved yet
|
||||
const veryFirstPaneKey = writable(undefined);
|
||||
let activeSplitterElement;
|
||||
let activeSplitterDrag;
|
||||
let ssrPaneDefinedSizeSum = 0;
|
||||
let ssrPaneUndefinedSizeCount = 0;
|
||||
// Cache for drag operations to avoid repeated style calculations
|
||||
let cachedContainerStyle = null;
|
||||
let cachedContainerRect = null;
|
||||
let cachedIsRTL = false;
|
||||
// Cache for splitter size calculations during drag
|
||||
// const cachedSplitterSizes: {
|
||||
// activeSplitterSize: number;
|
||||
// totalBefore: number;
|
||||
// totalAfter: number;
|
||||
// totalSplitter: number;
|
||||
// } | null = null;
|
||||
// Request animation frame ID for drag updates
|
||||
// let rafId: number | null = null;
|
||||
// let pendingDragData: { tdrag: number; containerSize: number } | null = null;
|
||||
// Snapshot for verifyAndUpdatePanesOrder optimization
|
||||
let lastChildrenSnapshot = [];
|
||||
// REACTIVE ----------------
|
||||
$: $isHorizontal = horizontal;
|
||||
$: $showFirstSplitter = firstSplitter;
|
||||
// used to complete rendering service side (SSR mode)
|
||||
function ssrRegisterPaneSize(size) {
|
||||
if (size === null) {
|
||||
++ssrPaneUndefinedSizeCount;
|
||||
}
|
||||
else {
|
||||
ssrPaneDefinedSizeSum += size;
|
||||
}
|
||||
}
|
||||
const onPaneInit = _key => {
|
||||
if ($veryFirstPaneKey === undefined) {
|
||||
$veryFirstPaneKey = _key;
|
||||
}
|
||||
return {
|
||||
undefinedPaneInitSize: browser
|
||||
? 0
|
||||
: (FULL_SIZE - ssrPaneDefinedSizeSum) / ssrPaneUndefinedSizeCount
|
||||
};
|
||||
};
|
||||
setContext(KEY, {
|
||||
showFirstSplitter,
|
||||
veryFirstPaneKey,
|
||||
isHorizontal,
|
||||
ssrRegisterPaneSize: browser ? undefined : ssrRegisterPaneSize,
|
||||
onPaneInit,
|
||||
clientOnly: browser
|
||||
? {
|
||||
onPaneAdd,
|
||||
onPaneRemove
|
||||
}
|
||||
: undefined
|
||||
});
|
||||
/**
|
||||
* Calculates the index of a pane element within its parent container.
|
||||
* Optimized to avoid array allocation by iterating through siblings directly.
|
||||
*
|
||||
* @param paneElement - The HTML element of the pane
|
||||
* @returns The zero-based index of the pane among all pane elements
|
||||
*/
|
||||
function calculatePaneIndex(paneElement) {
|
||||
let index = -1;
|
||||
let currentNode = paneElement.parentNode?.firstChild;
|
||||
while (currentNode) {
|
||||
if (currentNode.nodeType === Node.ELEMENT_NODE &&
|
||||
currentNode.classList.contains('splitpanes__pane')) {
|
||||
index++;
|
||||
}
|
||||
if (currentNode === paneElement)
|
||||
break;
|
||||
currentNode = currentNode.nextSibling;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
function onPaneAdd(pane) {
|
||||
// 1. Add pane to array at the same index it was inserted in the <splitpanes> tag.
|
||||
const index = calculatePaneIndex(pane.element);
|
||||
if (index === 0) {
|
||||
// Need to update the first pane key, because the first pane can be changed in runtime.
|
||||
$veryFirstPaneKey = pane.key;
|
||||
}
|
||||
//inserts pane at proper array index
|
||||
panes.splice(index, 0, pane);
|
||||
// reindex panes
|
||||
for (let i = 0; i < panes.length; i++) {
|
||||
panes[i].index = i;
|
||||
}
|
||||
if (isReady) {
|
||||
// 2. tick and resize the panes.
|
||||
tickAndResetPaneSizes().then(() => {
|
||||
// 3. Set the pane as ready
|
||||
pane.isReady = true;
|
||||
// 4. Fire `pane-add` event.
|
||||
dispatch('pane-add', {
|
||||
index,
|
||||
panes: prepareSizeEvent()
|
||||
});
|
||||
});
|
||||
}
|
||||
const paneForward = (cb, includingFirst = true) => (value) => {
|
||||
if (includingFirst || pane.index > 0) {
|
||||
cb(value, pane);
|
||||
}
|
||||
};
|
||||
return {
|
||||
onSplitterDown: paneForward(onMouseDown, false),
|
||||
onSplitterClick: paneForward(onSplitterClick, false),
|
||||
onSplitterDblClick: paneForward(onSplitterDblClick),
|
||||
onPaneClick: paneForward(onPaneClick),
|
||||
reportGivenSizeChange: paneForward(reportGivenSizeChange)
|
||||
};
|
||||
}
|
||||
async function onPaneRemove(key) {
|
||||
// 1. Remove the pane from array and redo indexes.
|
||||
const index = panes.findIndex(p => p.key === key);
|
||||
// race condition - typically happens when the dev server restarts
|
||||
if (index >= 0) {
|
||||
const removed = panes.splice(index, 1)[0];
|
||||
// reindex panes
|
||||
for (let i = 0; i < panes.length; i++) {
|
||||
panes[i].index = i;
|
||||
}
|
||||
if (index === 0) {
|
||||
$veryFirstPaneKey = panes.length > 0 ? panes[0].key : undefined;
|
||||
}
|
||||
if (isReady) {
|
||||
// 3. tick and resize the panes.
|
||||
await tickAndResetPaneSizes();
|
||||
// 4. Fire `pane-remove` event.
|
||||
dispatch('pane-remove', {
|
||||
removed,
|
||||
panes: prepareSizeEvent()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// called by sub-panes
|
||||
function onPaneClick(_event, pane) {
|
||||
dispatch('pane-click', pane);
|
||||
}
|
||||
function reportGivenSizeChange(newGivenSize, pane) {
|
||||
pane.setSz(newGivenSize);
|
||||
tickAndResetPaneSizes();
|
||||
}
|
||||
onMount(() => {
|
||||
verifyAndUpdatePanesOrder();
|
||||
resetPaneSizes();
|
||||
for (let i = 0; i < panes.length; i++) {
|
||||
panes[i].isReady = true;
|
||||
}
|
||||
isReady = true;
|
||||
dispatch('ready');
|
||||
setTimeout(() => {
|
||||
isAfterInitialTimeoutZero = true;
|
||||
}, 0);
|
||||
});
|
||||
if (browser) {
|
||||
onDestroy(() => {
|
||||
if (isReady) {
|
||||
// this is to solve an edge case:
|
||||
// when the user starts dragging and the component is destroyed, leaving behind hanging events
|
||||
unbindEvents();
|
||||
}
|
||||
// Prevent emitting console warnings on hot reloading.
|
||||
isReady = false;
|
||||
});
|
||||
}
|
||||
afterUpdate(() => {
|
||||
verifyAndUpdatePanesOrder();
|
||||
});
|
||||
// Tells in the current DOM state if we are in RTL direction or not.
|
||||
function isRTL(containerComputedStyle) {
|
||||
if (rtl === 'auto') {
|
||||
// the try catch is to support old browser, flag is preset to false
|
||||
try {
|
||||
return (containerComputedStyle ?? calcComputedStyle(container)).direction === 'rtl';
|
||||
}
|
||||
catch (_err) {
|
||||
// We want application to not crush, but don't care about the message
|
||||
}
|
||||
}
|
||||
// otherwise
|
||||
return rtl === true;
|
||||
}
|
||||
function bindEvents() {
|
||||
document.body.style.cursor = $isHorizontal ? 'col-resize' : 'row-resize';
|
||||
document.addEventListener('mousemove', onMouseMove, thirdEventArg);
|
||||
document.addEventListener('mouseup', onMouseUp);
|
||||
if ('ontouchstart' in window) {
|
||||
document.addEventListener('touchmove', onMouseMove, thirdEventArg);
|
||||
document.addEventListener('touchend', onMouseUp);
|
||||
}
|
||||
}
|
||||
function unbindEvents() {
|
||||
document.body.style.cursor = '';
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
if ('ontouchstart' in window) {
|
||||
document.removeEventListener('touchmove', onMouseMove);
|
||||
document.removeEventListener('touchend', onMouseUp);
|
||||
}
|
||||
}
|
||||
const isSplitterElement = (node) => node.nodeType === Node.ELEMENT_NODE &&
|
||||
node.classList.contains('splitpanes__splitter');
|
||||
function getOrientedDiff(drag, elementSize, isRTL) {
|
||||
let tdrag = drag[horizontal ? 'top' : 'left'];
|
||||
if (isRTL && !horizontal)
|
||||
tdrag = elementSize - tdrag;
|
||||
return tdrag;
|
||||
}
|
||||
const getCurrentDimensionName = () => getDimensionName(horizontal);
|
||||
function onMouseDown(event, splitterPane) {
|
||||
isMouseDown = true;
|
||||
activeSplitter = splitterPane.index;
|
||||
splitterPane.setSplitterActive(true);
|
||||
const paneElement = splitterPane.element;
|
||||
let activeSplitterNode = paneElement;
|
||||
while (activeSplitterNode) {
|
||||
activeSplitterNode = activeSplitterNode.previousSibling;
|
||||
if (activeSplitterNode && isSplitterElement(activeSplitterNode)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (activeSplitterNode === null) {
|
||||
console.error("Splitpane Error: Active splitter wasn't found!");
|
||||
return; // Don't bind move event on error
|
||||
}
|
||||
activeSplitterElement = activeSplitterNode;
|
||||
const globalMousePosition = getGlobalMousePosition(event);
|
||||
const splitterRect = getElementRect(activeSplitterElement);
|
||||
// Cache container style and dimensions for the drag operation
|
||||
cachedContainerStyle = calcComputedStyle(container);
|
||||
cachedContainerRect = elementRectWithoutBorder(container, cachedContainerStyle);
|
||||
cachedIsRTL = isRTL(cachedContainerStyle);
|
||||
activeSplitterDrag = getOrientedDiff(positionDiff(globalMousePosition, splitterRect), splitterRect[getCurrentDimensionName()], cachedIsRTL);
|
||||
bindEvents();
|
||||
}
|
||||
function onMouseMove(event) {
|
||||
if (isMouseDown && cachedContainerRect) {
|
||||
isDragging = true;
|
||||
const globalMousePosition = getGlobalMousePosition(event);
|
||||
// Use cached values to avoid repeated expensive DOM calculations
|
||||
const containerSizeWithoutBorder = cachedContainerRect[getCurrentDimensionName()];
|
||||
const currentMouseDrag = positionDiff(globalMousePosition, cachedContainerRect);
|
||||
const tdrag = getOrientedDiff(currentMouseDrag, containerSizeWithoutBorder, cachedIsRTL);
|
||||
calculatePanesSize(tdrag, containerSizeWithoutBorder);
|
||||
dispatch('resize', prepareSizeEvent());
|
||||
}
|
||||
}
|
||||
function onMouseUp() {
|
||||
if (isDragging) {
|
||||
dispatch('resized', prepareSizeEvent());
|
||||
}
|
||||
isMouseDown = false;
|
||||
const pane = panes[activeSplitter];
|
||||
pane.setSplitterActive(false);
|
||||
// Clear caches after drag operation
|
||||
cachedContainerStyle = null;
|
||||
cachedContainerRect = null;
|
||||
// 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();
|
||||
}, DRAG_FINISH_DELAY);
|
||||
}
|
||||
// If touch device, detect double tap manually (2 taps separated by less than 500ms).
|
||||
function onSplitterClick(event, splitterPane) {
|
||||
if ('ontouchstart' in window) {
|
||||
const splitterIndex = splitterPane.index;
|
||||
// Detect splitter double taps if the option is on.
|
||||
if (dblClickSplitter) {
|
||||
if (clickedSplitter === splitterIndex) {
|
||||
if (timeoutId)
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
onSplitterDblClick(event, splitterPane);
|
||||
clickedSplitter = -1; // Reset for the next tap check.
|
||||
}
|
||||
else {
|
||||
clickedSplitter = splitterIndex;
|
||||
timeoutId = setTimeout(() => {
|
||||
clickedSplitter = -1;
|
||||
}, DOUBLE_CLICK_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isDragging)
|
||||
dispatch('splitter-click', splitterPane);
|
||||
}
|
||||
// On splitter dbl click or dbl tap maximize this pane.
|
||||
function onSplitterDblClick(_event, splitterPane) {
|
||||
if (dblClickSplitter) {
|
||||
const splitterIndex = splitterPane.index;
|
||||
let totalMinSizes = 0;
|
||||
for (let i = 0; i < panes.length; i++) {
|
||||
const pane = panes[i];
|
||||
if (i !== splitterIndex) {
|
||||
totalMinSizes += pane.min();
|
||||
}
|
||||
}
|
||||
const maxExtendedSize = Math.min(Math.max(0, FULL_SIZE - totalMinSizes), splitterPane.max());
|
||||
const totalMaxExtendedPlusMinSizes = totalMinSizes + maxExtendedSize;
|
||||
if (totalMaxExtendedPlusMinSizes >= FULL_SIZE) {
|
||||
// put everything to the minimum, and in the splitterPane put the rest of the size
|
||||
for (let i = 0; i < panes.length; i++) {
|
||||
const pane = panes[i];
|
||||
if (pane !== splitterPane) {
|
||||
pane.setSz(pane.min());
|
||||
}
|
||||
else {
|
||||
pane.setSz(FULL_SIZE - totalMinSizes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// notice that in this case, we can conclude that `panes.length >= 2`
|
||||
// put splitterPane to the maximum (the actual one), and the normal panes to the minimum,
|
||||
// and give the spare to left pane (or to the right pane, if the splitterPane is the first pane)
|
||||
// if this spare size is beyond the pane maximum, need to pass it along to the other panes
|
||||
let leftSpare = FULL_SIZE - totalMaxExtendedPlusMinSizes;
|
||||
splitterPane.setSz(maxExtendedSize);
|
||||
const giveBest = (pane) => {
|
||||
const min = pane.min();
|
||||
const max = pane.max();
|
||||
const szExtra = Math.min(Math.max(0, leftSpare), max - min);
|
||||
pane.setSz(min + szExtra);
|
||||
leftSpare -= szExtra;
|
||||
};
|
||||
// go backward and give the most size as we can
|
||||
for (let i = splitterIndex - 1; i >= 0; i--)
|
||||
giveBest(panes[i]);
|
||||
// go forward and give the most size as we can
|
||||
for (let i = splitterIndex + 1; i < panes.length; i++)
|
||||
giveBest(panes[i]);
|
||||
// at the end of the process, we must have that `leftSpare` is 0
|
||||
if (leftSpare !== 0) {
|
||||
console.warn('Splitpanes: there is a left spare size after computation of splitter double click, which means there are issues on the size constains of the panes.');
|
||||
}
|
||||
}
|
||||
dispatch('pane-maximize', splitterPane);
|
||||
dispatch('resized', prepareSizeEvent());
|
||||
}
|
||||
// onMouseUp might not be called on the second click, so update the mouse state.
|
||||
// TODO: Should also check and unbind events, but better IMO to not bind&unbind on every click, so ignored for now.
|
||||
isMouseDown = false;
|
||||
}
|
||||
const prepareSizeEvent = () => panes.map(pane => ({
|
||||
min: pane.min(),
|
||||
max: pane.max(),
|
||||
size: pane.sz(),
|
||||
snap: pane.snap()
|
||||
}));
|
||||
/**
|
||||
* Returns the drag percentage of the splitter relative to the 2 parts it's inbetween, meaning the ratio between
|
||||
* the size that all the panes before the splitter consumes (ignoring other splitters size) and the total size of the container.
|
||||
*/
|
||||
function getCurrentDragPercentage(tdrag, containerSizeWithoutBorder) {
|
||||
// Here we want the splitter size **including the borders**.
|
||||
// We need to use `Element.getBoundingClientRect()` and not `Element.clientWidth` and `Element.clientHeight`,
|
||||
// bacause the latter round the number of pixels to integer, and additionally, they don't include the borders.
|
||||
const splitterSize = (node) => getElementRect(node)[getCurrentDimensionName()];
|
||||
const activeSplitterSize = splitterSize(activeSplitterElement);
|
||||
let splittersTotalSizeBefore = 0;
|
||||
let currentBeforeNode = activeSplitterElement.previousSibling;
|
||||
while (currentBeforeNode) {
|
||||
if (isSplitterElement(currentBeforeNode)) {
|
||||
splittersTotalSizeBefore += splitterSize(currentBeforeNode);
|
||||
}
|
||||
currentBeforeNode = currentBeforeNode.previousSibling;
|
||||
}
|
||||
let splittersTotalSizeAfter = 0;
|
||||
let currentAfterNode = activeSplitterElement.nextSibling;
|
||||
while (currentAfterNode) {
|
||||
if (isSplitterElement(currentAfterNode)) {
|
||||
splittersTotalSizeAfter += splitterSize(currentAfterNode);
|
||||
}
|
||||
currentAfterNode = currentAfterNode.nextSibling;
|
||||
}
|
||||
const totalSplitterBefore = splittersTotalSizeBefore + activeSplitterDrag;
|
||||
const totalSplitter = splittersTotalSizeBefore + activeSplitterSize + splittersTotalSizeAfter;
|
||||
// An explanation to the mathematical computation:
|
||||
//
|
||||
// Let's start with the case of only two panes. If we mark the first pane size in prec
|
||||
// (thinking about it as a number between 0 to 1) as `x`, we'll get that the size of the left pane in pixels will be:
|
||||
// `x*containerSizeWithoutBorder - x*totalSplitter = x*(containerSizeWithoutBorder - totalSplitter)`
|
||||
// Since we want that the total size in pixels before the user mouse pointer will be `tdrag`, and we need to add the
|
||||
// size of the splitter itself that is before the mouse pointer, we get the equation:
|
||||
// `x*(containerSizeWithoutBorder - totalSplitter) + activeSplitterDrag = tdrag`
|
||||
//
|
||||
// Now in the general case when we have many panes before the splitter, mark their precentages
|
||||
// (again, thinking about it as a number between 0 to 1) by x1,x2,...,xn we'll get the equation:
|
||||
// `(x1 + ... + xn)*(containerSizeWithoutBorder - totalSplitter) + totalSplitterBefore = tdrag`
|
||||
// And solving it yeild the answer:
|
||||
// `x1 + ... + xn = (tdrag - totalSplitterBefore) / (containerSizeWithoutBorder - totalSplitter)`
|
||||
return (((tdrag - totalSplitterBefore) / (containerSizeWithoutBorder - totalSplitter)) * FULL_SIZE);
|
||||
}
|
||||
/**
|
||||
* Called when slitters are moving to adjust pane sizes
|
||||
*/
|
||||
function calculatePanesSize(tdrag, containerSizeWithoutBorder) {
|
||||
let paneBeforeIndex = activeSplitter - 1;
|
||||
let paneBefore = panes[paneBeforeIndex];
|
||||
let paneAfterIndex = activeSplitter;
|
||||
let paneAfter = panes[paneAfterIndex];
|
||||
let sums = {
|
||||
prevPanesSize: sumPrevPanesSize(paneBeforeIndex),
|
||||
nextPanesSize: sumNextPanesSize(paneAfterIndex),
|
||||
prevReachedMinPanes: 0,
|
||||
nextReachedMinPanes: 0
|
||||
};
|
||||
// If not pushing other panes, panes to resize are right before and right after splitter.
|
||||
const minDrag = 0 + (pushOtherPanes ? 0 : sums.prevPanesSize);
|
||||
const maxDrag = 100 - (pushOtherPanes ? 0 : sums.nextPanesSize);
|
||||
// Calculate drag percentage
|
||||
const mouseDragPercentage = Math.max(Math.min(getCurrentDragPercentage(tdrag, containerSizeWithoutBorder), maxDrag), minDrag);
|
||||
// Handle snap
|
||||
const paneBeforeSnap = sums.prevPanesSize + paneBefore.min() + paneBefore.snap();
|
||||
const paneAfterSnap = 100 - (sums.nextPanesSize + paneAfter.min() + paneAfter.snap());
|
||||
let dragPercentage = mouseDragPercentage;
|
||||
let snapped = false;
|
||||
if (mouseDragPercentage <= paneBeforeSnap) {
|
||||
if (mouseDragPercentage > sums.prevPanesSize + paneBefore.min()) {
|
||||
dragPercentage = Math.max(paneBefore.min() + sums.prevPanesSize, 100 - (paneAfter.max() + sums.nextPanesSize));
|
||||
snapped = true;
|
||||
}
|
||||
}
|
||||
else if (mouseDragPercentage >= paneAfterSnap) {
|
||||
if (mouseDragPercentage < 100 - sums.nextPanesSize - paneAfter.min()) {
|
||||
dragPercentage = Math.min(100 - (paneAfter.min() + sums.nextPanesSize), paneBefore.max() + sums.prevPanesSize);
|
||||
snapped = true;
|
||||
}
|
||||
}
|
||||
const paneBeforeMaxReached = paneBefore.max() < 100 && dragPercentage >= paneBefore.max() + sums.prevPanesSize;
|
||||
const paneAfterMaxReached = paneAfter.max() < 100 && dragPercentage <= 100 - (paneAfter.max() + sums.nextPanesSize);
|
||||
// Prevent dragging beyond pane max.
|
||||
if (paneBeforeMaxReached || paneAfterMaxReached) {
|
||||
if (paneBeforeMaxReached) {
|
||||
paneBefore.setSz(paneBefore.max());
|
||||
paneAfter.setSz(Math.max(100 - paneBefore.max() - sums.prevPanesSize - sums.nextPanesSize, 0));
|
||||
}
|
||||
else {
|
||||
paneBefore.setSz(Math.max(100 - paneAfter.max() - sums.prevPanesSize - sums.nextPanesSize, 0));
|
||||
paneAfter.setSz(paneAfter.max());
|
||||
}
|
||||
}
|
||||
else {
|
||||
// When pushOtherPanes = true, find the closest expanded pane on each side of the splitter.
|
||||
// TODO: Bug: This should work also when removing `!snapped` condition, but it's not!
|
||||
// To reproduce, reload the example page and see the example "Min & max with snap".
|
||||
// It gets wrongly pushed when try to snap on the initial dragging of the first splitter to the right.
|
||||
if (pushOtherPanes && !snapped) {
|
||||
const vars = doPushOtherPanes(sums, dragPercentage);
|
||||
if (!vars) {
|
||||
// setAllPaneDimensions();
|
||||
return; // Prevent other calculation.
|
||||
}
|
||||
({ sums, paneBeforeIndex, paneAfterIndex } = vars);
|
||||
paneBefore = panes[paneBeforeIndex];
|
||||
paneAfter = panes[paneAfterIndex];
|
||||
}
|
||||
if (typeof paneBeforeIndex === 'number') {
|
||||
paneBefore.setSz(Math.min(Math.max(dragPercentage - sums.prevPanesSize - sums.prevReachedMinPanes, paneBefore.min()), paneBefore.max()));
|
||||
}
|
||||
if (typeof paneAfterIndex === 'number') {
|
||||
paneAfter.setSz(Math.min(Math.max(100 - dragPercentage - sums.nextPanesSize - sums.nextReachedMinPanes, paneAfter.min()), paneAfter.max()));
|
||||
}
|
||||
}
|
||||
}
|
||||
function doPushOtherPanes(sums, dragPercentage) {
|
||||
const splitterIndex = activeSplitter - 1;
|
||||
let paneBeforeIndex = splitterIndex;
|
||||
let paneAfterIndex = splitterIndex + 1;
|
||||
// Pushing Down.
|
||||
// Going smaller than the current pane min size: take the previous expanded pane.
|
||||
if (dragPercentage < sums.prevPanesSize + panes[paneBeforeIndex].min()) {
|
||||
paneBeforeIndex = findPrevExpandedPane(splitterIndex)?.index;
|
||||
sums.prevReachedMinPanes = 0;
|
||||
if (paneBeforeIndex === undefined) {
|
||||
// If nothing else to push down, cancel dragging.
|
||||
sums.prevPanesSize = 0;
|
||||
panes[0].setSz(panes[0].min());
|
||||
forEachPartial(panes, 1, splitterIndex + 1, (pane) => {
|
||||
pane.setSz(pane.min());
|
||||
sums.prevReachedMinPanes += pane.min();
|
||||
});
|
||||
panes[paneAfterIndex].setSz(100 - sums.prevReachedMinPanes - panes[0].min() - sums.prevPanesSize - sums.nextPanesSize);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
// If pushing a n-2 or less pane, from splitter, then make sure all in between is at min size.
|
||||
if (paneBeforeIndex < splitterIndex) {
|
||||
forEachPartial(panes, paneBeforeIndex + 1, splitterIndex + 1, (pane) => {
|
||||
pane.setSz(pane.min());
|
||||
sums.prevReachedMinPanes += pane.min();
|
||||
});
|
||||
}
|
||||
sums.prevPanesSize = sumPrevPanesSize(paneBeforeIndex);
|
||||
}
|
||||
}
|
||||
// Pushing Up.
|
||||
// Pushing up beyond min size is reached: take the next expanded pane.
|
||||
if (dragPercentage > 100 - sums.nextPanesSize - panes[paneAfterIndex].min()) {
|
||||
paneAfterIndex = findNextExpandedPane(splitterIndex)?.index;
|
||||
if (paneBeforeIndex === undefined)
|
||||
console.log('Yep undefined paneAfterIndex');
|
||||
sums.nextReachedMinPanes = 0;
|
||||
if (paneAfterIndex === undefined) {
|
||||
// If nothing else to push up, cancel dragging.
|
||||
sums.nextPanesSize = 0;
|
||||
const panesCount = panes.length;
|
||||
panes[panesCount - 1].setSz(panes[panesCount - 1].min());
|
||||
forEachPartial(panes, splitterIndex + 1, panesCount - 1, pane => {
|
||||
pane.setSz(pane.min());
|
||||
sums.nextReachedMinPanes += pane.min();
|
||||
});
|
||||
panes[paneBeforeIndex].setSz(100 -
|
||||
sums.prevPanesSize -
|
||||
sums.nextReachedMinPanes -
|
||||
panes[panesCount - 1].min() -
|
||||
sums.nextPanesSize);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
// If pushing a n+2 or more pane, from splitter, then make sure all in between is at min size.
|
||||
if (paneAfterIndex > splitterIndex + 1) {
|
||||
forEachPartial(panes, splitterIndex + 1, paneAfterIndex, (pane) => {
|
||||
pane.setSz(pane.min());
|
||||
sums.nextReachedMinPanes += pane.min();
|
||||
});
|
||||
}
|
||||
sums.nextPanesSize = sumNextPanesSize(paneAfterIndex);
|
||||
}
|
||||
}
|
||||
return { sums, paneBeforeIndex, paneAfterIndex };
|
||||
}
|
||||
const getSizeOfPane = (pane) => pane.sz();
|
||||
const sumPrevPanesSize = (splitterIndex) => sumPartial(panes, 0, splitterIndex, getSizeOfPane);
|
||||
const sumNextPanesSize = (splitterIndex) => sumPartial(panes, splitterIndex + 1, panes.length, getSizeOfPane);
|
||||
// Return the previous pane from siblings which has a size (width for vert or height for horz) of more than 0.
|
||||
const findPrevExpandedPane = (splitterIndex) => [...panes].reverse().find(p => p.index < splitterIndex && p.sz() > p.min());
|
||||
// Return the next pane from siblings which has a size (width for vert or height for horz) of more than 0.
|
||||
const findNextExpandedPane = (splitterIndex) => panes.find(p => p.index > splitterIndex + 1 && p.sz() > p.min());
|
||||
async function tickAndResetPaneSizes() {
|
||||
isAwaitingPaneReset = true;
|
||||
await tick();
|
||||
if (isAwaitingPaneReset) {
|
||||
resetPaneSizes();
|
||||
isAwaitingPaneReset = false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param addedPane
|
||||
* @param removedPane
|
||||
*/
|
||||
function resetPaneSizes() {
|
||||
equalize();
|
||||
if (isReady)
|
||||
dispatch('resized', prepareSizeEvent());
|
||||
}
|
||||
function equalize() {
|
||||
// Escape the function on the edge case that there is not even a single pane
|
||||
if (panes.length === 0) {
|
||||
return;
|
||||
}
|
||||
// otherwise
|
||||
const panesCount = panes.length;
|
||||
let leftToAllocate = 100;
|
||||
let definedSizesCount = 0;
|
||||
let undefinedSizesNotReadyCount = 0;
|
||||
let undefinedSizesSum = 0;
|
||||
const ungrowable = [];
|
||||
const unshrinkable = [];
|
||||
for (let i = 0; i < panesCount; i++) {
|
||||
const pane = panes[i];
|
||||
const sz = pane.sz();
|
||||
if (pane.givenSize === null) {
|
||||
if (pane.isReady) {
|
||||
undefinedSizesSum += sz;
|
||||
if (sz >= pane.max())
|
||||
ungrowable.push(pane);
|
||||
if (sz <= pane.min())
|
||||
unshrinkable.push(pane);
|
||||
}
|
||||
else {
|
||||
undefinedSizesNotReadyCount += 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if the size is defined, we don't modify its size at all
|
||||
leftToAllocate -= sz;
|
||||
definedSizesCount++;
|
||||
ungrowable.push(pane);
|
||||
unshrinkable.push(pane);
|
||||
}
|
||||
}
|
||||
const undefinedSizesCount = panesCount - definedSizesCount;
|
||||
const undefinedSizesReadyCount = undefinedSizesCount - undefinedSizesNotReadyCount;
|
||||
// the proportion of the newly added panes
|
||||
let undefinedSizesNotReadySz;
|
||||
let undefinedScaleFactor;
|
||||
if (undefinedSizesReadyCount > 0) {
|
||||
// if has undefined sizes panes that are ready:
|
||||
undefinedSizesNotReadySz = undefinedSizesSum / undefinedSizesReadyCount;
|
||||
if (undefinedSizesNotReadySz > SIZE_THRESHOLD && leftToAllocate > SIZE_THRESHOLD) {
|
||||
undefinedSizesSum += undefinedSizesNotReadyCount * undefinedSizesNotReadySz;
|
||||
undefinedScaleFactor = leftToAllocate / undefinedSizesSum;
|
||||
}
|
||||
else {
|
||||
// when the size of the ready undefined panes shares are negligible, need to set the not ready
|
||||
// undefined one to size 0, for being "proportional" to negligible sizes
|
||||
undefinedSizesNotReadySz = 0;
|
||||
undefinedScaleFactor = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// otherwise, divide the space of the undefined sizes panes equally:
|
||||
undefinedSizesNotReadySz = leftToAllocate / undefinedSizesCount;
|
||||
undefinedScaleFactor = 1;
|
||||
}
|
||||
// whenever `leftToAllocate` or `undefinedSizesSum` aren't negligible, need to adjact the sizes
|
||||
if (leftToAllocate + undefinedSizesSum > SIZE_THRESHOLD) {
|
||||
leftToAllocate = 100; // reset the space calculation
|
||||
for (let i = 0; i < panesCount; i++) {
|
||||
const pane = panes[i];
|
||||
if (!(typeof pane.givenSize === 'number')) {
|
||||
// add the proportion of the newly added pane if has undefined size
|
||||
const currentSz = pane.isReady ? pane.sz() : undefinedSizesNotReadySz;
|
||||
const sz = Math.max(Math.min(currentSz * undefinedScaleFactor, pane.max()), pane.min());
|
||||
pane.setSz(sz);
|
||||
}
|
||||
leftToAllocate -= pane.sz();
|
||||
}
|
||||
// since we multiply by scaling, there might be left space that is needed to be saturated
|
||||
if (Math.abs(leftToAllocate) > SIZE_THRESHOLD) {
|
||||
leftToAllocate = readjustSizes(leftToAllocate, ungrowable, unshrinkable);
|
||||
}
|
||||
}
|
||||
if (!isFinite(leftToAllocate)) {
|
||||
console.warn('Splitpanes: Internal error, sizes might be NaN as a result.');
|
||||
}
|
||||
else if (Math.abs(leftToAllocate) > SIZE_THRESHOLD) {
|
||||
console.warn('Splitpanes: Could not resize panes correctly due to their constraints.');
|
||||
}
|
||||
}
|
||||
// Second loop to adjust sizes now that we know more about the panes constraints.
|
||||
function readjustSizes(leftToAllocate, ungrowable, unshrinkable) {
|
||||
const panesCount = panes.length;
|
||||
const panesSizableCount = panesCount - (leftToAllocate > 0 ? ungrowable.length : unshrinkable.length);
|
||||
if (panesSizableCount <= 0) {
|
||||
return leftToAllocate;
|
||||
}
|
||||
const equalSpaceToAllocate = leftToAllocate / panesSizableCount;
|
||||
if (panes.length === 1) {
|
||||
panes[0].setSz(100);
|
||||
leftToAllocate = 0;
|
||||
}
|
||||
else
|
||||
for (let i = 0; i < panes.length; i++) {
|
||||
const pane = panes[i];
|
||||
const sz = pane.sz();
|
||||
if (leftToAllocate > 0 && !ungrowable.includes(pane)) {
|
||||
// Need to diff the size before and after to get the exact allocated space.
|
||||
const newPaneSize = Math.max(Math.min(sz + equalSpaceToAllocate, pane.max()), pane.min());
|
||||
const allocated = newPaneSize - sz;
|
||||
leftToAllocate -= allocated;
|
||||
pane.setSz(newPaneSize);
|
||||
}
|
||||
else if (!unshrinkable.includes(pane)) {
|
||||
// Need to diff the size before and after to get the exact allocated space.
|
||||
const newPaneSize = Math.max(Math.min(sz + equalSpaceToAllocate, pane.max()), pane.min());
|
||||
const allocated = newPaneSize - sz;
|
||||
leftToAllocate -= allocated;
|
||||
pane.setSz(newPaneSize);
|
||||
}
|
||||
}
|
||||
return leftToAllocate;
|
||||
}
|
||||
/**
|
||||
* Checks that <Splitpanes> is composed of <Pane>, and verify that the panes are still in the right order,
|
||||
* and if not update the internal order.
|
||||
*
|
||||
* Optimized with early exit guards to avoid unnecessary DOM iterations.
|
||||
*/
|
||||
function verifyAndUpdatePanesOrder() {
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
const { children } = container;
|
||||
// Quick check: if length hasn't changed and first/last elements are same, skip
|
||||
if (children.length === lastChildrenSnapshot.length &&
|
||||
children.length > 0 &&
|
||||
children[0] === lastChildrenSnapshot[0] &&
|
||||
children[children.length - 1] === lastChildrenSnapshot[children.length - 1]) {
|
||||
return; // No changes detected
|
||||
}
|
||||
let currentPaneIndex = 0;
|
||||
let needReorder = false;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children.item(i);
|
||||
const isPane = child.classList.contains('splitpanes__pane');
|
||||
const isSplitter = child.classList.contains('splitpanes__splitter');
|
||||
// Node is not a Pane or a splitter: remove it.
|
||||
if (!isPane && !isSplitter) {
|
||||
child.parentNode?.removeChild(child); // el.remove() doesn't work on IE11.
|
||||
console.warn('Splitpanes: Only <Pane> elements are allowed at the root of <Splitpanes>. One of your DOM nodes was removed.');
|
||||
lastChildrenSnapshot = Array.from(children);
|
||||
return;
|
||||
}
|
||||
else if (isPane) {
|
||||
if (!needReorder && panes[currentPaneIndex]?.element !== child) {
|
||||
needReorder = true;
|
||||
}
|
||||
currentPaneIndex++;
|
||||
}
|
||||
}
|
||||
if (needReorder) {
|
||||
const newPanes = [];
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children.item(i);
|
||||
const isPane = child?.classList.contains('splitpanes__pane');
|
||||
if (isPane) {
|
||||
const pane = panes.find(pane => pane.element === child);
|
||||
if (pane) {
|
||||
pane.index = newPanes.length;
|
||||
newPanes.push(pane);
|
||||
}
|
||||
else {
|
||||
console.warn("Splitpanes: Internal error - found a <Pane> elements which isn't tracked.");
|
||||
}
|
||||
}
|
||||
}
|
||||
panes = newPanes;
|
||||
$veryFirstPaneKey = panes.length > 0 ? panes[0].key : undefined;
|
||||
}
|
||||
// Update snapshot after verification
|
||||
lastChildrenSnapshot = Array.from(children);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
{id}
|
||||
bind:this={container}
|
||||
class={`splitpanes ${theme || ''} ${clazz || ''}`}
|
||||
class:splitpanes--horizontal={horizontal}
|
||||
class:splitpanes--vertical={!horizontal}
|
||||
class:splitpanes--dragging={isMouseDown || isDragging}
|
||||
class:splitpanes--freeze={!isAfterInitialTimeoutZero}
|
||||
{style}>
|
||||
{#if !browser}
|
||||
<GatheringRound><slot /></GatheringRound>
|
||||
{/if}
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style global>:global(.splitpanes.default-theme) :global(.splitpanes__pane) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
:global(.splitpanes.default-theme) :global(.splitpanes__splitter) {
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
:global(.splitpanes.default-theme) :global(.splitpanes__splitter:before), :global(.splitpanes.default-theme) :global(.splitpanes__splitter:after) {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
:global(.splitpanes.default-theme) :global(.splitpanes__splitter:hover:before), :global(.splitpanes.default-theme) :global(.splitpanes__splitter:hover:after) {
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
:global(.splitpanes.default-theme) :global(.splitpanes__splitter:first-child) {
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
:global(.default-theme.splitpanes) :global(.splitpanes) :global(.splitpanes__splitter) {
|
||||
z-index: 1;
|
||||
}
|
||||
:global(.default-theme.splitpanes--vertical) > :global(.splitpanes__splitter),
|
||||
:global(.default-theme) :global(.splitpanes--vertical) > :global(.splitpanes__splitter) {
|
||||
width: 7px;
|
||||
border-left: 1px solid #eee;
|
||||
cursor: col-resize;
|
||||
}
|
||||
:global(.default-theme.splitpanes--vertical) > :global(.splitpanes__splitter:before), :global(.default-theme.splitpanes--vertical) > :global(.splitpanes__splitter:after), :global(.default-theme) :global(.splitpanes--vertical) > :global(.splitpanes__splitter:before), :global(.default-theme) :global(.splitpanes--vertical) > :global(.splitpanes__splitter:after) {
|
||||
transform: translateY(-50%);
|
||||
width: 1px;
|
||||
height: 30px;
|
||||
}
|
||||
:global(.default-theme.splitpanes--vertical) > :global(.splitpanes__splitter:before),
|
||||
:global(.default-theme) :global(.splitpanes--vertical) > :global(.splitpanes__splitter:before) {
|
||||
margin-left: -2px;
|
||||
}
|
||||
:global(.default-theme.splitpanes--vertical) > :global(.splitpanes__splitter:after),
|
||||
:global(.default-theme) :global(.splitpanes--vertical) > :global(.splitpanes__splitter:after) {
|
||||
margin-left: 1px;
|
||||
}
|
||||
:global(.default-theme.splitpanes--horizontal) > :global(.splitpanes__splitter),
|
||||
:global(.default-theme) :global(.splitpanes--horizontal) > :global(.splitpanes__splitter) {
|
||||
height: 7px;
|
||||
border-top: 1px solid #eee;
|
||||
cursor: row-resize;
|
||||
}
|
||||
:global(.default-theme.splitpanes--horizontal) > :global(.splitpanes__splitter:before), :global(.default-theme.splitpanes--horizontal) > :global(.splitpanes__splitter:after), :global(.default-theme) :global(.splitpanes--horizontal) > :global(.splitpanes__splitter:before), :global(.default-theme) :global(.splitpanes--horizontal) > :global(.splitpanes__splitter:after) {
|
||||
transform: translateX(-50%);
|
||||
width: 30px;
|
||||
height: 1px;
|
||||
}
|
||||
:global(.default-theme.splitpanes--horizontal) > :global(.splitpanes__splitter:before),
|
||||
:global(.default-theme) :global(.splitpanes--horizontal) > :global(.splitpanes__splitter:before) {
|
||||
margin-top: -2px;
|
||||
}
|
||||
:global(.default-theme.splitpanes--horizontal) > :global(.splitpanes__splitter:after),
|
||||
:global(.default-theme) :global(.splitpanes--horizontal) > :global(.splitpanes__splitter:after) {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
:global(div.splitpanes--horizontal.splitpanes--dragging) {
|
||||
cursor: row-resize;
|
||||
}
|
||||
|
||||
:global(div.splitpanes--vertical.splitpanes--dragging) {
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
:global(.splitpanes) {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
:global(.splitpanes--vertical) {
|
||||
flex-direction: row;
|
||||
}
|
||||
:global(.splitpanes--horizontal) {
|
||||
flex-direction: column;
|
||||
}
|
||||
:global(.splitpanes--dragging) :global(*) {
|
||||
user-select: none;
|
||||
}
|
||||
:global(.splitpanes__pane) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
:global(.splitpanes--vertical) :global(.splitpanes__pane) {
|
||||
transition: width 0.2s ease-out;
|
||||
}
|
||||
:global(.splitpanes--horizontal) :global(.splitpanes__pane) {
|
||||
transition: height 0.2s ease-out;
|
||||
}
|
||||
:global(.splitpanes__pane) {
|
||||
/** Add also a direct child selector, for dealing with specifity of nested splitpanes transition.
|
||||
This issue was happening in the examples on nested splitpanes, vertical inside horizontal.
|
||||
I think it's better to keep also the previous CSS selector for (potential) old browser compatibility.
|
||||
*/
|
||||
}
|
||||
:global(.splitpanes--vertical) > :global(.splitpanes__pane) {
|
||||
transition: width 0.2s ease-out;
|
||||
}
|
||||
:global(.splitpanes--horizontal) > :global(.splitpanes__pane) {
|
||||
transition: height 0.2s ease-out;
|
||||
}
|
||||
:global(.splitpanes--dragging) :global(.splitpanes__pane) {
|
||||
transition: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
:global(.splitpanes--freeze) :global(.splitpanes__pane) {
|
||||
transition: none;
|
||||
}
|
||||
:global(.splitpanes__splitter) {
|
||||
touch-action: none;
|
||||
}
|
||||
:global(.splitpanes--vertical) > :global(.splitpanes__splitter) {
|
||||
min-width: 1px;
|
||||
}
|
||||
:global(.splitpanes--horizontal) > :global(.splitpanes__splitter) {
|
||||
min-height: 1px;
|
||||
}</style>
|
||||
100
web/node_modules/svelte-splitpanes/dist/Splitpanes.svelte.d.ts
generated
vendored
Normal file
100
web/node_modules/svelte-splitpanes/dist/Splitpanes.svelte.d.ts
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
export declare const KEY: {};
|
||||
import type { IPane, IPaneSizingEvent } from './index.js';
|
||||
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
||||
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
||||
$$bindings?: Bindings;
|
||||
} & Exports;
|
||||
(internal: unknown, props: Props & {
|
||||
$$events?: Events;
|
||||
$$slots?: Slots;
|
||||
}): Exports & {
|
||||
$set?: any;
|
||||
$on?: any;
|
||||
};
|
||||
z_$$bindings?: Bindings;
|
||||
}
|
||||
type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
||||
default: any;
|
||||
} ? Props extends Record<string, never> ? any : {
|
||||
children?: any;
|
||||
} : {});
|
||||
declare const Splitpanes: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
|
||||
id?: string;
|
||||
horizontal?: boolean;
|
||||
pushOtherPanes?: boolean;
|
||||
dblClickSplitter?: boolean;
|
||||
rtl?: boolean | "auto";
|
||||
firstSplitter?: boolean;
|
||||
style?: string | null;
|
||||
theme?: string;
|
||||
class?: string;
|
||||
}, {
|
||||
default: {};
|
||||
}>, {
|
||||
/**
|
||||
* When clicking (or touching) a pane.
|
||||
*
|
||||
* Returns the clicked pane object with its dimensions.
|
||||
*/
|
||||
'pane-click': CustomEvent<IPane>;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
'splitter-click': CustomEvent<IPane>;
|
||||
/**
|
||||
* Fires when the pane is maximized (ie. typically by double clicking the splitter).
|
||||
*
|
||||
* Returns the maximized pane object with its.
|
||||
*/
|
||||
'pane-maximize': CustomEvent<IPane>;
|
||||
/**
|
||||
* Fires when splitpanes is ready.
|
||||
*/
|
||||
ready: CustomEvent<void>;
|
||||
/**
|
||||
* Fires while resizing (on mousemove/touchmove).
|
||||
*
|
||||
* Returns the clicked pane object with its dimensions.
|
||||
*/
|
||||
resize: CustomEvent<IPaneSizingEvent[]>;
|
||||
/**
|
||||
* Fires once when the resizing stops after user drag (on mouseup/touchend) or when adding or removing a pane.
|
||||
*
|
||||
* Returns the clicked pane object with its dimensions.
|
||||
*/
|
||||
resized: CustomEvent<IPaneSizingEvent[]>;
|
||||
/**
|
||||
* Fires when a pane is added.
|
||||
*/
|
||||
'pane-add': CustomEvent<{
|
||||
/**
|
||||
* The index of the added pane.
|
||||
*/
|
||||
index: number;
|
||||
/**
|
||||
* The new array of panes after resize.
|
||||
*/
|
||||
panes: IPaneSizingEvent[];
|
||||
}>;
|
||||
/**
|
||||
* Fires when a pane is removed.
|
||||
*/
|
||||
'pane-remove': CustomEvent<{
|
||||
/**
|
||||
* The removed pane.
|
||||
*/
|
||||
removed: IPane;
|
||||
/**
|
||||
* An array of all the remaining pane objects with their dimensions (after resize).
|
||||
*/
|
||||
panes: IPaneSizingEvent[];
|
||||
}>;
|
||||
}, {
|
||||
default: {};
|
||||
}, {}, string>;
|
||||
type Splitpanes = InstanceType<typeof Splitpanes>;
|
||||
export default Splitpanes;
|
||||
60
web/node_modules/svelte-splitpanes/dist/index.d.ts
generated
vendored
Normal file
60
web/node_modules/svelte-splitpanes/dist/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { Readable } from 'svelte/store';
|
||||
export { default as Splitpanes } from './Splitpanes.svelte';
|
||||
export { default as Pane } from './Pane.svelte';
|
||||
export type PaneInitFunction = (_key: any) => {
|
||||
undefinedPaneInitSize: number;
|
||||
};
|
||||
export interface ClientCallbacks {
|
||||
onSplitterDown: (_event: TouchEvent | MouseEvent) => void;
|
||||
onSplitterClick: (_event: MouseEvent) => void;
|
||||
onSplitterDblClick: (_event: MouseEvent) => void;
|
||||
onPaneClick: (_event: MouseEvent) => void;
|
||||
/** Report the manual given size was changed. */
|
||||
reportGivenSizeChange: (_newGivenSize: number) => void;
|
||||
}
|
||||
export interface SplitContext {
|
||||
/** Tells the key of the very first pane, or undefined if not recieved yet. */
|
||||
veryFirstPaneKey: Readable<any>;
|
||||
isHorizontal: Readable<boolean>;
|
||||
showFirstSplitter: Readable<boolean>;
|
||||
ssrRegisterPaneSize?: (size: number | null) => void;
|
||||
onPaneInit: PaneInitFunction;
|
||||
clientOnly?: {
|
||||
onPaneAdd: (pane: IPane) => ClientCallbacks;
|
||||
onPaneRemove: (key: any) => Promise<void>;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Pane sizing details on an event.
|
||||
*/
|
||||
export interface IPaneSizingEvent {
|
||||
/**
|
||||
* Minimum size in %.
|
||||
*/
|
||||
min: number;
|
||||
/**
|
||||
* Maximum size in %.
|
||||
*/
|
||||
max: number;
|
||||
/**
|
||||
* Pane size in %.
|
||||
*/
|
||||
size: number;
|
||||
/**
|
||||
* Snap size in %.
|
||||
*/
|
||||
snap: number;
|
||||
}
|
||||
export interface IPane {
|
||||
key: any;
|
||||
element: HTMLElement;
|
||||
index: number;
|
||||
min: () => number;
|
||||
max: () => number;
|
||||
snap: () => number;
|
||||
sz: () => number;
|
||||
setSz: (number: number) => void;
|
||||
setSplitterActive: (isActive: boolean) => void;
|
||||
givenSize: number | null;
|
||||
isReady: boolean;
|
||||
}
|
||||
2
web/node_modules/svelte-splitpanes/dist/index.js
generated
vendored
Normal file
2
web/node_modules/svelte-splitpanes/dist/index.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as Splitpanes } from './Splitpanes.svelte';
|
||||
export { default as Pane } from './Pane.svelte';
|
||||
8
web/node_modules/svelte-splitpanes/dist/internal/GatheringRound.svelte
generated
vendored
Normal file
8
web/node_modules/svelte-splitpanes/dist/internal/GatheringRound.svelte
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<script lang="ts" context="module">export const gatheringKey = {};
|
||||
</script>
|
||||
|
||||
<script lang="ts">import { setContext } from 'svelte';
|
||||
setContext(gatheringKey, true);
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
21
web/node_modules/svelte-splitpanes/dist/internal/GatheringRound.svelte.d.ts
generated
vendored
Normal file
21
web/node_modules/svelte-splitpanes/dist/internal/GatheringRound.svelte.d.ts
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
export declare const gatheringKey: {};
|
||||
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
||||
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
||||
$$bindings?: Bindings;
|
||||
} & Exports;
|
||||
(internal: unknown, props: {
|
||||
$$events?: Events;
|
||||
$$slots?: Slots;
|
||||
}): Exports & {
|
||||
$set?: any;
|
||||
$on?: any;
|
||||
};
|
||||
z_$$bindings?: Bindings;
|
||||
}
|
||||
declare const GatheringRound: $$__sveltets_2_IsomorphicComponent<any, {
|
||||
[evt: string]: CustomEvent<any>;
|
||||
}, {
|
||||
default: {};
|
||||
}, {}, string>;
|
||||
type GatheringRound = InstanceType<typeof GatheringRound>;
|
||||
export default GatheringRound;
|
||||
9
web/node_modules/svelte-splitpanes/dist/internal/env.d.ts
generated
vendored
Normal file
9
web/node_modules/svelte-splitpanes/dist/internal/env.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Browser detection utility.
|
||||
*
|
||||
* Uses SvelteKit's native browser detection which is more reliable
|
||||
* and doesn't require external dependencies.
|
||||
*
|
||||
* @see https://kit.svelte.dev/docs/modules#$app-environment
|
||||
*/
|
||||
export { browser } from '$app/environment';
|
||||
9
web/node_modules/svelte-splitpanes/dist/internal/env.js
generated
vendored
Normal file
9
web/node_modules/svelte-splitpanes/dist/internal/env.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Browser detection utility.
|
||||
*
|
||||
* Uses SvelteKit's native browser detection which is more reliable
|
||||
* and doesn't require external dependencies.
|
||||
*
|
||||
* @see https://kit.svelte.dev/docs/modules#$app-environment
|
||||
*/
|
||||
export { browser } from '$app/environment';
|
||||
2
web/node_modules/svelte-splitpanes/dist/internal/utils/array.d.ts
generated
vendored
Normal file
2
web/node_modules/svelte-splitpanes/dist/internal/utils/array.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare function sumPartial<T>(arr: ReadonlyArray<T>, start: number, end: number, valueFunction: (element: T, index: number) => number): number;
|
||||
export declare function forEachPartial<T>(arr: ReadonlyArray<T>, start: number, end: number, callback: (element: T, index: number) => void): void;
|
||||
12
web/node_modules/svelte-splitpanes/dist/internal/utils/array.js
generated
vendored
Normal file
12
web/node_modules/svelte-splitpanes/dist/internal/utils/array.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
export function sumPartial(arr, start, end, valueFunction) {
|
||||
let sum = 0;
|
||||
for (let i = start; i < end; i++) {
|
||||
sum += valueFunction(arr[i], i);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
export function forEachPartial(arr, start, end, callback) {
|
||||
for (let i = start; i < end; i++) {
|
||||
callback(arr[i], i);
|
||||
}
|
||||
}
|
||||
6
web/node_modules/svelte-splitpanes/dist/internal/utils/functions.d.ts
generated
vendored
Normal file
6
web/node_modules/svelte-splitpanes/dist/internal/utils/functions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* This is an source of callbacks that are safe to be called even if the object of `callbackObjectGetter()` is nullish on that moment.
|
||||
*
|
||||
* In the case of the object is nullish, invoking the callbacks will do nothing.
|
||||
*/
|
||||
export declare const carefullCallbackSource: <CallbacksObject extends object>(callbackObjectGetter: () => CallbacksObject | undefined) => (<Callback extends keyof CallbacksObject>(callbackName: Callback) => CallbacksObject[Callback]);
|
||||
19
web/node_modules/svelte-splitpanes/dist/internal/utils/functions.js
generated
vendored
Normal file
19
web/node_modules/svelte-splitpanes/dist/internal/utils/functions.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Generate a callback that is safe to be called even if `callbackObjectGetter()` is nullish on that moment.
|
||||
*
|
||||
* In the case of the object is nullish, invoking the callback will do nothing.
|
||||
*/
|
||||
const carefullCallbackGenerator = (callbackObjectGetter, callbackName) => (value) => {
|
||||
const callbackObject = callbackObjectGetter();
|
||||
if (callbackObject !== null) {
|
||||
callbackObject[callbackName](value);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* This is an source of callbacks that are safe to be called even if the object of `callbackObjectGetter()` is nullish on that moment.
|
||||
*
|
||||
* In the case of the object is nullish, invoking the callbacks will do nothing.
|
||||
*/
|
||||
export const carefullCallbackSource = (callbackObjectGetter) =>
|
||||
//@ts-expect-error unassignable
|
||||
carefullCallbackGenerator.bind(null, callbackObjectGetter);
|
||||
32
web/node_modules/svelte-splitpanes/dist/internal/utils/position.d.ts
generated
vendored
Normal file
32
web/node_modules/svelte-splitpanes/dist/internal/utils/position.d.ts
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import { type Sides, type SidesStart } from './sizing.js';
|
||||
export type Position = SidesStart;
|
||||
/** This is a minimal version of DOMRect for our use.
|
||||
* We don't use DOMRect constructor because the lack of legacy browsers support (e.g. IE11).
|
||||
*/
|
||||
export interface Rect extends Position {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
type LegacyClientRect = Pick<Readonly<DOMRect>, 'height' | 'width' | 'left' | 'right' | 'top' | 'bottom'>;
|
||||
/**
|
||||
* A legacy-typed safer version of `element.getBoundingClientRect()`,
|
||||
* that also invites minification capabilities (muliply calls can be forward to here, and it's pure).
|
||||
* */
|
||||
export declare const getElementRect: (element: HTMLElement) => LegacyClientRect;
|
||||
export declare const getBordersSizeOffsets: {
|
||||
(computedStyle: CSSStyleDeclaration, calcEnds?: true): Sides;
|
||||
(computedStyle: CSSStyleDeclaration, calcEnds: false): SidesStart;
|
||||
};
|
||||
/**
|
||||
* Computes the position and the dimensions of the element without the border.
|
||||
*
|
||||
* While `element.getBoundingClientRect()` gives the correct size with the borders, this method method does include the borders.
|
||||
*
|
||||
* Notice that for calculating the width and the height without the border, we must use this function instead of using
|
||||
* `Element.clientWidth` and `Element.clientHeight`, beacuse they round the sizes of the pixels to be integer.
|
||||
*/
|
||||
export declare function elementRectWithoutBorder(element: HTMLElement, computedStyle?: CSSStyleDeclaration): Rect;
|
||||
/** Get the cursor position relative to some element. */
|
||||
export declare const positionDiff: (to: Position, from: Position) => Position;
|
||||
export declare function getGlobalMousePosition(event: MouseEvent | TouchEvent): Position;
|
||||
export {};
|
||||
83
web/node_modules/svelte-splitpanes/dist/internal/utils/position.js
generated
vendored
Normal file
83
web/node_modules/svelte-splitpanes/dist/internal/utils/position.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
import { pxToNumber } from './sizing.js';
|
||||
import { calcComputedStyle } from './styling.js';
|
||||
/**
|
||||
* A legacy-typed safer version of `element.getBoundingClientRect()`,
|
||||
* that also invites minification capabilities (muliply calls can be forward to here, and it's pure).
|
||||
* */
|
||||
export const getElementRect = (element) =>
|
||||
/*@__PURE__*/ element.getBoundingClientRect();
|
||||
export const getBordersSizeOffsets = (computedStyle, calcEnds = true) => {
|
||||
if (computedStyle.getPropertyValue('box-sizing') === 'border-box') {
|
||||
// In this case, no offset is needed since the box model of this element doesn't include the border.
|
||||
return undefined;
|
||||
}
|
||||
// otherwise
|
||||
const left = pxToNumber(computedStyle.getPropertyValue('border-left-width'));
|
||||
if (left === undefined) {
|
||||
console.error('Splitpanes Error: Fail to parse container `border-left-width`.');
|
||||
return undefined;
|
||||
}
|
||||
// otherwise
|
||||
const top = pxToNumber(computedStyle.getPropertyValue('border-top-width'));
|
||||
if (top === undefined) {
|
||||
console.error('Splitpanes Error: Fail to parse container `border-top-width`.');
|
||||
return undefined;
|
||||
}
|
||||
// otherwise
|
||||
const result = { left, top };
|
||||
if (calcEnds) {
|
||||
const right = pxToNumber(computedStyle.getPropertyValue('border-right-width'));
|
||||
if (right === undefined) {
|
||||
console.error('Splitpanes Error: Fail to parse container `border-right-width`.');
|
||||
return undefined;
|
||||
}
|
||||
// otherwise
|
||||
const bottom = pxToNumber(computedStyle.getPropertyValue('border-bottom-width'));
|
||||
if (bottom === undefined) {
|
||||
console.error('Splitpanes Error: Fail to parse container `border-bottom-width`.');
|
||||
return undefined;
|
||||
}
|
||||
// otherwise
|
||||
const resultExtended = result;
|
||||
resultExtended.right = right;
|
||||
resultExtended.bottom = bottom;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
* Computes the position and the dimensions of the element without the border.
|
||||
*
|
||||
* While `element.getBoundingClientRect()` gives the correct size with the borders, this method method does include the borders.
|
||||
*
|
||||
* Notice that for calculating the width and the height without the border, we must use this function instead of using
|
||||
* `Element.clientWidth` and `Element.clientHeight`, beacuse they round the sizes of the pixels to be integer.
|
||||
*/
|
||||
export function elementRectWithoutBorder(element, computedStyle) {
|
||||
if (!computedStyle) {
|
||||
computedStyle = calcComputedStyle(element);
|
||||
}
|
||||
const rect = getElementRect(element);
|
||||
const borderOffsets = getBordersSizeOffsets(computedStyle, true) || {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0
|
||||
};
|
||||
return {
|
||||
width: rect.width - borderOffsets.left - borderOffsets.right,
|
||||
height: rect.height - borderOffsets.top - borderOffsets.bottom,
|
||||
left: rect.left + borderOffsets.left,
|
||||
top: rect.top + borderOffsets.top
|
||||
};
|
||||
}
|
||||
/** Get the cursor position relative to some element. */
|
||||
export const positionDiff = (to, from) => ({
|
||||
left: to.left - from.left,
|
||||
top: to.top - from.top
|
||||
});
|
||||
export function getGlobalMousePosition(event) {
|
||||
const eventMouse = event;
|
||||
const eventTouch = event;
|
||||
const { clientX, clientY } = 'ontouchstart' in window && eventTouch.touches ? eventTouch.touches[0] : eventMouse;
|
||||
return { left: clientX, top: clientY };
|
||||
}
|
||||
11
web/node_modules/svelte-splitpanes/dist/internal/utils/sizing.d.ts
generated
vendored
Normal file
11
web/node_modules/svelte-splitpanes/dist/internal/utils/sizing.d.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
export interface SidesStart {
|
||||
left: number;
|
||||
top: number;
|
||||
}
|
||||
export interface SidesEnd {
|
||||
right: number;
|
||||
bottom: number;
|
||||
}
|
||||
export type Sides = SidesStart & SidesEnd;
|
||||
export declare function pxToNumber(pxString: string | undefined): number | undefined;
|
||||
export declare const getDimensionName: (horizontal: boolean) => "height" | "width";
|
||||
9
web/node_modules/svelte-splitpanes/dist/internal/utils/sizing.js
generated
vendored
Normal file
9
web/node_modules/svelte-splitpanes/dist/internal/utils/sizing.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
export function pxToNumber(pxString) {
|
||||
if (!pxString?.endsWith('px')) {
|
||||
return undefined;
|
||||
}
|
||||
// otherwise
|
||||
const num = parseFloat(pxString.slice(0, pxString.length - 2));
|
||||
return isNaN(num) ? undefined : num;
|
||||
}
|
||||
export const getDimensionName = (horizontal) => (horizontal ? 'height' : 'width');
|
||||
5
web/node_modules/svelte-splitpanes/dist/internal/utils/styling.d.ts
generated
vendored
Normal file
5
web/node_modules/svelte-splitpanes/dist/internal/utils/styling.d.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* A wrapper of `window.getComputedStyle()`,
|
||||
* that also invites minification capabilities (muliply calls can be forward to here, and it's pure).
|
||||
* */
|
||||
export declare const calcComputedStyle: (element: HTMLElement) => CSSStyleDeclaration;
|
||||
6
web/node_modules/svelte-splitpanes/dist/internal/utils/styling.js
generated
vendored
Normal file
6
web/node_modules/svelte-splitpanes/dist/internal/utils/styling.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* A wrapper of `window.getComputedStyle()`,
|
||||
* that also invites minification capabilities (muliply calls can be forward to here, and it's pure).
|
||||
* */
|
||||
export const calcComputedStyle = (element) =>
|
||||
/*@__PURE__*/ window.getComputedStyle(element);
|
||||
46
web/node_modules/svelte-splitpanes/package.json
generated
vendored
Normal file
46
web/node_modules/svelte-splitpanes/package.json
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "svelte-splitpanes",
|
||||
"version": "8.0.12",
|
||||
"description": "A full featured resizable pane layout splitter, ported from vue-splitpanes and enhanced",
|
||||
"keywords": [
|
||||
"svelte",
|
||||
"layout",
|
||||
"split",
|
||||
"splitter",
|
||||
"pane",
|
||||
"panel",
|
||||
"resizable"
|
||||
],
|
||||
"homepage": "https://orefalo.github.io/svelte-splitpanes/",
|
||||
"bugs": "https://github.com/orefalo/svelte-splitpanes/issues",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/orefalo/svelte-splitpanes"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "Olivier Refalo",
|
||||
"url": "https://github.com/orefalo"
|
||||
},
|
||||
"type": "module",
|
||||
"sideEffects": [
|
||||
"**/*.css",
|
||||
"**/*.scss"
|
||||
],
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"svelte": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"svelte": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"svelte": "^5.43.0"
|
||||
},
|
||||
"packageManager": "pnpm@10.23.0"
|
||||
}
|
||||
Reference in New Issue
Block a user