hyperapp-is 0.1.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.
package/README.npm.md ADDED
@@ -0,0 +1,107 @@
1
+ # hyperapp-is
2
+
3
+ Lightweight. Declarative. Composable.
4
+
5
+ Reusable component foundation library for Hyperapp v2.
6
+
7
+ State-structure independent design + RAF-based animation system.
8
+
9
+ ---
10
+
11
+ ## Features
12
+
13
+ - State-path based reusable component design
14
+ - Local state helpers
15
+ `getLocalState`, `setLocalState`, `createLocalKey`
16
+ - Action composition utility
17
+ `concatAction`
18
+ - Class / props utilities
19
+ `getClassList`, `deleteKeys`
20
+ - requestAnimationFrame task system
21
+ `RAFTask`, `subscription_RAFManager`
22
+ - Built-in animated Carousel component
23
+
24
+ ---
25
+
26
+ ## Installation
27
+
28
+ ``` bash
29
+ npm install hyperapp-is
30
+ ```
31
+
32
+ Peer dependencies:
33
+
34
+ - hyperapp v2
35
+ - hyperapp-jsx-pragma (when using JSX)
36
+
37
+ ---
38
+
39
+ ## Basic Usage (Carousel Example)
40
+
41
+ ``` ts
42
+ import { app } from "hyperapp"
43
+ import h from "hyperapp-jsx-pragma"
44
+ import {
45
+ RAFTask, subscription_RAFManager,
46
+ Carousel, effect_InitCarousel
47
+ } from "hyperapp-is"
48
+
49
+ interface State {
50
+ tasks: RAFTask<State>[]
51
+ }
52
+
53
+ const initState: State = {
54
+ tasks: []
55
+ }
56
+
57
+ app({
58
+ node: document.getElementById("app") as HTMLElement,
59
+ init: [initState, effect_InitCarousel(["tasks"], {
60
+ id : "carousel",
61
+ duration: 2000,
62
+ delay : 1000,
63
+ step : 1
64
+ })],
65
+
66
+ subscriptions: (state) => [
67
+ subscription_RAFManager(state, ["tasks"])
68
+ ],
69
+
70
+ view: (state) => (<Carousel
71
+ state = { state }
72
+ id = "carousel"
73
+ keyNames = { ["tasks"] }
74
+ >
75
+ <div>Slide 1</div>
76
+ <div>Slide 2</div>
77
+ <div>Slide 3</div>
78
+ </Carousel>)
79
+ })
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Concept
85
+
86
+ hyperapp-is allows components to:
87
+
88
+ - Remain independent from root state structure
89
+ - Store internal state without polluting user state
90
+ - Compose actions safely
91
+ - Manage animations declaratively via RAFTask
92
+
93
+ Designed for building reusable UI components on top of Hyperapp.
94
+
95
+ ---
96
+
97
+ ## Documentation
98
+
99
+ Full documentation and detailed design notes are available on GitHub:
100
+
101
+ https://github.com/is4416/hyperapp-is
102
+
103
+ ---
104
+
105
+ ## License
106
+
107
+ MIT
@@ -0,0 +1,15 @@
1
+ export declare const progress_easing: {
2
+ linear: (t: number) => number;
3
+ easeInQuad: (t: number) => number;
4
+ easeOutQuad: (t: number) => number;
5
+ easeInOutQuad: (t: number) => number;
6
+ easeInCubic: (t: number) => number;
7
+ easeOutCubic: (t: number) => number;
8
+ easeInOutCubic: (t: number) => number;
9
+ easeInQuart: (t: number) => number;
10
+ easeOutQuart: (t: number) => number;
11
+ easeInOutQuart: (t: number) => number;
12
+ easeOutBack: (t: number) => number;
13
+ easeOutBounce: (t: number) => number;
14
+ easeOutElastic: (t: number) => number;
15
+ };
@@ -0,0 +1,57 @@
1
+ // hyperapp-ui / animation / easing.ts
2
+ // ---------- ---------- ---------- ---------- ----------
3
+ // progress_easing
4
+ // ---------- ---------- ---------- ---------- ----------
5
+ export const progress_easing = {
6
+ // basic
7
+ linear: (t) => t,
8
+ easeInQuad: (t) => t * t,
9
+ easeOutQuad: (t) => 1 - (1 - t) * (1 - t),
10
+ easeInOutQuad: (t) => t < 0.5
11
+ ? 2 * t * t
12
+ : 1 - Math.pow(-2 * t + 2, 2) / 2,
13
+ // cubic
14
+ easeInCubic: (t) => t * t * t,
15
+ easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
16
+ easeInOutCubic: (t) => t < 0.5
17
+ ? 4 * t * t * t
18
+ : 1 - Math.pow(-2 * t + 2, 3) / 2,
19
+ // quart
20
+ easeInQuart: (t) => t * t * t * t,
21
+ easeOutQuart: (t) => 1 - Math.pow(1 - t, 4),
22
+ easeInOutQuart: (t) => t < 0.5
23
+ ? 8 * t * t * t * t
24
+ : 1 - Math.pow(-2 * t + 2, 4) / 2,
25
+ // back (跳ねる)
26
+ easeOutBack: (t) => {
27
+ const c1 = 1.70158;
28
+ const c3 = c1 + 1;
29
+ return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
30
+ },
31
+ // bounce
32
+ easeOutBounce: (t) => {
33
+ const n1 = 7.5625;
34
+ const d1 = 2.75;
35
+ if (t < 1 / d1) {
36
+ return n1 * t * t;
37
+ }
38
+ else if (t < 2 / d1) {
39
+ return n1 * (t -= 1.5 / d1) * t + 0.75;
40
+ }
41
+ else if (t < 2.5 / d1) {
42
+ return n1 * (t -= 2.25 / d1) * t + 0.9375;
43
+ }
44
+ else {
45
+ return n1 * (t -= 2.625 / d1) * t + 0.984375;
46
+ }
47
+ },
48
+ // elastic
49
+ easeOutElastic: (t) => {
50
+ const c4 = (2 * Math.PI) / 3;
51
+ return t === 0
52
+ ? 0
53
+ : t === 1
54
+ ? 1
55
+ : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
56
+ }
57
+ };
@@ -0,0 +1,5 @@
1
+ export type { InternalEffect, RAFEvent } from "./raf";
2
+ export type { CSSProperty } from "./properties";
3
+ export { RAFTask, subscription_RAFManager } from "./raf";
4
+ export { progress_easing } from "./easing";
5
+ export { createUnits, createRAFProperties, effect_RAFProperties } from "./properties";
@@ -0,0 +1,3 @@
1
+ export { RAFTask, subscription_RAFManager } from "./raf";
2
+ export { progress_easing } from "./easing";
3
+ export { createUnits, createRAFProperties, effect_RAFProperties } from "./properties";
@@ -0,0 +1,64 @@
1
+ import { Dispatch } from "hyperapp";
2
+ import { InternalEffect, RAFTask } from "./raf";
3
+ /**
4
+ * アニメーション進捗 (0〜1) を受け取り CSS 値を返す関数
5
+ *
6
+ * @type {Object.<string, Object.<string, (progress: number) => string>>} CSSProperty
7
+ * @property {Object.<string, (progress: number) => string>} [selector]
8
+ * @param {number} progress
9
+ */
10
+ export interface CSSProperty {
11
+ [selector: string]: {
12
+ [name: string]: (progress: number) => string;
13
+ };
14
+ }
15
+ /**
16
+ * CSSProperty[] から、doms と styles のセットに変換
17
+ *
18
+ * @param {CSSProperty[]} properties - プロパティ配列
19
+ * @returns {doms: HTMLElement[], styles:{ [name: string]: (progress: number) => string}}
20
+ */
21
+ export declare const createUnits: (properties: CSSProperty[]) => {
22
+ doms: HTMLElement[];
23
+ styles: {
24
+ [name: string]: (progress: number) => string;
25
+ };
26
+ }[];
27
+ /**
28
+ * subscription_RAFManager をベースにした CSS アニメーション RAFTask を作成する
29
+ * props は基本的に RAFTask の値
30
+ *
31
+ * @param {CSSProperty[]} props.properties - セレクタとスタイル設定のセット配列
32
+ */
33
+ export declare const createRAFProperties: <S>(props: {
34
+ id: string;
35
+ groupID?: string;
36
+ duration: number;
37
+ delay?: number;
38
+ finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>];
39
+ priority?: number;
40
+ extension?: {
41
+ [key: string]: any;
42
+ };
43
+ properties: CSSProperty[];
44
+ }) => RAFTask<S>;
45
+ /**
46
+ * subscription_RAFManager をベースにした CSS アニメーションエフェクト
47
+ * props は基本的に RAFTask の値
48
+ *
49
+ * @param {CSSProperty[]} props.properties - セレクタとスタイル設定のセット配列
50
+ * @param {string[]} props.keyNames - RAFTask 配列までのパス
51
+ */
52
+ export declare const effect_RAFProperties: <S>(props: {
53
+ id: string;
54
+ groupID?: string;
55
+ duration: number;
56
+ delay?: number;
57
+ finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>];
58
+ priority?: number;
59
+ extension?: {
60
+ [key: string]: any;
61
+ };
62
+ properties: CSSProperty[];
63
+ keyNames: string[];
64
+ }) => (dispatch: Dispatch<S>) => void;
@@ -0,0 +1,108 @@
1
+ // hyperapp-ui / animation / properties.ts
2
+ import { getValue, setValue } from "../core/state";
3
+ import { RAFTask } from "./raf";
4
+ // ---------- ---------- ---------- ---------- ----------
5
+ // createUnits
6
+ // ---------- ---------- ---------- ---------- ----------
7
+ /**
8
+ * CSSProperty[] から、doms と styles のセットに変換
9
+ *
10
+ * @param {CSSProperty[]} properties - プロパティ配列
11
+ * @returns {doms: HTMLElement[], styles:{ [name: string]: (progress: number) => string}}
12
+ */
13
+ export const createUnits = function (properties) {
14
+ return properties.map(p => {
15
+ const selector = Object.keys(p)[0];
16
+ return {
17
+ doms: Array.from(document.querySelectorAll(selector)),
18
+ styles: p[selector]
19
+ };
20
+ });
21
+ };
22
+ // ---------- ---------- ---------- ---------- ----------
23
+ // createRAFProperties
24
+ // ---------- ---------- ---------- ---------- ----------
25
+ /**
26
+ * subscription_RAFManager をベースにした CSS アニメーション RAFTask を作成する
27
+ * props は基本的に RAFTask の値
28
+ *
29
+ * @param {CSSProperty[]} props.properties - セレクタとスタイル設定のセット配列
30
+ */
31
+ export const createRAFProperties = function (props) {
32
+ const { id, groupID, duration, delay, priority, extension, properties } = props;
33
+ // action
34
+ const action = (state, rafTask) => {
35
+ var _a;
36
+ const progress = (_a = rafTask.progress) !== null && _a !== void 0 ? _a : 0;
37
+ const units = createUnits(properties);
38
+ // set styles
39
+ units.forEach(unit => {
40
+ for (const [name, fn] of Object.entries(unit.styles)) {
41
+ unit.doms.forEach(dom => dom.style.setProperty(name, fn(progress)));
42
+ }
43
+ });
44
+ return state;
45
+ };
46
+ // finish
47
+ const finish = (state, rafTask) => {
48
+ const units = createUnits(properties);
49
+ // release gpu layer
50
+ units.forEach(unit => {
51
+ unit.doms.forEach(dom => dom.style.willChange = "");
52
+ });
53
+ return [
54
+ state,
55
+ (dispatch) => {
56
+ const fn = props.finish;
57
+ if (fn) {
58
+ requestAnimationFrame(() => requestAnimationFrame(() => dispatch((state) => fn(state, rafTask))));
59
+ }
60
+ }
61
+ ];
62
+ };
63
+ return new RAFTask({
64
+ id, groupID, duration, delay,
65
+ action, finish,
66
+ priority,
67
+ extension: {
68
+ ...extension,
69
+ properties
70
+ }
71
+ });
72
+ };
73
+ // ---------- ---------- ---------- ---------- ----------
74
+ // effect_RAFProperties
75
+ // ---------- ---------- ---------- ---------- ----------
76
+ const GPU_LAYER = new Set(["transform", "opacity"]);
77
+ /**
78
+ * subscription_RAFManager をベースにした CSS アニメーションエフェクト
79
+ * props は基本的に RAFTask の値
80
+ *
81
+ * @param {CSSProperty[]} props.properties - セレクタとスタイル設定のセット配列
82
+ * @param {string[]} props.keyNames - RAFTask 配列までのパス
83
+ */
84
+ export const effect_RAFProperties = function (props) {
85
+ const { id, groupID, duration, delay, finish, priority, extension, properties, keyNames } = props;
86
+ // get doms
87
+ const units = createUnits(properties);
88
+ // set GPU Layer
89
+ units.forEach(unit => {
90
+ const val = [...new Set(Object.keys(unit.styles))].filter(name => GPU_LAYER.has(name)).join(",");
91
+ unit.doms.forEach(dom => dom.style.willChange = val);
92
+ });
93
+ // newTask
94
+ const newTask = createRAFProperties({
95
+ id, groupID, duration, delay, finish, priority, extension, properties
96
+ });
97
+ // set newTask
98
+ return (dispatch) => {
99
+ requestAnimationFrame(() => {
100
+ dispatch((state) => {
101
+ const tasks = getValue(state, keyNames, [])
102
+ .filter(task => task.id !== id)
103
+ .concat(newTask);
104
+ return setValue(state, keyNames, tasks);
105
+ });
106
+ });
107
+ };
108
+ };
@@ -0,0 +1,71 @@
1
+ import { Effect, Subscription } from "hyperapp";
2
+ /**
3
+ * 戻値としては返されないことを示したエフェクト
4
+ * Effect の型エイリアス
5
+ */
6
+ export type InternalEffect<S> = Effect<S>;
7
+ /**
8
+ * RAFTask の action, finish
9
+ * 型エイリアス
10
+ */
11
+ export type RAFEvent<S> = (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>];
12
+ declare const _isStart: unique symbol;
13
+ export declare class RAFTask<S> {
14
+ #private;
15
+ constructor(props: {
16
+ id: string;
17
+ groupID?: string;
18
+ duration: number;
19
+ delay?: number;
20
+ action: RAFEvent<S>;
21
+ finish?: RAFEvent<S>;
22
+ priority?: number;
23
+ extension?: {
24
+ [key: string]: any;
25
+ };
26
+ });
27
+ get id(): string;
28
+ get groupID(): string | undefined;
29
+ get duration(): number;
30
+ get delay(): number;
31
+ get action(): RAFEvent<S>;
32
+ get finish(): RAFEvent<S> | undefined;
33
+ get priority(): number;
34
+ get extension(): {
35
+ [key: string]: any;
36
+ };
37
+ get progress(): number;
38
+ get deltaTime(): number;
39
+ get isDone(): boolean;
40
+ get paused(): boolean;
41
+ set groupID(val: string | undefined);
42
+ set priority(val: number);
43
+ set extension(val: {
44
+ [key: string]: any;
45
+ });
46
+ set isDone(val: boolean);
47
+ set paused(val: boolean);
48
+ /**
49
+ * アクションを開始して良いか判定する
50
+ * 現在時間等のアップデートも同時に行われる
51
+ * subscription_RAFManager でのみ使用される
52
+ *
53
+ * @param {number} now - requestAnimatinFrame が返す絶対時間
54
+ * @returns {boolan} - アクションを実行して良いか判定
55
+ */
56
+ private [_isStart];
57
+ /**
58
+ * 時間を初期化したクローンを作成して返す
59
+ */
60
+ clone(): RAFTask<S>;
61
+ }
62
+ /**
63
+ * RAFTask 配列をフレームごとに実行するサブスクリプション
64
+ *
65
+ * @template S
66
+ * @param {S} state - ステート
67
+ * @param {string[]} keyNames - RAFTask 配列までのパス
68
+ * @returns {Subscription<S>}
69
+ */
70
+ export declare const subscription_RAFManager: <S>(state: S, keyNames: string[]) => Subscription<S>;
71
+ export {};
@@ -0,0 +1,202 @@
1
+ // hyperapp-ui / animation / raf.ts
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _RAFTask_id, _RAFTask_groupID, _RAFTask_duration, _RAFTask_delay, _RAFTask_action, _RAFTask_finish, _RAFTask_priority, _RAFTask_extension, _RAFTask_startTime, _RAFTask_currentTime, _RAFTask_pausedTime, _RAFTask_paused, _RAFTask_deltaTime, _RAFTask_isDone;
14
+ import { getValue, setValue } from "../core/state";
15
+ // ---------- ---------- ---------- ---------- ----------
16
+ // class RAFTask
17
+ // ---------- ---------- ---------- ---------- ----------
18
+ // Symbol
19
+ // subscription_RAFManager のみで使用される専用メソッド
20
+ // Symbol を知らない限り、モジュールの外からは呼べない
21
+ const _isStart = Symbol("RAFTask.isStart");
22
+ export class RAFTask {
23
+ // constructor
24
+ constructor(props) {
25
+ var _a, _b, _c;
26
+ // field
27
+ _RAFTask_id.set(this, void 0);
28
+ _RAFTask_groupID.set(this, void 0);
29
+ _RAFTask_duration.set(this, void 0);
30
+ _RAFTask_delay.set(this, void 0);
31
+ _RAFTask_action.set(this, void 0);
32
+ _RAFTask_finish.set(this, void 0);
33
+ _RAFTask_priority.set(this, void 0);
34
+ _RAFTask_extension.set(this, void 0);
35
+ _RAFTask_startTime.set(this, void 0);
36
+ _RAFTask_currentTime.set(this, void 0);
37
+ _RAFTask_pausedTime.set(this, void 0);
38
+ _RAFTask_paused.set(this, void 0);
39
+ _RAFTask_deltaTime.set(this, void 0);
40
+ _RAFTask_isDone.set(this, void 0);
41
+ __classPrivateFieldSet(this, _RAFTask_id, props.id, "f");
42
+ __classPrivateFieldSet(this, _RAFTask_groupID, props.groupID, "f");
43
+ __classPrivateFieldSet(this, _RAFTask_duration, props.duration, "f");
44
+ __classPrivateFieldSet(this, _RAFTask_delay, (_a = props.delay) !== null && _a !== void 0 ? _a : 0, "f");
45
+ __classPrivateFieldSet(this, _RAFTask_action, props.action, "f");
46
+ __classPrivateFieldSet(this, _RAFTask_finish, props.finish, "f");
47
+ __classPrivateFieldSet(this, _RAFTask_priority, (_b = props.priority) !== null && _b !== void 0 ? _b : 0, "f");
48
+ __classPrivateFieldSet(this, _RAFTask_extension, (_c = props.extension) !== null && _c !== void 0 ? _c : {}, "f");
49
+ __classPrivateFieldSet(this, _RAFTask_isDone, false, "f");
50
+ __classPrivateFieldSet(this, _RAFTask_paused, false, "f");
51
+ }
52
+ // getter
53
+ get id() { return __classPrivateFieldGet(this, _RAFTask_id, "f"); }
54
+ get groupID() { return __classPrivateFieldGet(this, _RAFTask_groupID, "f"); }
55
+ get duration() { return __classPrivateFieldGet(this, _RAFTask_duration, "f"); }
56
+ get delay() { return __classPrivateFieldGet(this, _RAFTask_delay, "f"); }
57
+ get action() { return __classPrivateFieldGet(this, _RAFTask_action, "f"); }
58
+ get finish() { return __classPrivateFieldGet(this, _RAFTask_finish, "f"); }
59
+ get priority() { return __classPrivateFieldGet(this, _RAFTask_priority, "f"); }
60
+ get extension() { return __classPrivateFieldGet(this, _RAFTask_extension, "f"); }
61
+ get progress() {
62
+ if (__classPrivateFieldGet(this, _RAFTask_startTime, "f") === undefined || __classPrivateFieldGet(this, _RAFTask_currentTime, "f") === undefined)
63
+ return 0;
64
+ return Math.min(1, Math.max(0, (__classPrivateFieldGet(this, _RAFTask_currentTime, "f") - __classPrivateFieldGet(this, _RAFTask_startTime, "f")) /
65
+ Math.max(1, __classPrivateFieldGet(this, _RAFTask_duration, "f"))));
66
+ }
67
+ get deltaTime() { var _a; return (_a = __classPrivateFieldGet(this, _RAFTask_deltaTime, "f")) !== null && _a !== void 0 ? _a : 0; }
68
+ get isDone() {
69
+ if (__classPrivateFieldGet(this, _RAFTask_isDone, "f"))
70
+ return true;
71
+ if (__classPrivateFieldGet(this, _RAFTask_pausedTime, "f") !== undefined)
72
+ return false;
73
+ return this.progress === 1;
74
+ }
75
+ get paused() { return __classPrivateFieldGet(this, _RAFTask_paused, "f"); }
76
+ // setter
77
+ set groupID(val) { __classPrivateFieldSet(this, _RAFTask_groupID, val, "f"); }
78
+ set priority(val) { __classPrivateFieldSet(this, _RAFTask_priority, val, "f"); }
79
+ set extension(val) { __classPrivateFieldSet(this, _RAFTask_extension, val, "f"); }
80
+ set isDone(val) { __classPrivateFieldSet(this, _RAFTask_isDone, val, "f"); }
81
+ set paused(val) { __classPrivateFieldSet(this, _RAFTask_paused, val, "f"); }
82
+ // private method: _isStart
83
+ /**
84
+ * アクションを開始して良いか判定する
85
+ * 現在時間等のアップデートも同時に行われる
86
+ * subscription_RAFManager でのみ使用される
87
+ *
88
+ * @param {number} now - requestAnimatinFrame が返す絶対時間
89
+ * @returns {boolan} - アクションを実行して良いか判定
90
+ */
91
+ [(_RAFTask_id = new WeakMap(), _RAFTask_groupID = new WeakMap(), _RAFTask_duration = new WeakMap(), _RAFTask_delay = new WeakMap(), _RAFTask_action = new WeakMap(), _RAFTask_finish = new WeakMap(), _RAFTask_priority = new WeakMap(), _RAFTask_extension = new WeakMap(), _RAFTask_startTime = new WeakMap(), _RAFTask_currentTime = new WeakMap(), _RAFTask_pausedTime = new WeakMap(), _RAFTask_paused = new WeakMap(), _RAFTask_deltaTime = new WeakMap(), _RAFTask_isDone = new WeakMap(), _isStart)](now) {
92
+ var _a;
93
+ // done
94
+ if (this.isDone)
95
+ return false;
96
+ // startTime
97
+ if (__classPrivateFieldGet(this, _RAFTask_startTime, "f") === undefined)
98
+ __classPrivateFieldSet(this, _RAFTask_startTime, now + __classPrivateFieldGet(this, _RAFTask_delay, "f"), "f");
99
+ // pause
100
+ if (this.paused) {
101
+ if (__classPrivateFieldGet(this, _RAFTask_pausedTime, "f") === undefined)
102
+ __classPrivateFieldSet(this, _RAFTask_pausedTime, now, "f");
103
+ __classPrivateFieldSet(this, _RAFTask_deltaTime, 0, "f");
104
+ __classPrivateFieldSet(this, _RAFTask_currentTime, now, "f");
105
+ return false;
106
+ }
107
+ // resume
108
+ if (!this.paused && __classPrivateFieldGet(this, _RAFTask_pausedTime, "f") !== undefined) {
109
+ __classPrivateFieldSet(this, _RAFTask_startTime, __classPrivateFieldGet(this, _RAFTask_startTime, "f") + now - __classPrivateFieldGet(this, _RAFTask_pausedTime, "f"), "f");
110
+ __classPrivateFieldSet(this, _RAFTask_pausedTime, undefined, "f");
111
+ }
112
+ // deltaTime
113
+ __classPrivateFieldSet(this, _RAFTask_deltaTime, now < __classPrivateFieldGet(this, _RAFTask_startTime, "f")
114
+ ? 0
115
+ : now - ((_a = __classPrivateFieldGet(this, _RAFTask_currentTime, "f")) !== null && _a !== void 0 ? _a : now), "f");
116
+ // currentTime
117
+ __classPrivateFieldSet(this, _RAFTask_currentTime, now, "f");
118
+ // result
119
+ __classPrivateFieldSet(this, _RAFTask_isDone, this.progress === 1, "f");
120
+ return !__classPrivateFieldGet(this, _RAFTask_isDone, "f");
121
+ }
122
+ // method: clone
123
+ /**
124
+ * 時間を初期化したクローンを作成して返す
125
+ */
126
+ clone() {
127
+ return new RAFTask({
128
+ id: this.id,
129
+ groupID: this.groupID,
130
+ duration: this.duration,
131
+ delay: this.delay,
132
+ action: this.action,
133
+ finish: this.finish,
134
+ priority: this.priority,
135
+ extension: this.extension
136
+ });
137
+ }
138
+ }
139
+ // ---------- ---------- ---------- ---------- ----------
140
+ // subscription_RAFManager
141
+ // ---------- ---------- ---------- ---------- ----------
142
+ /**
143
+ * RAFTask 配列をフレームごとに実行するサブスクリプション
144
+ *
145
+ * @template S
146
+ * @param {S} state - ステート
147
+ * @param {string[]} keyNames - RAFTask 配列までのパス
148
+ * @returns {Subscription<S>}
149
+ */
150
+ export const subscription_RAFManager = function (state, keyNames) {
151
+ let rID = 0; // rAF timerID
152
+ // result
153
+ return [
154
+ (dispatch, payload) => {
155
+ if (payload.length === 0)
156
+ return () => {
157
+ if (rID !== 0)
158
+ cancelAnimationFrame(rID);
159
+ };
160
+ // rAF callback
161
+ const loop = (now) => {
162
+ dispatch((state) => {
163
+ const tasks = getValue(state, keyNames, []);
164
+ const newTasks = tasks.map(task => {
165
+ if (task.isDone)
166
+ return null;
167
+ // action
168
+ if (task[_isStart](now)) {
169
+ requestAnimationFrame(() => dispatch((state) => task.action(state, task)));
170
+ }
171
+ // finish
172
+ if (task.isDone) {
173
+ const fn = task.finish;
174
+ if (fn) {
175
+ requestAnimationFrame(() => dispatch((state) => fn(state, task)));
176
+ }
177
+ return null;
178
+ }
179
+ // next
180
+ return task;
181
+ }).filter(task => task !== null);
182
+ // next loop
183
+ if (newTasks.length !== 0)
184
+ rID = requestAnimationFrame(loop);
185
+ // set state
186
+ return setValue(state, keyNames, newTasks);
187
+ });
188
+ };
189
+ // set animation
190
+ rID = requestAnimationFrame(loop);
191
+ // finalize
192
+ return () => {
193
+ if (rID !== 0)
194
+ cancelAnimationFrame(rID);
195
+ };
196
+ },
197
+ // payload
198
+ getValue(state, keyNames, [])
199
+ .filter(task => !task.isDone)
200
+ .sort((a, b) => b.priority - a.priority)
201
+ ];
202
+ };