fix: 修复关闭SSH终端标签页时会话状态未更新的问题

This commit is contained in:
2026-04-18 02:35:38 +08:00
commit 6e2e2f9387
43467 changed files with 5489040 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020-2021 Ryan Carniato
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.
+152
View File
@@ -0,0 +1,152 @@
<p>
<img width="100%" src="https://assets.solidjs.com/banner?project=Transition%20Group&type=core" alt="Solid Transition Group">
</p>
# Solid Transition Group
[![pnpm](https://img.shields.io/badge/maintained%20with-pnpm-cc00ff.svg?style=for-the-badge&logo=pnpm)](https://pnpm.io/)
[![version](https://img.shields.io/npm/v/solid-transition-group?style=for-the-badge)](https://www.npmjs.com/package/solid-transition-group)
[![downloads](https://img.shields.io/npm/dw/solid-transition-group?color=blue&style=for-the-badge)](https://www.npmjs.com/package/solid-transition-group)
Components for applying animations when children elements enter or leave the DOM. Influenced by React Transition Group and Vue Transitions for the SolidJS library.
## Installation
```bash
npm install solid-transition-group
# or
yarn add solid-transition-group
# or
pnpm add solid-transition-group
```
## Transition
`<Transition>` serve as transition effects for single element/component. The `<Transition>` only applies the transition behavior to the wrapped content inside; it doesn't render an extra DOM element, or show up in the inspected component hierarchy.
All props besides `children` are optional.
### Using with CSS
Usage with CSS is straightforward. Just add the `name` prop and the CSS classes will be automatically generated for you. The `name` prop is used as a prefix for the generated CSS classes. For example, if you use `name="slide-fade"`, the generated CSS classes will be `.slide-fade-enter`, `.slide-fade-enter-active`, etc.
The exitting element will be removed from the DOM when the first transition ends. You can override this behavior by providing a `done` callback to the `onExit` prop.
```tsx
import { Transition } from "solid-transition-group"
const [isVisible, setVisible] = createSignal(true)
<Transition name="slide-fade">
<Show when={isVisible()}>
<div>Hello</div>
</Show>
</Transition>
setVisible(false) // triggers exit transition
```
Example CSS transition:
```css
.slide-fade-enter-active,
.slide-fade-exit-active {
transition: opacity 0.3s, transform 0.3s;
}
.slide-fade-enter,
.slide-fade-exit-to {
transform: translateX(10px);
opacity: 0;
}
.slide-fade-enter {
transform: translateX(-10px);
}
```
Props for customizing the CSS classes applied by `<Transition>`:
| Name | Description |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | Used to automatically generate transition CSS class names. e.g. `name: 'fade'` will auto expand to `.fade-enter`, `.fade-enter-active`, etc. Defaults to `"s"`. |
| `enterClass` | CSS class applied to the entering element at the start of the enter transition, and removed the frame after. Defaults to `"s-enter"`. |
| `enterToClass` | CSS class applied to the entering element after the enter transition starts. Defaults to `"s-enter-to"`. |
| `enterActiveClass` | CSS class applied to the entering element for the entire duration of the enter transition. Defaults to `"s-enter-active"`. |
| `exitClass` | CSS class applied to the exiting element at the start of the exit transition, and removed the frame after. Defaults to `"s-exit"`. |
| `exitToClass` | CSS class applied to the exiting element after the exit transition starts. Defaults to `"s-exit-to"`. |
| `exitActiveClass` | CSS class applied to the exiting element for the entire duration of the exit transition. Defaults to `"s-exit-active"`. |
### Using with JavaScript
You can also use JavaScript to animate the transition. The `<Transition>` component provides several events that you can use to hook into the transition lifecycle. The `onEnter` and `onExit` events are called when the transition starts, and the `onBeforeEnter` and `onBeforeExit` events are called before the transition starts. The `onAfterEnter` and `onAfterExit` events are called after the transition ends.
```jsx
<Transition
onEnter={(el, done) => {
const a = el.animate([{ opacity: 0 }, { opacity: 1 }], {
duration: 600
});
a.finished.then(done);
}}
onExit={(el, done) => {
const a = el.animate([{ opacity: 1 }, { opacity: 0 }], {
duration: 600
});
a.finished.then(done);
}}
>
{show() && <div>Hello</div>}
</Transition>
```
**Events** proved by `<Transition>` for animating elements with JavaScript:
| Name | Parameters | Description |
| --------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onBeforeEnter` | `element: Element` | Function called before the enter transition starts. The `element` is not yet rendered. |
| `onEnter` | `element: Element, done: () => void` | Function called when the enter transition starts. The `element` is rendered to the DOM. Call `done` to end the transition - removes the enter classes, and calls `onAfterEnter`. If the parameter for `done` is not provided, it will be called on `transitionend` or `animationend`. |
| `onAfterEnter` | `element: Element` | Function called after the enter transition ends. The `element` is removed from the DOM. |
| `onBeforeExit` | `element: Element` | Function called before the exit transition starts. The `element` is still rendered, exit classes are not yet applied. |
| `onExit` | `element: Element, done: () => void` | Function called when the exit transition starts, after the exit classes are applied (`enterToClass` and `exitActiveClass`). The `element` is still rendered. Call `done` to end the transition - removes exit classes, calls `onAfterExit` and removes the element from the DOM. If the parameter for `done` is not provided, it will be called on `transitionend` or `animationend`. |
| `onAfterExit` | `element: Element` | Function called after the exit transition ends. The `element` is removed from the DOM. |
### Changing Transition Mode
By default, `<Transition>` will apply the transition effect to both entering and exiting elements simultaneously. You can change this behavior by setting the `mode` prop to `"outin"` or `"inout"`. The `"outin"` mode will wait for the exiting element to finish before applying the transition to the entering element. The `"inout"` mode will wait for the entering element to finish before applying the transition to the exiting element.
By default the transition won't be applied on initial render. You can change this behavior by setting the `appear` prop to `true`.
> **Warning:** When using `appear` with SSR, the initial transition will be applied on the client-side, which might cause a flash of unstyled content.
> You need to handle applying the initial transition on the server-side yourself.
## TransitionGroup
### Props
- `moveClass` - CSS class applied to the moving elements for the entire duration of the move transition. Defaults to `"s-move"`.
- exposes the same props as `<Transition>` except `mode`.
### Usage
`<TransitionGroup>` serve as transition effects for multiple elements/components.
`<TransitionGroup>` supports moving transitions via CSS transform. When a child's position on screen has changed after an update, it will get applied a moving CSS class (auto generated from the name attribute or configured with the move-class attribute). If the CSS transform property is "transition-able" when the moving class is applied, the element will be smoothly animated to its destination using the FLIP technique.
```jsx
<ul>
<TransitionGroup name="slide">
<For each={state.items}>{item => <li>{item.text}</li>}</For>
</TransitionGroup>
</ul>
```
## Demo
Kitchen sink demo: https://solid-transition-group.netlify.app/
Source code: https://github.com/solidjs-community/solid-transition-group/blob/main/dev/Test.tsx
## FAQ
- **How to use with Portal?** - [Issue #8](https://github.com/solidjs-community/solid-transition-group/issues/8)
- **How to use with Outlet?** - [Issue #29](https://github.com/solidjs-community/solid-transition-group/issues/29)
- **Why elements are not connected in outin mode** - [Issue #34](https://github.com/solidjs-community/solid-transition-group/issues/34)
+183
View File
@@ -0,0 +1,183 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
Transition: () => Transition,
TransitionGroup: () => TransitionGroup
});
module.exports = __toCommonJS(src_exports);
// src/common.ts
var import_solid_js = require("solid-js");
function createClassnames(props) {
return (0, import_solid_js.createMemo)(() => {
const name = props.name || "s";
return {
enterActive: (props.enterActiveClass || name + "-enter-active").split(" "),
enter: (props.enterClass || name + "-enter").split(" "),
enterTo: (props.enterToClass || name + "-enter-to").split(" "),
exitActive: (props.exitActiveClass || name + "-exit-active").split(" "),
exit: (props.exitClass || name + "-exit").split(" "),
exitTo: (props.exitToClass || name + "-exit-to").split(" "),
move: (props.moveClass || name + "-move").split(" ")
};
});
}
function nextFrame(fn) {
requestAnimationFrame(() => requestAnimationFrame(fn));
}
function enterTransition(classes, events, el, done) {
const { onBeforeEnter, onEnter, onAfterEnter } = events;
onBeforeEnter?.(el);
el.classList.add(...classes.enter);
el.classList.add(...classes.enterActive);
queueMicrotask(() => {
if (!el.parentNode)
return done?.();
onEnter?.(el, () => endTransition());
});
nextFrame(() => {
el.classList.remove(...classes.enter);
el.classList.add(...classes.enterTo);
if (!onEnter || onEnter.length < 2) {
el.addEventListener("transitionend", endTransition);
el.addEventListener("animationend", endTransition);
}
});
function endTransition(e) {
if (!e || e.target === el) {
done?.();
el.removeEventListener("transitionend", endTransition);
el.removeEventListener("animationend", endTransition);
el.classList.remove(...classes.enterActive);
el.classList.remove(...classes.enterTo);
onAfterEnter?.(el);
}
}
}
function exitTransition(classes, events, el, done) {
const { onBeforeExit, onExit, onAfterExit } = events;
if (!el.parentNode)
return done?.();
onBeforeExit?.(el);
el.classList.add(...classes.exit);
el.classList.add(...classes.exitActive);
onExit?.(el, () => endTransition());
nextFrame(() => {
el.classList.remove(...classes.exit);
el.classList.add(...classes.exitTo);
if (!onExit || onExit.length < 2) {
el.addEventListener("transitionend", endTransition);
el.addEventListener("animationend", endTransition);
}
});
function endTransition(e) {
if (!e || e.target === el) {
done?.();
el.removeEventListener("transitionend", endTransition);
el.removeEventListener("animationend", endTransition);
el.classList.remove(...classes.exitActive);
el.classList.remove(...classes.exitTo);
onAfterExit?.(el);
}
}
}
// src/Transition.ts
var import_transition_group = require("@solid-primitives/transition-group");
var import_refs = require("@solid-primitives/refs");
var TRANSITION_MODE_MAP = {
inout: "in-out",
outin: "out-in"
};
var Transition = (props) => {
const classnames = createClassnames(props);
return (0, import_transition_group.createSwitchTransition)(
(0, import_refs.resolveFirst)(() => props.children),
{
mode: TRANSITION_MODE_MAP[props.mode],
appear: props.appear,
onEnter(el, done) {
enterTransition(classnames(), props, el, done);
},
onExit(el, done) {
exitTransition(classnames(), props, el, done);
}
}
);
};
// src/TransitionGroup.ts
var import_transition_group2 = require("@solid-primitives/transition-group");
var import_refs2 = require("@solid-primitives/refs");
var TransitionGroup = (props) => {
const classnames = createClassnames(props);
return (0, import_transition_group2.createListTransition)((0, import_refs2.resolveElements)(() => props.children).toArray, {
appear: props.appear,
exitMethod: "keep-index",
onChange({ added, removed, finishRemoved, list }) {
const classes = classnames();
for (const el of added) {
enterTransition(classes, props, el);
}
const toMove = [];
for (const el of list) {
if (el.isConnected && (el instanceof HTMLElement || el instanceof SVGElement)) {
toMove.push({ el, rect: el.getBoundingClientRect() });
}
}
queueMicrotask(() => {
const moved = [];
for (const { el, rect } of toMove) {
if (el.isConnected) {
const newRect = el.getBoundingClientRect(), dX = rect.left - newRect.left, dY = rect.top - newRect.top;
if (dX || dY) {
el.style.transform = `translate(${dX}px, ${dY}px)`;
el.style.transitionDuration = "0s";
moved.push(el);
}
}
}
document.body.offsetHeight;
for (const el of moved) {
let endTransition2 = function(e) {
if (e.target === el || /transform$/.test(e.propertyName)) {
el.removeEventListener("transitionend", endTransition2);
el.classList.remove(...classes.move);
}
};
var endTransition = endTransition2;
el.classList.add(...classes.move);
el.style.transform = el.style.transitionDuration = "";
el.addEventListener("transitionend", endTransition2);
}
});
for (const el of removed) {
exitTransition(classes, props, el, () => finishRemoved([el]));
}
}
});
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Transition,
TransitionGroup
});
+123
View File
@@ -0,0 +1,123 @@
import { FlowComponent } from 'solid-js';
type TransitionEvents = {
/**
* Function called before the enter transition starts.
* The {@link element} is not yet rendered.
*/
onBeforeEnter?: (element: Element) => void;
/**
* Function called when the enter transition starts.
* The {@link element} is rendered to the DOM.
*
* Call {@link done} to end the transition - removes the enter classes,
* and calls {@link TransitionEvents.onAfterEnter}.
* If the parameter for {@link done} is not provided, it will be called on `transitionend` or `animationend`.
*/
onEnter?: (element: Element, done: () => void) => void;
/**
* Function called after the enter transition ends.
* The {@link element} is removed from the DOM.
*/
onAfterEnter?: (element: Element) => void;
/**
* Function called before the exit transition starts.
* The {@link element} is still rendered, exit classes are not yet applied.
*/
onBeforeExit?: (element: Element) => void;
/**
* Function called when the exit transition starts, after the exit classes are applied
* ({@link TransitionProps.enterToClass} and {@link TransitionProps.exitActiveClass}).
* The {@link element} is still rendered.
*
* Call {@link done} to end the transition - removes exit classes,
* calls {@link TransitionEvents.onAfterExit} and removes the element from the DOM.
* If the parameter for {@link done} is not provided, it will be called on `transitionend` or `animationend`.
*/
onExit?: (element: Element, done: () => void) => void;
/**
* Function called after the exit transition ends.
* The {@link element} is removed from the DOM.
*/
onAfterExit?: (element: Element) => void;
};
/**
* Props for the {@link Transition} component.
*/
type TransitionProps = TransitionEvents & {
/**
* Used to automatically generate transition CSS class names.
* e.g. `name: 'fade'` will auto expand to `.fade-enter`, `.fade-enter-active`, etc.
* Defaults to `"s"`.
*/
name?: string;
/**
* CSS class applied to the entering element for the entire duration of the enter transition.
* Defaults to `"s-enter-active"`.
*/
enterActiveClass?: string;
/**
* CSS class applied to the entering element at the start of the enter transition, and removed the frame after.
* Defaults to `"s-enter"`.
*/
enterClass?: string;
/**
* CSS class applied to the entering element after the enter transition starts.
* Defaults to `"s-enter-to"`.
*/
enterToClass?: string;
/**
* CSS class applied to the exiting element for the entire duration of the exit transition.
* Defaults to `"s-exit-active"`.
*/
exitActiveClass?: string;
/**
* CSS class applied to the exiting element at the start of the exit transition, and removed the frame after.
* Defaults to `"s-exit"`.
*/
exitClass?: string;
/**
* CSS class applied to the exiting element after the exit transition starts.
* Defaults to `"s-exit-to"`.
*/
exitToClass?: string;
/**
* Whether to apply transition on initial render. Defaults to `false`.
*/
appear?: boolean;
/**
* Controls the timing sequence of leaving/entering transitions.
* Available modes are `"outin"` and `"inout"`;
* Defaults to simultaneous.
*/
mode?: "inout" | "outin";
};
/**
* The `<Transition>` component lets you apply enter and leave animations on element passed to `props.children`.
*
* It only supports transitioning a single element at a time.
*
* @param props {@link TransitionProps}
*/
declare const Transition: FlowComponent<TransitionProps>;
/**
* Props for the {@link TransitionGroup} component.
*/
type TransitionGroupProps = Omit<TransitionProps, "mode"> & {
/**
* CSS class applied to the moving elements for the entire duration of the move transition.
* Defaults to `"s-move"`.
*/
moveClass?: string;
};
/**
* The `<TransitionGroup>` component lets you apply enter and leave animations on elements passed to `props.children`.
*
* It supports transitioning multiple elements at a time and moving elements around.
*
* @param props {@link TransitionGroupProps}
*/
declare const TransitionGroup: FlowComponent<TransitionGroupProps>;
export { Transition, TransitionEvents, TransitionGroup, TransitionGroupProps, TransitionProps };
+123
View File
@@ -0,0 +1,123 @@
import { FlowComponent } from 'solid-js';
type TransitionEvents = {
/**
* Function called before the enter transition starts.
* The {@link element} is not yet rendered.
*/
onBeforeEnter?: (element: Element) => void;
/**
* Function called when the enter transition starts.
* The {@link element} is rendered to the DOM.
*
* Call {@link done} to end the transition - removes the enter classes,
* and calls {@link TransitionEvents.onAfterEnter}.
* If the parameter for {@link done} is not provided, it will be called on `transitionend` or `animationend`.
*/
onEnter?: (element: Element, done: () => void) => void;
/**
* Function called after the enter transition ends.
* The {@link element} is removed from the DOM.
*/
onAfterEnter?: (element: Element) => void;
/**
* Function called before the exit transition starts.
* The {@link element} is still rendered, exit classes are not yet applied.
*/
onBeforeExit?: (element: Element) => void;
/**
* Function called when the exit transition starts, after the exit classes are applied
* ({@link TransitionProps.enterToClass} and {@link TransitionProps.exitActiveClass}).
* The {@link element} is still rendered.
*
* Call {@link done} to end the transition - removes exit classes,
* calls {@link TransitionEvents.onAfterExit} and removes the element from the DOM.
* If the parameter for {@link done} is not provided, it will be called on `transitionend` or `animationend`.
*/
onExit?: (element: Element, done: () => void) => void;
/**
* Function called after the exit transition ends.
* The {@link element} is removed from the DOM.
*/
onAfterExit?: (element: Element) => void;
};
/**
* Props for the {@link Transition} component.
*/
type TransitionProps = TransitionEvents & {
/**
* Used to automatically generate transition CSS class names.
* e.g. `name: 'fade'` will auto expand to `.fade-enter`, `.fade-enter-active`, etc.
* Defaults to `"s"`.
*/
name?: string;
/**
* CSS class applied to the entering element for the entire duration of the enter transition.
* Defaults to `"s-enter-active"`.
*/
enterActiveClass?: string;
/**
* CSS class applied to the entering element at the start of the enter transition, and removed the frame after.
* Defaults to `"s-enter"`.
*/
enterClass?: string;
/**
* CSS class applied to the entering element after the enter transition starts.
* Defaults to `"s-enter-to"`.
*/
enterToClass?: string;
/**
* CSS class applied to the exiting element for the entire duration of the exit transition.
* Defaults to `"s-exit-active"`.
*/
exitActiveClass?: string;
/**
* CSS class applied to the exiting element at the start of the exit transition, and removed the frame after.
* Defaults to `"s-exit"`.
*/
exitClass?: string;
/**
* CSS class applied to the exiting element after the exit transition starts.
* Defaults to `"s-exit-to"`.
*/
exitToClass?: string;
/**
* Whether to apply transition on initial render. Defaults to `false`.
*/
appear?: boolean;
/**
* Controls the timing sequence of leaving/entering transitions.
* Available modes are `"outin"` and `"inout"`;
* Defaults to simultaneous.
*/
mode?: "inout" | "outin";
};
/**
* The `<Transition>` component lets you apply enter and leave animations on element passed to `props.children`.
*
* It only supports transitioning a single element at a time.
*
* @param props {@link TransitionProps}
*/
declare const Transition: FlowComponent<TransitionProps>;
/**
* Props for the {@link TransitionGroup} component.
*/
type TransitionGroupProps = Omit<TransitionProps, "mode"> & {
/**
* CSS class applied to the moving elements for the entire duration of the move transition.
* Defaults to `"s-move"`.
*/
moveClass?: string;
};
/**
* The `<TransitionGroup>` component lets you apply enter and leave animations on elements passed to `props.children`.
*
* It supports transitioning multiple elements at a time and moving elements around.
*
* @param props {@link TransitionGroupProps}
*/
declare const TransitionGroup: FlowComponent<TransitionGroupProps>;
export { Transition, TransitionEvents, TransitionGroup, TransitionGroupProps, TransitionProps };
+155
View File
@@ -0,0 +1,155 @@
// src/common.ts
import { createMemo } from "solid-js";
function createClassnames(props) {
return createMemo(() => {
const name = props.name || "s";
return {
enterActive: (props.enterActiveClass || name + "-enter-active").split(" "),
enter: (props.enterClass || name + "-enter").split(" "),
enterTo: (props.enterToClass || name + "-enter-to").split(" "),
exitActive: (props.exitActiveClass || name + "-exit-active").split(" "),
exit: (props.exitClass || name + "-exit").split(" "),
exitTo: (props.exitToClass || name + "-exit-to").split(" "),
move: (props.moveClass || name + "-move").split(" ")
};
});
}
function nextFrame(fn) {
requestAnimationFrame(() => requestAnimationFrame(fn));
}
function enterTransition(classes, events, el, done) {
const { onBeforeEnter, onEnter, onAfterEnter } = events;
onBeforeEnter?.(el);
el.classList.add(...classes.enter);
el.classList.add(...classes.enterActive);
queueMicrotask(() => {
if (!el.parentNode)
return done?.();
onEnter?.(el, () => endTransition());
});
nextFrame(() => {
el.classList.remove(...classes.enter);
el.classList.add(...classes.enterTo);
if (!onEnter || onEnter.length < 2) {
el.addEventListener("transitionend", endTransition);
el.addEventListener("animationend", endTransition);
}
});
function endTransition(e) {
if (!e || e.target === el) {
done?.();
el.removeEventListener("transitionend", endTransition);
el.removeEventListener("animationend", endTransition);
el.classList.remove(...classes.enterActive);
el.classList.remove(...classes.enterTo);
onAfterEnter?.(el);
}
}
}
function exitTransition(classes, events, el, done) {
const { onBeforeExit, onExit, onAfterExit } = events;
if (!el.parentNode)
return done?.();
onBeforeExit?.(el);
el.classList.add(...classes.exit);
el.classList.add(...classes.exitActive);
onExit?.(el, () => endTransition());
nextFrame(() => {
el.classList.remove(...classes.exit);
el.classList.add(...classes.exitTo);
if (!onExit || onExit.length < 2) {
el.addEventListener("transitionend", endTransition);
el.addEventListener("animationend", endTransition);
}
});
function endTransition(e) {
if (!e || e.target === el) {
done?.();
el.removeEventListener("transitionend", endTransition);
el.removeEventListener("animationend", endTransition);
el.classList.remove(...classes.exitActive);
el.classList.remove(...classes.exitTo);
onAfterExit?.(el);
}
}
}
// src/Transition.ts
import { createSwitchTransition } from "@solid-primitives/transition-group";
import { resolveFirst } from "@solid-primitives/refs";
var TRANSITION_MODE_MAP = {
inout: "in-out",
outin: "out-in"
};
var Transition = (props) => {
const classnames = createClassnames(props);
return createSwitchTransition(
resolveFirst(() => props.children),
{
mode: TRANSITION_MODE_MAP[props.mode],
appear: props.appear,
onEnter(el, done) {
enterTransition(classnames(), props, el, done);
},
onExit(el, done) {
exitTransition(classnames(), props, el, done);
}
}
);
};
// src/TransitionGroup.ts
import { createListTransition } from "@solid-primitives/transition-group";
import { resolveElements } from "@solid-primitives/refs";
var TransitionGroup = (props) => {
const classnames = createClassnames(props);
return createListTransition(resolveElements(() => props.children).toArray, {
appear: props.appear,
exitMethod: "keep-index",
onChange({ added, removed, finishRemoved, list }) {
const classes = classnames();
for (const el of added) {
enterTransition(classes, props, el);
}
const toMove = [];
for (const el of list) {
if (el.isConnected && (el instanceof HTMLElement || el instanceof SVGElement)) {
toMove.push({ el, rect: el.getBoundingClientRect() });
}
}
queueMicrotask(() => {
const moved = [];
for (const { el, rect } of toMove) {
if (el.isConnected) {
const newRect = el.getBoundingClientRect(), dX = rect.left - newRect.left, dY = rect.top - newRect.top;
if (dX || dY) {
el.style.transform = `translate(${dX}px, ${dY}px)`;
el.style.transitionDuration = "0s";
moved.push(el);
}
}
}
document.body.offsetHeight;
for (const el of moved) {
let endTransition2 = function(e) {
if (e.target === el || /transform$/.test(e.propertyName)) {
el.removeEventListener("transitionend", endTransition2);
el.classList.remove(...classes.move);
}
};
var endTransition = endTransition2;
el.classList.add(...classes.move);
el.style.transform = el.style.transitionDuration = "";
el.addEventListener("transitionend", endTransition2);
}
});
for (const el of removed) {
exitTransition(classes, props, el, () => finishRemoved([el]));
}
}
});
};
export {
Transition,
TransitionGroup
};
+59
View File
@@ -0,0 +1,59 @@
{
"name": "solid-transition-group",
"description": "Components to manage animations for SolidJS",
"author": "Ryan Carniato",
"license": "MIT",
"version": "0.2.3",
"homepage": "https://github.com/solidjs/solid-transition-group#readme",
"repository": {
"type": "git",
"url": "https://github.com/solidjs/solid-transition-group"
},
"sideEffects": false,
"private": false,
"type": "module",
"main": "dist/index.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"dev": "astro dev --root dev",
"build:site": "astro build --root dev",
"build": "tsup",
"test:client": "vitest",
"test:ssr": "pnpm run test:client --mode ssr",
"test": "concurrently pnpm:test:*",
"format": "prettier -w **/*.{js,ts,json,css,tsx,jsx} --ignore-path .gitignore",
"release": "pnpm build && release-it"
},
"devDependencies": {
"@astrojs/solid-js": "^2.2.0",
"@astrojs/tailwind": "^4.0.0",
"@release-it/keep-a-changelog": "^4.0.0",
"astro": "^2.10.1",
"concurrently": "^8.2.0",
"jsdom": "^22.1.0",
"prettier": "^3.0.1",
"release-it": "^16.1.3",
"solid-js": "^1.7.9",
"tailwindcss": "^3.3.3",
"tsup": "^7.2.0",
"typescript": "^5.1.6",
"vite-plugin-solid": "^2.7.0",
"vitest": "^0.34.1"
},
"dependencies": {
"@solid-primitives/refs": "^1.0.5",
"@solid-primitives/transition-group": "^1.0.2"
},
"peerDependencies": {
"solid-js": "^1.6.12"
},
"packageManager": "pnpm@8.6.0",
"engines": {
"node": ">=18.0.0",
"pnpm": ">=8.6.0"
}
}