@tempots/dom 7.1.3 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ import { Renderable } from "../renderable";
2
+ export declare function Autofocus(): Renderable;
@@ -0,0 +1,4 @@
1
+ import { Lifecycle } from "./Lifecycle";
2
+ export function Autofocus() {
3
+ return Lifecycle({ onMount: (el) => setTimeout(() => el && el.focus(), 10) });
4
+ }
@@ -1,14 +1,14 @@
1
- import { type JSX } from '../jsx';
1
+ import { type JSX } from '../jsx-runtime';
2
2
  import { type Signal } from '../prop';
3
3
  export interface IfProps {
4
4
  is: Signal<boolean>;
5
- then?: JSX.DOMNode;
6
- otherwise?: JSX.DOMNode;
5
+ then?: () => JSX.DOMNode;
6
+ otherwise?: () => JSX.DOMNode;
7
7
  }
8
8
  export declare function If({ is, then, otherwise }: IfProps): JSX.DOMNode;
9
9
  export interface WhenProps {
10
10
  is: Signal<boolean>;
11
- children?: JSX.DOMNode;
11
+ children?: () => JSX.DOMNode;
12
12
  }
13
13
  export declare function When({ is, children }: WhenProps): JSX.DOMNode;
14
14
  export declare function Unless({ is, children }: WhenProps): JSX.DOMNode;
package/components/If.js CHANGED
@@ -1,19 +1,19 @@
1
1
  import { OneOfImpl } from './OneOf';
2
2
  export function If({ is, then, otherwise }) {
3
- return new OneOfImpl(is.map(v => v ? { 1: true } : { 2: false }), {
4
- 1: () => then,
5
- 2: () => otherwise
3
+ return new OneOfImpl(is.map(v => v ? { then: true } : { otherwise: false }), {
4
+ then: then || (() => null),
5
+ otherwise: otherwise || (() => null)
6
6
  });
7
7
  }
8
8
  export function When({ is, children }) {
9
- return new OneOfImpl(is.map(v => v ? { 1: true } : { 2: false }), {
10
- 1: () => children,
11
- 2: () => null
9
+ return new OneOfImpl(is.map(v => v ? { then: true } : { otherwise: false }), {
10
+ then: children,
11
+ otherwise: (() => null)
12
12
  });
13
13
  }
14
14
  export function Unless({ is, children }) {
15
- return new OneOfImpl(is.map(v => v ? { 1: true } : { 2: false }), {
16
- 1: () => null,
17
- 2: () => children
15
+ return new OneOfImpl(is.map(v => v ? { then: true } : { otherwise: false }), {
16
+ then: (() => null),
17
+ otherwise: children
18
18
  });
19
19
  }
@@ -3,7 +3,7 @@ import { type Signal } from '../prop';
3
3
  import { type JSX } from '../jsx-runtime';
4
4
  export interface NotEmptyProps<T> {
5
5
  on: Signal<T>;
6
- whenEmpty?: JSX.DOMNode;
7
- display: JSX.DOMNode;
6
+ whenEmpty?: () => JSX.DOMNode;
7
+ display: () => JSX.DOMNode;
8
8
  }
9
9
  export declare function NotEmpty<T extends unknown[] | Record<any, unknown>>({ on, display, whenEmpty }: NotEmptyProps<T>): JSX.DOMNode;
@@ -101,7 +101,7 @@ export class RepeatImpl {
101
101
  index: i
102
102
  });
103
103
  }
104
- for (let i = clears.length - 1; i < newCount; i++) {
104
+ for (let i = clears.length; i < newCount; i++) {
105
105
  positions[i] = new Prop(makePosition(i, count));
106
106
  clears[i] = makeRenderable(this.children(positions[i])).appendTo(newCtx);
107
107
  if (i < newCount - 1) {
@@ -1,20 +1,15 @@
1
1
  /** @jsxImportSource .. */
2
2
  import { type Signal } from '../prop';
3
- import { type Renderable } from '../renderable';
4
3
  import { type JSX } from '../jsx';
5
- import { type Clear } from '../clean';
6
- import { type DOMContext } from '../dom-context';
4
+ import { OneOfImpl } from './OneOf';
7
5
  export type Condition<T> = Signal<T | null | undefined> | Signal<T | undefined> | Signal<T | null> | Signal<T>;
8
- export declare class ShowImpl<T> implements Renderable {
9
- private readonly on;
10
- private readonly otherwise;
11
- private readonly children;
12
- constructor(on: Condition<T>, otherwise: JSX.DOMNode, children: (value: Signal<NonNullable<T>>) => JSX.DOMNode);
13
- readonly appendTo: (ctx: DOMContext) => Clear;
14
- }
15
6
  export interface ShowProps<T> {
16
7
  when: Condition<T>;
17
- otherwise?: JSX.DOMNode;
8
+ otherwise?: () => JSX.DOMNode;
18
9
  children?: (value: Signal<NonNullable<T>>) => JSX.DOMNode;
19
10
  }
20
- export declare function Show<T>({ when, children, otherwise }: ShowProps<T>): ShowImpl<T>;
11
+ export declare function Show<T>({ when, children, otherwise }: ShowProps<T>): OneOfImpl<{
12
+ then: NonNullable<T>;
13
+ } | {
14
+ otherwise: false;
15
+ }>;
@@ -1,22 +1,8 @@
1
- import { jsx as _jsx, Fragment as _Fragment } from "../jsx-runtime";
2
- import { If } from './If';
3
- import { makeRenderable } from '../jsx-runtime';
4
- export class ShowImpl {
5
- on;
6
- otherwise;
7
- children;
8
- constructor(on, otherwise, children) {
9
- this.on = on;
10
- this.otherwise = otherwise;
11
- this.children = children;
12
- }
13
- appendTo = (ctx) => {
14
- const condition = this.on.map(v => v != null);
15
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
- const el = makeRenderable(_jsx(If, { is: condition, then: this.children(this.on), otherwise: this.otherwise }));
17
- return el.appendTo(ctx);
18
- };
19
- }
1
+ import { Fragment as _Fragment, jsx as _jsx } from "../jsx-runtime";
2
+ import { OneOfImpl } from './OneOf';
20
3
  export function Show({ when, children, otherwise }) {
21
- return new ShowImpl(when, otherwise, children ?? (() => _jsx(_Fragment, {})));
4
+ return new OneOfImpl(when.map(v => (v != null ? { then: v } : { otherwise: false })), {
5
+ then: (v) => ((children && children(v)) || _jsx(_Fragment, {})),
6
+ otherwise: otherwise || (() => _jsx(_Fragment, {}))
7
+ });
22
8
  }
@@ -13,7 +13,7 @@ function shouldNotApplyCallback(e, checkExtension, checkExternalUrl) {
13
13
  }
14
14
  // If there is a target and it is not `_self` then we take this
15
15
  // as a signal that it doesn't want to be intercepted.
16
- if (anchor.target !== '_self') {
16
+ if (anchor.target !== '_self' && anchor.target !== '') {
17
17
  return true;
18
18
  }
19
19
  if (anchor.getAttribute('download') != null) {
package/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export { handleTextInput } from './helpers/handle-text-input';
8
8
  export { handleAnchorClick } from './helpers/handle-anchor-click';
9
9
  export { type Animatable, applyInterpolatedAnimatableProp, applyInterpolatedAnimatable, applyAnimatableProp, applyAnimatable, getComputedAnimatableProp, getComputedAnimatable } from './components/animatable';
10
10
  export { AttributeImpl, Attribute, type AttributeProps } from './components/Attribute';
11
+ export { Autofocus } from './components/Autofocus';
11
12
  export { BooleanAttributeImpl, BooleanAttribute, type BooleanAttributeProps } from './components/BooleanAttribute';
12
13
  export { ClassNameImpl, ClassName, type ClassNameProps } from './components/ClassName';
13
14
  export { ConsumerImpl, Consumer, type ConsumerProps, ProviderImpl, Provider, type ProviderProps } from './components/Provider';
@@ -27,7 +28,7 @@ export { OneOfImpl, OneOf, type OneOfProps, OneOfLiteral, type OneOfLiteralProps
27
28
  export { PortalImpl, Portal, type PortalProps } from './components/Portal';
28
29
  export { PropertyImpl, Property, type PropertyProps } from './components/Property';
29
30
  export { RepeatImpl, Repeat, type RepeatProps, conjuctions, type PositionProps } from './components/Repeat';
30
- export { ShowImpl, Show, type ShowProps } from './components/Show';
31
+ export { Show, type ShowProps } from './components/Show';
31
32
  export { TextImpl, Text, type TextProps } from './components/Text';
32
33
  export { TextContentImpl, TextContent, type TextContentProps } from './components/TextContent';
33
34
  export type { JSX } from './jsx-runtime';
package/index.js CHANGED
@@ -6,6 +6,7 @@ export { handleTextInput } from './helpers/handle-text-input';
6
6
  export { handleAnchorClick } from './helpers/handle-anchor-click';
7
7
  export { applyInterpolatedAnimatableProp, applyInterpolatedAnimatable, applyAnimatableProp, applyAnimatable, getComputedAnimatableProp, getComputedAnimatable } from './components/animatable';
8
8
  export { AttributeImpl, Attribute } from './components/Attribute';
9
+ export { Autofocus } from './components/Autofocus';
9
10
  export { BooleanAttributeImpl, BooleanAttribute } from './components/BooleanAttribute';
10
11
  export { ClassNameImpl, ClassName } from './components/ClassName';
11
12
  export { ConsumerImpl, Consumer, ProviderImpl, Provider } from './components/Provider';
@@ -25,6 +26,6 @@ export { OneOfImpl, OneOf, OneOfLiteral, OneOfUnion, OneOfUnionKind, OneOfUnionT
25
26
  export { PortalImpl, Portal } from './components/Portal';
26
27
  export { PropertyImpl, Property } from './components/Property';
27
28
  export { RepeatImpl, Repeat, conjuctions } from './components/Repeat';
28
- export { ShowImpl, Show } from './components/Show';
29
+ export { Show } from './components/Show';
29
30
  export { TextImpl, Text } from './components/Text';
30
31
  export { TextContentImpl, TextContent } from './components/TextContent';
package/package.json CHANGED
@@ -2,32 +2,7 @@
2
2
  "name": "@tempots/dom",
3
3
  "main": "index.js",
4
4
  "types": "index.d.ts",
5
- "version": "7.1.3",
6
- "scripts": {
7
- "watch": "tsc --watch",
8
- "build": "tsc",
9
- "test": "jest",
10
- "test:watch": "jest --watch",
11
- "coverage": "jest --coverage",
12
- "npm:prep": "yarn build && cp README.md package.json dist",
13
- "npm:publish": "yarn npm:prep && (cd dist && yarn publish --access public)"
14
- },
15
- "dependencies": {},
16
- "devDependencies": {
17
- "@happy-dom/jest-environment": "^9.1.7",
18
- "@types/jest": "^29.5.0",
19
- "@types/node": "^18.15.11",
20
- "@typescript-eslint/eslint-plugin": "^5.43.0",
21
- "eslint": "^8.0.1",
22
- "eslint-config-standard-with-typescript": "^34.0.1",
23
- "eslint-plugin-import": "^2.25.2",
24
- "eslint-plugin-n": "^15.0.0",
25
- "eslint-plugin-promise": "^6.0.0",
26
- "happy-dom": "^9.1.0",
27
- "jest": "^29.5.0",
28
- "ts-jest": "^29.1.0",
29
- "typescript": "^5.0.3"
30
- },
5
+ "version": "9.0.0",
31
6
  "repository": {
32
7
  "type": "git",
33
8
  "url": "git+https://github.com/fponticelli/tempots-dom.git"
package/prop.d.ts CHANGED
@@ -8,10 +8,11 @@ export declare class Signal<T> {
8
8
  static ofValue<T>(value: Value<T> | null | undefined): Signal<T> | undefined;
9
9
  static wrap<T>(value: T | Signal<T>): Signal<T>;
10
10
  static isSignal<T = unknown>(x: unknown): x is Signal<T>;
11
+ static unwrap<T>(value: Value<T>): T;
11
12
  /**
12
13
  * Combines many into one using a merging function
13
14
  */
14
- static combine<Args extends [...unknown[]], Out>(others: ArgsToSignals<Args>, f: (...args: Args) => Out): Signal<Out>;
15
+ static combine<Args extends [...unknown[]], Out>(signals: ArgsToSignals<Args>, f: (...args: Args) => Out): Signal<Out>;
15
16
  readonly [$isSignal] = true;
16
17
  protected readonly _listeners: Array<(value: T) => void>;
17
18
  constructor(_value: T);
@@ -19,6 +20,7 @@ export declare class Signal<T> {
19
20
  readonly subscribe: (listener: (value: T) => void) => () => void;
20
21
  readonly map: <V>(f: (value: T) => V) => Signal<V>;
21
22
  readonly flatMap: <V>(f: (value: T) => Signal<V>) => Signal<V>;
23
+ readonly flatMapProp: <V>(f: (value: T) => Prop<V>) => Prop<V>;
22
24
  readonly tap: (f: (value: T) => void) => this;
23
25
  readonly at: <K extends keyof T>(key: K) => Signal<T[K]>;
24
26
  readonly filter: (predicate: (value: T) => boolean) => Signal<T>;
@@ -26,11 +28,16 @@ export declare class Signal<T> {
26
28
  readonly mapAsync: <V>(f: (value: T) => Promise<V>, alt: V) => Signal<V>;
27
29
  readonly mapMaybe: <V>(f: (value: T) => V | null | undefined, alt: V) => Signal<V>;
28
30
  readonly combine: <V, Z>(other: Signal<V>, f: (a: T, b: V) => Z) => Signal<Z>;
29
- readonly feed: (prop: Prop<T>) => Prop<T>;
31
+ readonly feed: (prop: Prop<T>) => () => void;
30
32
  readonly deriveProp: () => Prop<T>;
31
33
  readonly clean: () => void;
32
34
  readonly count: () => Signal<number>;
33
35
  readonly animate: (duration: number, interpolate: (start: T, end: T, delta: number) => T, initialValue?: T | null, easing?: (t: number) => number) => Signal<T>;
36
+ readonly equals: (other: Signal<T>, equality?: ((a: T, b: T) => boolean) | undefined) => Signal<boolean>;
37
+ readonly isNull: () => Signal<boolean>;
38
+ readonly isNotNull: () => Signal<boolean>;
39
+ readonly isEmpty: () => Signal<boolean>;
40
+ readonly isNotEmpty: () => Signal<boolean>;
34
41
  }
35
42
  export declare class Prop<T> extends Signal<T> {
36
43
  static isProp<T = unknown>(x: unknown): x is Prop<T>;
package/prop.js CHANGED
@@ -15,17 +15,20 @@ export class Signal {
15
15
  const s = x;
16
16
  return s != null && typeof s.get === 'function' && typeof s.subscribe === 'function';
17
17
  }
18
+ static unwrap(value) {
19
+ return (Signal.isSignal(value) ? value.get() : value);
20
+ }
18
21
  /**
19
22
  * Combines many into one using a merging function
20
23
  */
21
- static combine(others, f) {
24
+ static combine(signals, f) {
22
25
  function getValues(others) {
23
26
  return others.map(other => other.get());
24
27
  }
25
- const prop = new Prop(f(...getValues(others)));
26
- others.forEach((other) => {
28
+ const prop = new Prop(f(...getValues(signals)));
29
+ signals.forEach((other) => {
27
30
  other.subscribe(() => {
28
- prop.set(f(...getValues(others)));
31
+ prop.set(f(...getValues(signals)));
29
32
  });
30
33
  });
31
34
  return prop;
@@ -62,6 +65,18 @@ export class Signal {
62
65
  });
63
66
  return prop;
64
67
  };
68
+ flatMapProp = (f) => {
69
+ let tprop = f(this._value);
70
+ const prop = Prop.of(tprop.get());
71
+ let cancel = prop.feed(tprop);
72
+ this.subscribe(value => {
73
+ cancel();
74
+ tprop = f(value);
75
+ prop.set(tprop.get());
76
+ cancel = prop.feed(tprop);
77
+ });
78
+ return prop;
79
+ };
65
80
  tap = (f) => {
66
81
  f(this._value);
67
82
  this.subscribe(f);
@@ -128,11 +143,12 @@ export class Signal {
128
143
  return prop;
129
144
  };
130
145
  feed = (prop) => {
131
- this.subscribe(value => { prop.set(value); });
132
- return prop;
146
+ return this.subscribe(value => { prop.set(value); });
133
147
  };
134
148
  deriveProp = () => {
135
- return new Prop(this._value);
149
+ const prop = new Prop(this._value);
150
+ this.feed(prop);
151
+ return prop;
136
152
  };
137
153
  clean = () => {
138
154
  this._listeners.length = 0;
@@ -178,6 +194,17 @@ export class Signal {
178
194
  });
179
195
  return prop;
180
196
  };
197
+ equals = (other, equality) => {
198
+ return this.combine(other, (a, b) => {
199
+ if (equality != null)
200
+ return equality(a, b);
201
+ return a === b;
202
+ });
203
+ };
204
+ isNull = () => this.map(value => value == null);
205
+ isNotNull = () => this.map(value => value != null);
206
+ isEmpty = () => this.map(value => value == null || (Reflect.has(value, 'length') && Reflect.get(value, 'length') === 0));
207
+ isNotEmpty = () => this.map(value => value != null && (!Reflect.has(value, 'length') || Reflect.get(value, 'length') !== 0));
181
208
  }
182
209
  export class Prop extends Signal {
183
210
  static isProp(x) {
@@ -1,33 +0,0 @@
1
- import { type Signal } from '../prop';
2
- import { type DOMContext } from '../dom-context';
3
- import { type AnyKey } from './OneOf';
4
- import { type JSX } from '../jsx-runtime';
5
- import { type Clear } from '../clean';
6
- export declare class MatchImpl<T extends {
7
- [_ in K]: any;
8
- }, K extends keyof T> {
9
- private readonly on;
10
- private readonly using;
11
- private readonly matches;
12
- constructor(on: Signal<T>, using: K, matches: {
13
- [KIND in T[K]]: (_: Signal<T & {
14
- [KK in K]: KIND extends T[KK] ? KIND : never;
15
- }>) => JSX.DOMNode;
16
- });
17
- readonly appendTo: (ctx: DOMContext) => Clear;
18
- }
19
- export type MatchProps<T extends {
20
- [_ in K]: AnyKey;
21
- }, K extends keyof T> = {
22
- on: Signal<T>;
23
- using: K;
24
- } & {
25
- matches: {
26
- [KIND in T[K]]: (_: Signal<T & {
27
- [KK in K]: KIND extends T[KK] ? KIND : never;
28
- }>) => JSX.DOMNode;
29
- };
30
- };
31
- export declare function Match<T extends {
32
- [_ in K]: AnyKey;
33
- }, K extends keyof T>({ on, using, matches }: MatchProps<T, K>): JSX.DOMNode;
@@ -1,44 +0,0 @@
1
- import { makeRenderable } from '../jsx-runtime';
2
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3
- export class MatchImpl {
4
- on;
5
- using;
6
- matches;
7
- constructor(on, using, matches) {
8
- this.on = on;
9
- this.using = using;
10
- this.matches = matches;
11
- }
12
- appendTo = (ctx) => {
13
- let newCtx = ctx.makeReference();
14
- const value = this.on.get();
15
- let key = value[this.using];
16
- let derived = this.on.map(v => v);
17
- let renderable = makeRenderable(this.matches[key](derived));
18
- let clear = renderable.appendTo(newCtx);
19
- const cancel = this.on.subscribe(newValue => {
20
- const newKey = newValue[this.using];
21
- if (newKey === key)
22
- return;
23
- newCtx.requestClear(true, () => {
24
- clear(true);
25
- derived.clean();
26
- key = newKey;
27
- derived = this.on.map(v => v);
28
- newCtx = newCtx.makeReference();
29
- renderable = makeRenderable(this.matches[key](derived));
30
- clear = renderable.appendTo(newCtx);
31
- });
32
- });
33
- return (removeTree) => {
34
- newCtx.requestClear(removeTree, () => {
35
- cancel();
36
- derived.clean();
37
- clear(removeTree);
38
- });
39
- };
40
- };
41
- }
42
- export function Match({ on, using, matches }) {
43
- return new MatchImpl(on, using, matches);
44
- }
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,75 +0,0 @@
1
- /** @jsxImportSource .. */
2
- import { type Renderable } from '../types/renderable';
3
- import { type Clear } from '../types/clean';
4
- import { type DOMContext } from '../dom-context';
5
- export interface Animatable {
6
- width?: number;
7
- maxWidth?: number;
8
- minWidth?: number;
9
- height?: number;
10
- maxHeight?: number;
11
- minHeight?: number;
12
- lineHeight?: number;
13
- opacity?: number;
14
- top?: number;
15
- left?: number;
16
- right?: number;
17
- bottom?: number;
18
- padding?: number;
19
- paddingTop?: number;
20
- paddingBottom?: number;
21
- paddingLeft?: number;
22
- paddingRight?: number;
23
- margin?: number;
24
- marginTop?: number;
25
- marginBottom?: number;
26
- marginLeft?: number;
27
- marginRight?: number;
28
- fontSize?: number;
29
- letterSpacing?: number;
30
- borderWidth?: number;
31
- borderRadius?: number;
32
- translateX?: number;
33
- translateY?: number;
34
- translateZ?: number;
35
- rotateX?: number;
36
- rotateY?: number;
37
- rotateZ?: number;
38
- scaleX?: number;
39
- scaleY?: number;
40
- scaleZ?: number;
41
- skewX?: number;
42
- skewY?: number;
43
- grayScale?: number;
44
- sepia?: number;
45
- saturate?: number;
46
- hueRotate?: number;
47
- invert?: number;
48
- brightness?: number;
49
- contrast?: number;
50
- blur?: number;
51
- }
52
- export interface TweenAnimation {
53
- style: Animatable;
54
- duration?: number;
55
- delay?: number;
56
- }
57
- export interface TweenProps {
58
- enter?: TweenAnimation[];
59
- exit?: TweenAnimation[];
60
- style?: Animatable;
61
- }
62
- export declare function getComputedStyleValue(styles: CSSStyleDeclaration, key: keyof Animatable): Animatable[typeof key];
63
- export declare function getCurrentStyleValues(el: HTMLElement, styles: Animatable): Animatable;
64
- export declare function applyStyle(el: HTMLElement, key: keyof Animatable, value: Animatable[typeof key]): void;
65
- export declare function applyInterpolatedStyle(el: HTMLElement, key: keyof Animatable, from: Animatable[typeof key], to: Animatable[typeof key], progress: number): void;
66
- export declare function applyInterpolatedStyles(el: HTMLElement, from: Animatable, to: Animatable, progress: number): void;
67
- export declare function applyStyles(el: HTMLElement, styles: Animatable): void;
68
- export declare class TweenImpl implements Renderable {
69
- private readonly enter;
70
- private readonly exit;
71
- private readonly style?;
72
- constructor(enter?: TweenAnimation[], exit?: TweenAnimation[], style?: Animatable | undefined);
73
- appendTo(ctx: DOMContext): Clear;
74
- }
75
- export declare function Tween({ enter, exit, style }: TweenProps): TweenImpl;
@@ -1,242 +0,0 @@
1
- export function getComputedStyleValue(styles, key) {
2
- if (key === 'translateX') {
3
- return new WebKitCSSMatrix(styles.transform).m41;
4
- }
5
- else if (key === 'translateY') {
6
- return new WebKitCSSMatrix(styles.transform).m42;
7
- }
8
- else if (key === 'translateZ') {
9
- return new WebKitCSSMatrix(styles.transform).m43;
10
- }
11
- else if (key === 'rotateX') {
12
- return new WebKitCSSMatrix(styles.transform).m12;
13
- }
14
- else if (key === 'rotateY') {
15
- return new WebKitCSSMatrix(styles.transform).m21;
16
- }
17
- else if (key === 'rotateZ') {
18
- return new WebKitCSSMatrix(styles.transform).m31;
19
- }
20
- else if (key === 'scaleX') {
21
- return new WebKitCSSMatrix(styles.transform).m11;
22
- }
23
- else if (key === 'scaleY') {
24
- return new WebKitCSSMatrix(styles.transform).m22;
25
- }
26
- else if (key === 'scaleZ') {
27
- return new WebKitCSSMatrix(styles.transform).m33;
28
- }
29
- else if (key === 'skewX') {
30
- return new WebKitCSSMatrix(styles.transform).m13;
31
- }
32
- else if (key === 'skewY') {
33
- return new WebKitCSSMatrix(styles.transform).m23;
34
- }
35
- else if (key === 'grayScale') {
36
- return Number(styles.filter.match(/grayscale\((\d+)%\)/)?.[1]);
37
- }
38
- else if (key === 'sepia') {
39
- return Number(styles.filter.match(/sepia\((\d+)%\)/)?.[1]);
40
- }
41
- else if (key === 'saturate') {
42
- return Number(styles.filter.match(/saturate\((\d+)%\)/)?.[1]);
43
- }
44
- else if (key === 'hueRotate') {
45
- return Number(styles.filter.match(/hue-rotate\((\d+)deg\)/)?.[1]);
46
- }
47
- else if (key === 'invert') {
48
- return Number(styles.filter.match(/invert\((\d+)%\)/)?.[1]);
49
- }
50
- else if (key === 'brightness') {
51
- return Number(styles.filter.match(/brightness\((\d+)%\)/)?.[1]);
52
- }
53
- else if (key === 'contrast') {
54
- return Number(styles.filter.match(/contrast\((\d+)%\)/)?.[1]);
55
- }
56
- else if (key === 'blur') {
57
- return Number(styles.filter.match(/blur\((\d+)px\)/)?.[1]);
58
- }
59
- return Number(styles.getPropertyValue(key));
60
- }
61
- export function getCurrentStyleValues(el, styles) {
62
- const result = {};
63
- const computedStyles = getComputedStyle(el);
64
- for (const [key, value] of Object.entries(styles)) {
65
- const k = key;
66
- if (value != null) {
67
- result[k] = getComputedStyleValue(computedStyles, k);
68
- }
69
- }
70
- return result;
71
- }
72
- export function applyStyle(el, key, value) {
73
- if (value == null)
74
- return;
75
- if (key === 'translateX') {
76
- el.style.transform += ` translateX(${value}px)`;
77
- }
78
- else if (key === 'translateY') {
79
- el.style.transform += ` translateY(${value}px)`;
80
- }
81
- else if (key === 'translateZ') {
82
- el.style.transform += ` translateZ(${value}px)`;
83
- }
84
- else if (key === 'rotateX') {
85
- el.style.transform += ` rotateX(${value}deg)`;
86
- }
87
- else if (key === 'rotateY') {
88
- el.style.transform += ` rotateY(${value}deg)`;
89
- }
90
- else if (key === 'rotateZ') {
91
- el.style.transform += ` rotateZ(${value}deg)`;
92
- }
93
- else if (key === 'scaleX') {
94
- el.style.transform += ` scaleX(${value})`;
95
- }
96
- else if (key === 'scaleY') {
97
- el.style.transform += ` scaleY(${value})`;
98
- }
99
- else if (key === 'scaleZ') {
100
- el.style.transform += ` scaleZ(${value})`;
101
- }
102
- else if (key === 'skewX') {
103
- el.style.transform += ` skewX(${value}deg)`;
104
- }
105
- else if (key === 'skewY') {
106
- el.style.transform += ` skewY(${value}deg)`;
107
- }
108
- else if (key === 'grayScale') {
109
- el.style.filter += ` grayscale(${value}%)`;
110
- }
111
- else if (key === 'sepia') {
112
- el.style.filter += ` sepia(${value}%)`;
113
- }
114
- else if (key === 'saturate') {
115
- el.style.filter += ` saturate(${value}%)`;
116
- }
117
- else if (key === 'hueRotate') {
118
- el.style.filter += ` hue-rotate(${value}deg)`;
119
- }
120
- else if (key === 'invert') {
121
- el.style.filter += ` invert(${value}%)`;
122
- }
123
- else if (key === 'brightness') {
124
- el.style.filter += ` brightness(${value}%)`;
125
- }
126
- else if (key === 'contrast') {
127
- el.style.filter += ` contrast(${value}%)`;
128
- }
129
- else if (key === 'blur') {
130
- el.style.filter += ` blur(${value}px)`;
131
- }
132
- el.style.setProperty(key, String(value));
133
- }
134
- export function applyInterpolatedStyle(el, key, from, to, progress) {
135
- if (from != null && to != null) {
136
- const value = from + (to - from) * progress;
137
- applyStyle(el, key, value);
138
- }
139
- }
140
- export function applyInterpolatedStyles(el, from, to, progress) {
141
- el.style.transform = '';
142
- el.style.filter = '';
143
- for (const [key, value] of Object.entries(to)) {
144
- const k = key;
145
- applyInterpolatedStyle(el, k, from[k], value, progress);
146
- }
147
- }
148
- export function applyStyles(el, styles) {
149
- el.style.transform = '';
150
- el.style.filter = '';
151
- for (const [key, value] of Object.entries(styles)) {
152
- if (value != null) {
153
- applyStyle(el, key, value);
154
- }
155
- }
156
- }
157
- export class TweenImpl {
158
- enter;
159
- exit;
160
- style;
161
- constructor(enter = [], exit = [], style) {
162
- this.enter = enter;
163
- this.exit = exit;
164
- this.style = style;
165
- }
166
- appendTo(ctx) {
167
- const element = ctx.getElement();
168
- let currentAnimation = 0;
169
- let startTime = 0;
170
- let animation = null;
171
- let from = null;
172
- let willClear = null;
173
- // let unmounted = false
174
- let animations = this.enter;
175
- const { exit, style } = this;
176
- function frame() {
177
- // if (unmounted) return
178
- if (animation == null || from == null)
179
- return;
180
- const now = Date.now();
181
- const elapsed = now - startTime;
182
- const { duration = 250, delay = 0 } = animation;
183
- if (elapsed < delay)
184
- return;
185
- const progress = Math.min(1, (elapsed - delay) / duration);
186
- applyInterpolatedStyles(element, from, animation.style, progress);
187
- // console.log(
188
- // element.style.opacity,
189
- // // getComputedStyleValue(getComputedStyle(element), 'translateY')
190
- // )
191
- if (progress >= 1) {
192
- if (exit === animations) {
193
- console.log('exit');
194
- willClear?.();
195
- }
196
- else {
197
- console.log('play next');
198
- playNextAnimation();
199
- }
200
- }
201
- else {
202
- requestAnimationFrame(frame);
203
- }
204
- }
205
- function playNextAnimation() {
206
- if (currentAnimation >= animations.length)
207
- return;
208
- startTime = Date.now();
209
- animation = animations[currentAnimation];
210
- if (currentAnimation === 0 && style != null && animations !== exit) {
211
- applyStyles(element, style);
212
- from = style;
213
- console.log('playNextAnimation from style', currentAnimation, from, animation.style);
214
- }
215
- else {
216
- from = getCurrentStyleValues(element, animation.style);
217
- console.log('playNextAnimation from empty', currentAnimation, from, animation.style);
218
- }
219
- requestAnimationFrame(frame);
220
- currentAnimation++;
221
- }
222
- playNextAnimation();
223
- return (clearTree) => {
224
- console.log('onUnmount');
225
- animations = exit;
226
- // unmounted = true
227
- currentAnimation = 0;
228
- ctx.delayClear(clearTree, (clear) => {
229
- console.log('perform clear');
230
- willClear = () => {
231
- console.log('finalize clear');
232
- animations = [];
233
- clear();
234
- };
235
- playNextAnimation();
236
- });
237
- };
238
- }
239
- }
240
- export function Tween({ enter, exit, style }) {
241
- return new TweenImpl(enter, exit, style);
242
- }
package/types/clean.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export type Clear = (removeTree: boolean) => void;
2
- export type Clean = () => void;
package/types/clean.js DELETED
@@ -1 +0,0 @@
1
- export {};
@@ -1,27 +0,0 @@
1
- import { type Clear } from './clean';
2
- export type ProviderMark<T> = symbol;
3
- export declare function makeProviderMark<T>(): ProviderMark<T>;
4
- export interface IDOMContext {
5
- makeReference: () => IDOMContext;
6
- makeElement: (tagName: string) => IDOMContext;
7
- getBooleanAttribute: (name: string) => boolean;
8
- setBooleanAttribute: (name: string, value: boolean) => void;
9
- createBooleanAttribute: (name: string, value: boolean) => [(newValue: boolean) => void, Clear];
10
- getAttribute: (name: string) => string | null;
11
- setAttribute: (name: string, value: string | null) => void;
12
- createAttribute: (name: string, value: string) => [(newValue: string) => void, Clear];
13
- getProperty: <T>(name: string) => T;
14
- setProperty: <T>(name: string, value: T) => void;
15
- createProperty: <T>(name: string, value: T) => [(newValue: T) => void, Clear];
16
- createText: (text: string) => [(newText: string) => void, Clear];
17
- createClass: (cls: string) => [(newClass: string) => void, Clear];
18
- createHandler: <T>(name: string, handler: (value: T) => void) => Clear;
19
- delayClear: (removeTree: boolean, f: (finalize: () => void) => void) => void;
20
- requestClear: (removeTree: boolean, willClear: () => void) => void;
21
- getElement: () => HTMLElement;
22
- getDocument: () => Document;
23
- withProvider: <T>(mark: ProviderMark<T>, provider: T) => IDOMContext;
24
- getProvider: <T>(mark: ProviderMark<T>) => T;
25
- setStyle: (name: string, value: string | undefined | null) => void;
26
- createStyle: (name: string, value: string | undefined | null) => [(newValue: string) => void, Clear];
27
- }
@@ -1,3 +0,0 @@
1
- export function makeProviderMark() {
2
- return Symbol('providerMark');
3
- }
@@ -1,5 +0,0 @@
1
- import { type DOMContext } from '../dom-context';
2
- import { type Clear } from './clean';
3
- export interface Renderable {
4
- appendTo: (ctx: DOMContext) => Clear;
5
- }
@@ -1 +0,0 @@
1
- export {};