Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions packages/v4/docs/utils/css.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@ import { matrix, transform } from '@studiometa/js-toolkit-v4/utils';

[[toc]]

## `transform`
## Transforms

### transform

```ts
transform(props: TransformProps): string
```

Builds a `transform` value from named parts, so a component composes a transform instead of assembling a string:

```js twoslash
// @twoslash-cache: {"v":1,"hash":"9a8e004351703f9dffdc3f904dd9d23844d07bb9b49a501a38f6f2dbd5cb7a95","data":"N4Igdg9gJgpgziAXAbVAFwJ4AcZJACwgDcYAnEAGhDRgA808AKAQwBsBLZuASgAIAzAK5gAxmnYQwvNKWZg4/CKQC2jLKQhY4iXgBVZ8xSoAKGrdx1wZ7MAHMAOmHbKsStNIMKlyyiCgQRBEQQADFvZndmXgBhAGVYjzkvFQA6R0ddfBhpfFIYbOZaeF4Ifl4omSTWCIkpZjySsGyAA0r5apoAZihminKwKBzsuEJSNHw5QdLHKI00Gsk+qLgRNmylct44AGsYAHdePZs4EpJSXnY0E5xSAFpC9muzMnF4FN952yDkZBA6ZhcrFwVGaoIAVnBHG1kqpgLxaDoAIwABmRfRWax0yJSAFZeABfbgAbkcAHpSYl2hEYN1GCjkVhaH0GUzeCy+BigYxsTjuI5Qc0QABdIVUKz1BiIACcVCBdnGSBl1HqthgkuoniMPllNlwiDRIBEE1kYjIivxFHQ2D1BGIZqoNHoTDYnB4lJhajM2j0mu8pk0PEs1jsjmcrjG7q1vn8gTwYRUEU2cQS0K1aTAGSyOTyBSKJ1Km2hHVq5QakhaRep3V6/UG42Go3GkxK/BmvDmCzASy2qyBJXOy12ByO8lOZAuV14N3utEeU+eY3Ybw+zC+SB+f1oAKwQN8AohUN9KkYcIRvHp6N7MCxuIJxLJFMrXSgdNRjOZ77ZjI5V+5uL5YACsKoogOKYxIAAbAATLKMDyvgioOiqap4Km3i+BwTRIDBhrGswprkPqFpWjgeCEGcHx0OqnqaC8GB8PoSRav6WgpLQAD8OhgIIygAEbjgAPrwwiwPwupQL4YGSgA7AALLB8FIIiSGkKq6q0BhurYVQRr1PhNCEYiUHEdQ1pkXa5AOlRTDqLRYz0T6TF+l6KQYJxvDcXxgnCQMMBiU0ElivM4GIAAHMpIByrYCqIBFwVqXgGCaVhiA4bpJoGUpUomZgpHBOR9rUNZwQ0TcmAMUeygsXAKScjA7mefx5xCSJfniZJwWSqFoUKdFCGIDiKkJcEdXJXqaV4QR2EQTlZn5RZlFOiVtllQ5jGGM5AYpB2NANTxTW8C1vn+TAgWgZ1Smor1MUQUNKHBDtwKRVpqU6ZNmWIJ0oX4iBIjQDaYZuLwcJoSoBICBoyi8AA5AAAlYghQBIyhqswpIQrcaAQBArDbJctxELJpKCOIrBwNDJIZmAoOwvCSJorwGA6FBDN1UiuJ9I9OiyXihJEr4KPzEgoBUXBcC1HgEIgPi+JAA"}
import { transform } from '@studiometa/js-toolkit-v4/utils';

transform({ x: 10, y: 20, scale: 1.5, rotate: 45 });
```

`TransformProps` takes `x`, `y`, `z`, `rotate`, `rotateX`, `rotateY`, `rotateZ`, `scale`, `scaleX`, `scaleY`, `scaleZ`, `skew` and the rest of the family. `TRANSFORM_PROPS` is the ordered list of the keys it reads.
Builds a `transform` value from named parts, so a component composes a transform instead of assembling a string. `TransformProps` takes `x`, `y`, `z`, `rotate`, `rotateX`, `rotateY`, `rotateZ`, `scale`, `scaleX`, `scaleY`, `scaleZ`, `skew` and the rest of the family.

**The order is fixed by `TRANSFORM_PROPS`, not by the object.** Transform functions do not commute, so two components building "the same" transform from differently-ordered literals must still get the same matrix.

## `matrix`
### matrix

```ts
matrix(props?: MatrixProps): string
Expand All @@ -41,7 +41,17 @@ matrix({ scaleX: 2, translateX: 10 });

A `matrix()` string. Reach for it when a value has to be interpolated as a matrix rather than as separate functions.

## `getOffsetSizes`
### TRANSFORM_PROPS

```ts
const TRANSFORM_PROPS: readonly (keyof TransformProps)[];
```

The ordered list of keys `transform()` reads.

## Measuring

### getOffsetSizes

```ts
getOffsetSizes(element: HTMLElement): { x, y, width, height, top, right, bottom, left }
Expand All @@ -62,14 +72,18 @@ That is exactly what a drag or a tilt needs: the layout box is the frame of refe
Call it from the `read` phase — [`$read()`](/api/instance-methods.html#read-and-write) — so it batches with every other measurement of the frame.
:::

## `setClassesOrStyles`
## Applying

### setClassesOrStyles

```ts
setClassesOrStyles(el: HTMLElement, value: string | string[] | Partial<CSSStyleDeclaration> | undefined, method?: 'add' | 'remove'): void
setClassesOrStyles(
el: HTMLElement,
value: string | string[] | Partial<CSSStyleDeclaration> | undefined,
method?: 'add' | 'remove',
): void
```

Applies a value that may be **either** classes or inline styles, which is what lets [`transition()`](./transitions.html) take one option in both forms:

```js twoslash
// @twoslash-cache: {"v":1,"hash":"922eff9993f504dc1ead2fb24a0c4110ba1104c8ee56fa19ef3fe0d7208624ab","data":"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="}
import { setClassesOrStyles } from '@studiometa/js-toolkit-v4/utils';
Expand All @@ -82,6 +96,8 @@ setClassesOrStyles(el, { opacity: '0' }); // inline styles
setClassesOrStyles(el, 'is-active', 'remove'); // undo it
```

Applies a value that may be **either** classes or inline styles, which is what lets [`transition()`](./transitions.html) take one option in both forms.

An `undefined` value does nothing, so a caller with an optional state does not have to branch.

## What is not here
Expand Down
4 changes: 2 additions & 2 deletions packages/v4/docs/utils/dom.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { createElement, selectorFor } from '@studiometa/js-toolkit-v4/utils';

[[toc]]

## `createElement`
## createElement

```ts
createElement(tag?, children?): HTMLElement
Expand All @@ -32,7 +32,7 @@ createElement('button', { class: 'btn', data: { component: 'Action' } }, 'Send')

The `data` key is why this exists rather than three lines of `document.createElement`: building an element that carries `data-component` and a few `data-option-*` is the common case, and spelling each `setAttribute()` out loses the shape.

## `selectorFor`
## selectorFor

```ts
selectorFor(name: string): string
Expand Down
186 changes: 169 additions & 17 deletions packages/v4/docs/utils/easings.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,20 @@ An `EasingFunction` takes a `0 → 1` progress and returns a shaped `0 → 1` va

[[toc]]

## The 24 functions
## Choosing one

Eight curves, three directions each:
Eight curves, three directions each. Every `out` and `in-out` is derived from its `in`.

| Curve | In | Out | In-out |
| ------ | ------------- | -------------- | ---------------- |
| linear | `easeLinear` | — | — |
| quad | `easeInQuad` | `easeOutQuad` | `easeInOutQuad` |
| cubic | `easeInCubic` | `easeOutCubic` | `easeInOutCubic` |
| quart | `easeInQuart` | `easeOutQuart` | `easeInOutQuart` |
| quint | `easeInQuint` | `easeOutQuint` | `easeInOutQuint` |
| sine | `easeInSine` | `easeOutSine` | `easeInOutSine` |
| circ | `easeInCirc` | `easeOutCirc` | `easeInOutCirc` |
| expo | `easeInExpo` | `easeOutExpo` | `easeInOutExpo` |

`easeLinear` is the identity, and it exists so a call site can name "no easing" rather than branch on `undefined`.
| Curve | In | Out | In-out |
| ------ | ----------------------------- | ------------------------------- | ----------------------------------- |
| linear | [`easeLinear`](#easelinear) | — | — |
| quad | [`easeInQuad`](#easeinquad) | [`easeOutQuad`](#easeoutquad) | [`easeInOutQuad`](#easeinoutquad) |
| cubic | [`easeInCubic`](#easeincubic) | [`easeOutCubic`](#easeoutcubic) | [`easeInOutCubic`](#easeinoutcubic) |
| quart | [`easeInQuart`](#easeinquart) | [`easeOutQuart`](#easeoutquart) | [`easeInOutQuart`](#easeinoutquart) |
| quint | [`easeInQuint`](#easeinquint) | [`easeOutQuint`](#easeoutquint) | [`easeInOutQuint`](#easeinoutquint) |
| sine | [`easeInSine`](#easeinsine) | [`easeOutSine`](#easeoutsine) | [`easeInOutSine`](#easeinoutsine) |
| circ | [`easeInCirc`](#easeincirc) | [`easeOutCirc`](#easeoutcirc) | [`easeInOutCirc`](#easeinoutcirc) |
| expo | [`easeInExpo`](#easeinexpo) | [`easeOutExpo`](#easeoutexpo) | [`easeInOutExpo`](#easeinoutexpo) |

## Deriving one

Expand All @@ -53,7 +51,23 @@ const easeInOutBack = createEaseInOut(easeInBack);

That is why only the eight `in` functions are written out and the other sixteen are derived: an `out` is an `in` run backwards, and writing it twice is how the two drift apart.

## Usage
### createEaseOut

```ts
createEaseOut(easeIn: EasingFunction): EasingFunction
```

Mirror an `in` curve into its `out`.

### createEaseInOut

```ts
createEaseInOut(easeIn: EasingFunction): EasingFunction
```

Compose an `in` curve into its symmetric `in-out`.

## Using one

```js twoslash
// @twoslash-cache: {"v":1,"hash":"09933edf6d2a922b7f27e4d7327afd8598ff86255acb641b0754c36ba307675c","data":"N4Igdg9gJgpgziAXAbVAFwJ4AcZJACwgDcYAnEAGhDRgA808AKAQwBsBLZuASgAIBjCGDhpeMLjADyAVzQBhaQCN2/RLwCiXdmADmAMWlh+adkIA6YdgFssEUqPFwpshcv6UQI5vaQBOKqwwumj4SACMAExUaN46MAyIII7O8koqHhxguIgADFT8+N7MxmR+AL4U6NjZBMSl0XQJICwcXHwAZobGpmC8gaRYjFbaamDSVopkFLxWzLSj45Ok06TMJhALE2Tcm0sW1rb2fWRYHlAQ/AiJAJJgNAMQrGswvMy8q+u8k2gA7jBBvF+EC+EEMUDgADoPF4fIgIgBmAJBHQhJAAFmisXieH6pwC2myeRABSKJXIcPhFSqODwhBI5Aa9DwnSM616tjg7DZAEE0IwsKQIDpSPA4GpmGAMDteGMtgzPDFYQAOImBYKhRBhImKuJNDlcnq8jIEpBRYmFVZk8qVajVWl1eU0JmJflFKzxba8AVCkVwMWvSXQxUJXxhJHqpBKzGkXV4b3C0XGrKm/IW4r3U05Km2mmJOn1aiNJhsTg8Y4DIYjGWLKYzOa7WsfUwN0jS2V7Sw2OyiXFnC5XEC3e62J40V7vNamL7xP4AoEgsGQoPeBJhSLhlEajHULFNXv45OIRHm0kZxC+bOYXO1ekeJ1NFqlvjJGSpNz8wUJv0tts10j7LsjhfFw0ncKgYVXCIAFYN1RTUzR1bFEmAt90gPbJjxJS0zwiCJLztPMHTvIsXSwN0PVbL1P19f0JQwZdYTCeEoxANVN0jaNY0SeMaKTDDU1PUojygsoAF18mgGoDm7XhgDECRX1cFRplxXgyl4dpBSsXgAHIAAERGkKBTHdGIAHoACs4AAWjQCBHgAay5ayiDRMzZHYVg4B0gBuCwLBZbohC9CBOR5PkeNFPhgAsXh3niaRSF6XFGDyXg0RyNKUKU/gPx9KLuD8sAyg8UzmCQUBGiCTkhDwKyQDKMogA="}
Expand All @@ -66,9 +80,147 @@ function positionAt(progress) {

An easing shapes a **progress**, so it pairs with a value that already runs `0 → 1`: a [`useScrollProgress()`](/api/services/useScrollProgress.html) subscriber, or a `map()` of anything else.

## What they are not for
## They do not animate

They do not animate. There is no clock here — an easing is a pure function of a progress you already have.
There is no clock here — an easing is a pure function of a progress you already have.

- For a value chasing a target frame by frame, use [`damp()` or `smoothTo()`](./motion.html).
- For time-based playback, stagger and sequencing, that is the separate `ui-animation` package. `tween` and `animate` are not shipped.

## The functions

Each takes a `0 → 1` progress and returns the shaped value.

### easeLinear

```ts
easeLinear(progress: number): number
```

The identity. It exists so a call site can name "no easing" rather than branch on `undefined`.

### easeInQuad

```ts
easeInQuad(progress: number): number
```

### easeOutQuad

```ts
easeOutQuad(progress: number): number
```

### easeInOutQuad

```ts
easeInOutQuad(progress: number): number
```

### easeInCubic

```ts
easeInCubic(progress: number): number
```

### easeOutCubic

```ts
easeOutCubic(progress: number): number
```

### easeInOutCubic

```ts
easeInOutCubic(progress: number): number
```

### easeInQuart

```ts
easeInQuart(progress: number): number
```

### easeOutQuart

```ts
easeOutQuart(progress: number): number
```

### easeInOutQuart

```ts
easeInOutQuart(progress: number): number
```

### easeInQuint

```ts
easeInQuint(progress: number): number
```

### easeOutQuint

```ts
easeOutQuint(progress: number): number
```

### easeInOutQuint

```ts
easeInOutQuint(progress: number): number
```

### easeInSine

```ts
easeInSine(progress: number): number
```

### easeOutSine

```ts
easeOutSine(progress: number): number
```

### easeInOutSine

```ts
easeInOutSine(progress: number): number
```

### easeInCirc

```ts
easeInCirc(progress: number): number
```

### easeOutCirc

```ts
easeOutCirc(progress: number): number
```

### easeInOutCirc

```ts
easeInOutCirc(progress: number): number
```

### easeInExpo

```ts
easeInExpo(progress: number): number
```

### easeOutExpo

```ts
easeOutExpo(progress: number): number
```

### easeInOutExpo

```ts
easeInOutExpo(progress: number): number
```
40 changes: 27 additions & 13 deletions packages/v4/docs/utils/focus.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,7 @@ import { saveActiveElement, trapFocus, untrapFocus } from '@studiometa/js-toolki

The three calls a modal surface needs.

## The three

```ts
saveActiveElement(): void
trapFocus(el: HTMLElement, event: KeyboardEvent): void
untrapFocus(): void
```

| Function | Does |
| ---------------------- | ------------------------------------------------------------- |
| `saveActiveElement()` | remembers what had focus, so `untrapFocus()` can give it back |
| `trapFocus(el, event)` | keeps `Tab` and `Shift+Tab` inside `el` |
| `untrapFocus()` | releases the trap and restores focus to the saved element |
[[toc]]

## Usage

Expand Down Expand Up @@ -63,6 +51,32 @@ mounted() {
`trapFocus()` calls `preventDefault()` on the event it is handed, and a passive listener cannot. See [`useKey()`](/api/services/useKey.html#the-listeners-are-neither-passive-nor-capturing).
:::

## The three

### saveActiveElement

```ts
saveActiveElement(): void
```

Remembers what had focus, so `untrapFocus()` can give it back.

### trapFocus

```ts
trapFocus(el: HTMLElement, event: KeyboardEvent): void
```

Keeps `Tab` and `Shift+Tab` inside `el`.

### untrapFocus

```ts
untrapFocus(): void
```

Releases the trap and restores focus to the saved element.

## The saved element is shared across copies

Through the shared runtime, for the same reason the scroll lock counts: **there is one focus per document**. Two independently evaluated copies of the package must not each think they own it.
Expand Down
Loading
Loading