hyperapp-is 0.1.50 → 0.2.1
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.md +220 -1557
- package/dist/{hyperapp-is/animation → animation}/easing.d.ts +4 -0
- package/dist/{hyperapp-is/animation → animation}/easing.js +4 -4
- package/dist/{hyperapp-is/animation → animation}/properties.d.ts +9 -16
- package/dist/{hyperapp-is/animation → animation}/properties.js +13 -12
- package/dist/{hyperapp-is/animation → animation}/raf.d.ts +11 -12
- package/dist/animation/raf.js +192 -0
- package/dist/core/component.d.ts +23 -0
- package/dist/core/component.js +52 -0
- package/dist/core/effects.d.ts +10 -0
- package/dist/core/effects.js +34 -0
- package/dist/core/state.d.ts +21 -0
- package/dist/{hyperapp-is/core → core}/state.js +15 -20
- package/dist/dom/dialog.d.ts +6 -0
- package/dist/dom/dialog.js +85 -0
- package/dist/dom/utils.d.ts +15 -0
- package/dist/dom/utils.js +19 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +10 -0
- package/dist/services/google.d.ts +69 -0
- package/dist/services/google.js +170 -0
- package/package.json +13 -39
- package/dist/hyperapp-is/animation/raf.js +0 -209
- package/dist/hyperapp-is/animationView/carousel.d.ts +0 -48
- package/dist/hyperapp-is/animationView/carousel.js +0 -461
- package/dist/hyperapp-is/core/component.d.ts +0 -65
- package/dist/hyperapp-is/core/component.js +0 -242
- package/dist/hyperapp-is/core/navigator.d.ts +0 -115
- package/dist/hyperapp-is/core/navigator.js +0 -615
- package/dist/hyperapp-is/core/state.d.ts +0 -27
- package/dist/hyperapp-is/dom/utils.d.ts +0 -37
- package/dist/hyperapp-is/dom/utils.js +0 -69
- package/dist/hyperapp-is/index.d.ts +0 -16
- package/dist/hyperapp-is/index.js +0 -10
- package/dist/hyperapp-is/services/google.d.ts +0 -89
- package/dist/hyperapp-is/services/google.js +0 -178
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* RAFTask.progress に適用する
|
|
3
|
+
* イージング関数集
|
|
4
|
+
*/
|
|
5
5
|
export const progress_easing = {
|
|
6
6
|
// basic
|
|
7
7
|
linear: (t) => t,
|
|
@@ -1,32 +1,25 @@
|
|
|
1
|
-
import { Dispatch } from "hyperapp";
|
|
2
|
-
import {
|
|
1
|
+
import type { Dispatch, Effect } from "hyperapp";
|
|
2
|
+
import { RAFTask } from "./raf";
|
|
3
|
+
export type { CSSProperty };
|
|
4
|
+
export { createRAFProperties, effect_RAFProperties };
|
|
3
5
|
/**
|
|
4
6
|
* アニメーション進捗 (0〜1) を受け取り CSS 値を返す関数
|
|
5
7
|
*/
|
|
6
|
-
|
|
8
|
+
interface CSSProperty {
|
|
7
9
|
[selector: string]: {
|
|
8
10
|
[name: string]: (progress: number) => string;
|
|
9
11
|
};
|
|
10
12
|
}
|
|
11
|
-
/**
|
|
12
|
-
* CSSProperty[] から、doms と styles のセットに変換
|
|
13
|
-
*/
|
|
14
|
-
export declare const createUnits: (properties: CSSProperty[]) => {
|
|
15
|
-
doms: HTMLElement[];
|
|
16
|
-
styles: {
|
|
17
|
-
[name: string]: (progress: number) => string;
|
|
18
|
-
};
|
|
19
|
-
}[];
|
|
20
13
|
/**
|
|
21
14
|
* subscription_RAFManager をベースにした CSS アニメーション RAFTask を作成する
|
|
22
15
|
* props は基本的に RAFTask の値
|
|
23
16
|
*/
|
|
24
|
-
|
|
17
|
+
declare const createRAFProperties: <S>(props: {
|
|
25
18
|
id: string;
|
|
26
19
|
groupID?: string;
|
|
27
20
|
duration: number;
|
|
28
21
|
delay?: number;
|
|
29
|
-
finish?: (state: S, rafTask: RAFTask<S>) => S | [S,
|
|
22
|
+
finish?: (state: S, rafTask: RAFTask<S>) => S | [S, Effect<S>];
|
|
30
23
|
priority?: number;
|
|
31
24
|
extension?: Record<string, any>;
|
|
32
25
|
properties: CSSProperty[];
|
|
@@ -35,12 +28,12 @@ export declare const createRAFProperties: <S>(props: {
|
|
|
35
28
|
* subscription_RAFManager をベースにした CSS アニメーションエフェクト
|
|
36
29
|
* props は基本的に RAFTask の値
|
|
37
30
|
*/
|
|
38
|
-
|
|
31
|
+
declare const effect_RAFProperties: <S>(props: {
|
|
39
32
|
id: string;
|
|
40
33
|
groupID?: string;
|
|
41
34
|
duration: number;
|
|
42
35
|
delay?: number;
|
|
43
|
-
finish?: (state: S, rafTask: RAFTask<S>) => S | [S,
|
|
36
|
+
finish?: (state: S, rafTask: RAFTask<S>) => S | [S, Effect<S>];
|
|
44
37
|
priority?: number;
|
|
45
38
|
extension?: Record<string, any>;
|
|
46
39
|
properties: CSSProperty[];
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
//
|
|
1
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
2
|
+
// import
|
|
3
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
4
|
+
// hyprerapp-is
|
|
2
5
|
import { getValue, setValue } from "../core/state";
|
|
3
6
|
import { RAFTask } from "./raf";
|
|
7
|
+
export { createRAFProperties, effect_RAFProperties };
|
|
4
8
|
// ---------- ---------- ---------- ---------- ----------
|
|
5
|
-
//
|
|
9
|
+
// implementation
|
|
10
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
11
|
+
// GPU_LAYER を適用させる CSS プロパティ
|
|
12
|
+
const GPU_LAYER = new Set(["transform", "opacity"]);
|
|
6
13
|
// ---------- ---------- ---------- ---------- ----------
|
|
7
14
|
/**
|
|
8
15
|
* CSSProperty[] から、doms と styles のセットに変換
|
|
9
16
|
*/
|
|
10
|
-
|
|
17
|
+
const createUnits = function (properties) {
|
|
11
18
|
return properties.map(p => {
|
|
12
19
|
const selector = Object.keys(p)[0];
|
|
13
20
|
return {
|
|
@@ -17,20 +24,17 @@ export const createUnits = function (properties) {
|
|
|
17
24
|
});
|
|
18
25
|
};
|
|
19
26
|
// ---------- ---------- ---------- ---------- ----------
|
|
20
|
-
// createRAFProperties
|
|
21
|
-
// ---------- ---------- ---------- ---------- ----------
|
|
22
27
|
/**
|
|
23
28
|
* subscription_RAFManager をベースにした CSS アニメーション RAFTask を作成する
|
|
24
29
|
* props は基本的に RAFTask の値
|
|
25
30
|
*/
|
|
26
|
-
|
|
31
|
+
const createRAFProperties = function (props) {
|
|
27
32
|
const { id, groupID, duration, delay, priority, extension, properties } = props;
|
|
28
33
|
// ---------- ---------- ----------
|
|
29
34
|
// action
|
|
30
35
|
// ---------- ---------- ----------
|
|
31
36
|
const action = (state, rafTask) => {
|
|
32
|
-
|
|
33
|
-
const progress = (_a = rafTask.progress) !== null && _a !== void 0 ? _a : 0;
|
|
37
|
+
const progress = rafTask.progress ?? 0;
|
|
34
38
|
const units = createUnits(properties);
|
|
35
39
|
// set styles
|
|
36
40
|
units.forEach(unit => {
|
|
@@ -70,14 +74,11 @@ export const createRAFProperties = function (props) {
|
|
|
70
74
|
});
|
|
71
75
|
};
|
|
72
76
|
// ---------- ---------- ---------- ---------- ----------
|
|
73
|
-
// effect_RAFProperties
|
|
74
|
-
// ---------- ---------- ---------- ---------- ----------
|
|
75
|
-
const GPU_LAYER = new Set(["transform", "opacity"]);
|
|
76
77
|
/**
|
|
77
78
|
* subscription_RAFManager をベースにした CSS アニメーションエフェクト
|
|
78
79
|
* props は基本的に RAFTask の値
|
|
79
80
|
*/
|
|
80
|
-
|
|
81
|
+
const effect_RAFProperties = function (props) {
|
|
81
82
|
const { id, groupID, duration, delay, finish, priority, extension, properties, keyNames } = props;
|
|
82
83
|
// get doms
|
|
83
84
|
const units = createUnits(properties);
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { Effect, Subscription } from "hyperapp";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* Effect の型エイリアス
|
|
6
|
-
*/
|
|
7
|
-
export type InternalEffect<S> = Effect<S>;
|
|
1
|
+
import type { Effect, Subscription } from "hyperapp";
|
|
2
|
+
export type { RAFEvent };
|
|
3
|
+
export { RAFTask, subscription_RAFManager };
|
|
4
|
+
declare const _isStart: unique symbol;
|
|
8
5
|
/**
|
|
9
6
|
* RAFTask の action, finish
|
|
10
7
|
* 型エイリアス
|
|
11
8
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
type RAFEvent<S> = (state: S, rafTask: RAFTask<S>) => S | [S, Effect<S>];
|
|
10
|
+
/**
|
|
11
|
+
* requestAnimationFrame を利用して実行する、タスクを管理するクラス
|
|
12
|
+
*/
|
|
13
|
+
declare class RAFTask<S> {
|
|
15
14
|
#private;
|
|
16
15
|
constructor(props: {
|
|
17
16
|
id: string;
|
|
@@ -53,6 +52,6 @@ export declare class RAFTask<S> {
|
|
|
53
52
|
}
|
|
54
53
|
/**
|
|
55
54
|
* RAFTask 配列の実行を管理するサブスクリプション
|
|
55
|
+
* keyNames には、RAFTask[] までのパスを指定する
|
|
56
56
|
*/
|
|
57
|
-
|
|
58
|
-
export {};
|
|
57
|
+
declare const subscription_RAFManager: <S>(state: S, keyNames: string[]) => Subscription<S>;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
2
|
+
// import
|
|
3
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
4
|
+
// hyperapp-is
|
|
5
|
+
import { getValue, setValue } from "../core/state";
|
|
6
|
+
export { RAFTask, subscription_RAFManager };
|
|
7
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
8
|
+
// implementation
|
|
9
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
10
|
+
// Symbol
|
|
11
|
+
// subscription_RAFManager のみで使用される専用メソッド
|
|
12
|
+
// Symbol を知らない限り、モジュールの外からは呼べない
|
|
13
|
+
const _isStart = Symbol("RAFTask.isStart");
|
|
14
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
15
|
+
/**
|
|
16
|
+
* requestAnimationFrame を利用して実行する、タスクを管理するクラス
|
|
17
|
+
*/
|
|
18
|
+
class RAFTask {
|
|
19
|
+
// field
|
|
20
|
+
#id;
|
|
21
|
+
#groupID;
|
|
22
|
+
#duration;
|
|
23
|
+
#delay;
|
|
24
|
+
#action;
|
|
25
|
+
#finish;
|
|
26
|
+
#priority;
|
|
27
|
+
#extension;
|
|
28
|
+
#startTime;
|
|
29
|
+
#currentTime;
|
|
30
|
+
#pausedTime;
|
|
31
|
+
#paused;
|
|
32
|
+
#deltaTime;
|
|
33
|
+
#isDone;
|
|
34
|
+
// constructor
|
|
35
|
+
constructor(props) {
|
|
36
|
+
this.#id = props.id;
|
|
37
|
+
this.#groupID = props.groupID;
|
|
38
|
+
this.#duration = props.duration;
|
|
39
|
+
this.#delay = props.delay ?? 0;
|
|
40
|
+
this.#action = props.action;
|
|
41
|
+
this.#finish = props.finish;
|
|
42
|
+
this.#priority = props.priority ?? 0;
|
|
43
|
+
this.#extension = props.extension ?? {};
|
|
44
|
+
this.#isDone = false;
|
|
45
|
+
this.#paused = false;
|
|
46
|
+
}
|
|
47
|
+
// getter
|
|
48
|
+
get id() { return this.#id; }
|
|
49
|
+
get groupID() { return this.#groupID; }
|
|
50
|
+
get duration() { return this.#duration; }
|
|
51
|
+
get delay() { return this.#delay; }
|
|
52
|
+
get action() { return this.#action; }
|
|
53
|
+
get finish() { return this.#finish; }
|
|
54
|
+
get priority() { return this.#priority; }
|
|
55
|
+
get extension() { return this.#extension; }
|
|
56
|
+
get progress() {
|
|
57
|
+
if (this.#startTime === undefined || this.#currentTime === undefined)
|
|
58
|
+
return 0;
|
|
59
|
+
return Math.min(1, Math.max(0, (this.#currentTime - this.#startTime) /
|
|
60
|
+
Math.max(1, this.#duration)));
|
|
61
|
+
}
|
|
62
|
+
get deltaTime() { return this.#deltaTime ?? 0; }
|
|
63
|
+
get isDone() {
|
|
64
|
+
if (this.#isDone)
|
|
65
|
+
return true;
|
|
66
|
+
if (this.#pausedTime !== undefined)
|
|
67
|
+
return false;
|
|
68
|
+
return this.progress === 1;
|
|
69
|
+
}
|
|
70
|
+
get paused() { return this.#paused; }
|
|
71
|
+
// setter
|
|
72
|
+
set groupID(val) { this.#groupID = val; }
|
|
73
|
+
set priority(val) { this.#priority = val; }
|
|
74
|
+
set extension(val) { this.#extension = val; }
|
|
75
|
+
set isDone(val) { this.#isDone = val; }
|
|
76
|
+
set paused(val) { this.#paused = val; }
|
|
77
|
+
// ---------- ---------- ----------
|
|
78
|
+
// private method: _isStart
|
|
79
|
+
// ---------- ---------- ----------
|
|
80
|
+
/**
|
|
81
|
+
* アクションを開始して良いか判定する
|
|
82
|
+
* 現在時間等のアップデートも同時に行われる
|
|
83
|
+
* subscription_RAFManager でのみ使用される
|
|
84
|
+
*/
|
|
85
|
+
[_isStart](now) {
|
|
86
|
+
// done
|
|
87
|
+
if (this.isDone)
|
|
88
|
+
return false;
|
|
89
|
+
// startTime
|
|
90
|
+
if (this.#startTime === undefined)
|
|
91
|
+
this.#startTime = now + this.#delay;
|
|
92
|
+
// pause
|
|
93
|
+
if (this.paused) {
|
|
94
|
+
if (this.#pausedTime === undefined)
|
|
95
|
+
this.#pausedTime = now;
|
|
96
|
+
this.#deltaTime = 0;
|
|
97
|
+
this.#currentTime = now;
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
// resume
|
|
101
|
+
if (!this.paused && this.#pausedTime !== undefined) {
|
|
102
|
+
this.#startTime = this.#startTime + now - this.#pausedTime;
|
|
103
|
+
this.#pausedTime = undefined;
|
|
104
|
+
}
|
|
105
|
+
// deltaTime
|
|
106
|
+
this.#deltaTime = now < this.#startTime
|
|
107
|
+
? 0
|
|
108
|
+
: now - (this.#currentTime ?? now);
|
|
109
|
+
// currentTime
|
|
110
|
+
this.#currentTime = now;
|
|
111
|
+
// result
|
|
112
|
+
this.#isDone = this.progress === 1;
|
|
113
|
+
return !this.#isDone;
|
|
114
|
+
}
|
|
115
|
+
// ---------- ---------- ----------
|
|
116
|
+
// method: clone
|
|
117
|
+
// ---------- ---------- ----------
|
|
118
|
+
/**
|
|
119
|
+
* 時間を初期化したクローンを作成して返す
|
|
120
|
+
*/
|
|
121
|
+
clone() {
|
|
122
|
+
return new RAFTask({
|
|
123
|
+
id: this.id,
|
|
124
|
+
groupID: this.groupID,
|
|
125
|
+
duration: this.duration,
|
|
126
|
+
delay: this.delay,
|
|
127
|
+
action: this.action,
|
|
128
|
+
finish: this.finish,
|
|
129
|
+
priority: this.priority,
|
|
130
|
+
extension: this.extension
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
135
|
+
/**
|
|
136
|
+
* RAFTask 配列の実行を管理するサブスクリプション
|
|
137
|
+
* keyNames には、RAFTask[] までのパスを指定する
|
|
138
|
+
*/
|
|
139
|
+
const subscription_RAFManager = function (state, keyNames) {
|
|
140
|
+
let rID = 0; // rAF timerID
|
|
141
|
+
// result
|
|
142
|
+
return [
|
|
143
|
+
(dispatch, payload) => {
|
|
144
|
+
if (payload.length === 0)
|
|
145
|
+
return () => {
|
|
146
|
+
if (rID !== 0)
|
|
147
|
+
cancelAnimationFrame(rID);
|
|
148
|
+
};
|
|
149
|
+
// rAF callback
|
|
150
|
+
const loop = (now) => {
|
|
151
|
+
dispatch((state) => {
|
|
152
|
+
const tasks = getValue(state, keyNames, []);
|
|
153
|
+
// newTasks
|
|
154
|
+
const newTasks = tasks.map(task => {
|
|
155
|
+
if (task.isDone)
|
|
156
|
+
return null;
|
|
157
|
+
// action
|
|
158
|
+
if (task[_isStart](now)) {
|
|
159
|
+
requestAnimationFrame(() => dispatch((state) => task.action(state, task)));
|
|
160
|
+
}
|
|
161
|
+
// finish
|
|
162
|
+
if (task.isDone) {
|
|
163
|
+
const fn = task.finish;
|
|
164
|
+
if (fn) {
|
|
165
|
+
requestAnimationFrame(() => dispatch((state) => fn(state, task)));
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
// next
|
|
170
|
+
return task;
|
|
171
|
+
}).filter(task => task !== null);
|
|
172
|
+
// next loop
|
|
173
|
+
if (newTasks.length !== 0)
|
|
174
|
+
rID = requestAnimationFrame(loop);
|
|
175
|
+
// set state
|
|
176
|
+
return setValue(state, keyNames, newTasks);
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
// set animation
|
|
180
|
+
rID = requestAnimationFrame(loop);
|
|
181
|
+
// finalize
|
|
182
|
+
return () => {
|
|
183
|
+
if (rID !== 0)
|
|
184
|
+
cancelAnimationFrame(rID);
|
|
185
|
+
};
|
|
186
|
+
},
|
|
187
|
+
// payload
|
|
188
|
+
getValue(state, keyNames, [])
|
|
189
|
+
.filter(task => !task.isDone)
|
|
190
|
+
.sort((a, b) => b.priority - a.priority)
|
|
191
|
+
];
|
|
192
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { VNode, Effect } from "hyperapp";
|
|
2
|
+
export { el, concatAction, getClassList, deleteKeys };
|
|
3
|
+
/**
|
|
4
|
+
* h 関数のラッパー
|
|
5
|
+
*/
|
|
6
|
+
declare const el: <S = any>(tag: string) => (props?: {
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}, ...children: any[]) => VNode<S>;
|
|
9
|
+
/**
|
|
10
|
+
* アクションを結合する
|
|
11
|
+
* 結合したアクションは、1フレーム後に実行される
|
|
12
|
+
*/
|
|
13
|
+
declare const concatAction: <S, E>(action: undefined | ((state: S, e: E) => S | [S, Effect<S>]), newState: S, e: E) => S | [S, Effect<S>];
|
|
14
|
+
/**
|
|
15
|
+
* props から クラスリストを取得する
|
|
16
|
+
*/
|
|
17
|
+
declare const getClassList: (props: {
|
|
18
|
+
[key: string]: any;
|
|
19
|
+
}) => string[];
|
|
20
|
+
/**
|
|
21
|
+
* props から 指定されたキーを削除する
|
|
22
|
+
*/
|
|
23
|
+
declare const deleteKeys: <T extends Record<string, any>>(props: T, ...keys: (keyof T)[]) => Omit<T, (typeof keys)[number]>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
2
|
+
// import
|
|
3
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
4
|
+
import { h, text } from "hyperapp";
|
|
5
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
6
|
+
// exports
|
|
7
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
8
|
+
export { el, concatAction, getClassList, deleteKeys };
|
|
9
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
10
|
+
// implementation
|
|
11
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
12
|
+
/**
|
|
13
|
+
* h 関数のラッパー
|
|
14
|
+
*/
|
|
15
|
+
const el = (tag) => (props, ...children) => h(tag, props ?? {}, children
|
|
16
|
+
.flat()
|
|
17
|
+
.filter(child => child !== null &&
|
|
18
|
+
child !== undefined)
|
|
19
|
+
.map((child) => typeof child === "object" ? child : text(`${child}`)));
|
|
20
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
21
|
+
/**
|
|
22
|
+
* アクションを結合する
|
|
23
|
+
* 結合したアクションは、1フレーム後に実行される
|
|
24
|
+
*/
|
|
25
|
+
const concatAction = function (action, newState, e) {
|
|
26
|
+
if (!action)
|
|
27
|
+
return newState;
|
|
28
|
+
const effect = (dispatch) => {
|
|
29
|
+
requestAnimationFrame(() => {
|
|
30
|
+
dispatch((state) => action(state, e));
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
return [newState, effect];
|
|
34
|
+
};
|
|
35
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
36
|
+
/**
|
|
37
|
+
* props から クラスリストを取得する
|
|
38
|
+
*/
|
|
39
|
+
const getClassList = (props) => {
|
|
40
|
+
return props.class
|
|
41
|
+
? props.class.trim().split(" ").filter(Boolean)
|
|
42
|
+
: [];
|
|
43
|
+
};
|
|
44
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
45
|
+
/**
|
|
46
|
+
* props から 指定されたキーを削除する
|
|
47
|
+
*/
|
|
48
|
+
const deleteKeys = (props, ...keys) => {
|
|
49
|
+
const result = { ...props };
|
|
50
|
+
keys.forEach(key => delete result[key]);
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
2
|
+
// import
|
|
3
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
4
|
+
// hyperapp-is
|
|
5
|
+
import { getValue, setValue } from "./state";
|
|
6
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
7
|
+
// exports
|
|
8
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
9
|
+
export { effect_toast };
|
|
10
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
11
|
+
// implementation
|
|
12
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
13
|
+
/**
|
|
14
|
+
* 一定時間値を設定した後、元の値に戻す
|
|
15
|
+
*/
|
|
16
|
+
const effect_toast = function (props) {
|
|
17
|
+
const { keyNames, value, duration = 2000 } = props;
|
|
18
|
+
const fn = (dispatch, thisValue) => {
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
dispatch((state) => {
|
|
21
|
+
if (getValue(state, keyNames, undefined) !== value)
|
|
22
|
+
return state;
|
|
23
|
+
return setValue(state, keyNames, thisValue);
|
|
24
|
+
});
|
|
25
|
+
}, duration);
|
|
26
|
+
}; // end fn
|
|
27
|
+
return (dispatch) => {
|
|
28
|
+
dispatch((state) => {
|
|
29
|
+
const thisValue = getValue(state, keyNames, undefined);
|
|
30
|
+
fn(dispatch, thisValue);
|
|
31
|
+
return setValue(state, keyNames, value);
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export { getValue, setValue, getLocalState, setLocalState, createLocalKey };
|
|
2
|
+
/**
|
|
3
|
+
* state の keyNames をたどって値を取得する
|
|
4
|
+
*/
|
|
5
|
+
declare const getValue: <S, D>(state: S, keyNames: string[], def: D) => D;
|
|
6
|
+
/**
|
|
7
|
+
* state の keyNames をたどって値を設定する
|
|
8
|
+
*/
|
|
9
|
+
declare const setValue: <S>(state: S, keyNames: string[], value: any) => S;
|
|
10
|
+
/**
|
|
11
|
+
* ユニーク文字を作成する
|
|
12
|
+
*/
|
|
13
|
+
declare const createLocalKey: (id: string) => string;
|
|
14
|
+
/**
|
|
15
|
+
* state にぶら下げられたローカルステートを取得する
|
|
16
|
+
*/
|
|
17
|
+
declare const getLocalState: <S, T>(state: S, id: string, def: T) => T;
|
|
18
|
+
/**
|
|
19
|
+
* state にローカルステートをぶら下げる
|
|
20
|
+
*/
|
|
21
|
+
declare const setLocalState: <S, T>(state: S, id: string, value: T) => S;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
// hyperapp-is / core / state.ts
|
|
2
1
|
// ---------- ---------- ---------- ---------- ----------
|
|
3
|
-
//
|
|
2
|
+
// exports
|
|
3
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
4
|
+
export { getValue, setValue, getLocalState, setLocalState, createLocalKey };
|
|
5
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
6
|
+
// implementation
|
|
4
7
|
// ---------- ---------- ---------- ---------- ----------
|
|
5
8
|
/**
|
|
6
|
-
*
|
|
9
|
+
* state の keyNames をたどって値を取得する
|
|
7
10
|
*/
|
|
8
|
-
|
|
11
|
+
const getValue = function (state, keyNames, def) {
|
|
9
12
|
let result = state;
|
|
10
13
|
for (const key of keyNames) {
|
|
11
14
|
if (result == null ||
|
|
@@ -21,12 +24,10 @@ export const getValue = function (state, keyNames, def) {
|
|
|
21
24
|
return result;
|
|
22
25
|
};
|
|
23
26
|
// ---------- ---------- ---------- ---------- ----------
|
|
24
|
-
// setValue
|
|
25
|
-
// ---------- ---------- ---------- ---------- ----------
|
|
26
27
|
/**
|
|
27
|
-
*
|
|
28
|
+
* state の keyNames をたどって値を設定する
|
|
28
29
|
*/
|
|
29
|
-
|
|
30
|
+
const setValue = function (state, keyNames, value) {
|
|
30
31
|
let result = { ...state };
|
|
31
32
|
let current = result;
|
|
32
33
|
for (let i = 0; i < keyNames.length; i++) {
|
|
@@ -47,19 +48,15 @@ export const setValue = function (state, keyNames, value) {
|
|
|
47
48
|
return result;
|
|
48
49
|
};
|
|
49
50
|
// ---------- ---------- ---------- ---------- ----------
|
|
50
|
-
// createLocalKey
|
|
51
|
-
// ---------- ---------- ---------- ---------- ----------
|
|
52
51
|
/**
|
|
53
|
-
*
|
|
52
|
+
* ユニーク文字を作成する
|
|
54
53
|
*/
|
|
55
|
-
|
|
56
|
-
// ---------- ---------- ---------- ---------- ----------
|
|
57
|
-
// getLocalState
|
|
54
|
+
const createLocalKey = (id) => `local_key_${id}`;
|
|
58
55
|
// ---------- ---------- ---------- ---------- ----------
|
|
59
56
|
/**
|
|
60
|
-
*
|
|
57
|
+
* state にぶら下げられたローカルステートを取得する
|
|
61
58
|
*/
|
|
62
|
-
|
|
59
|
+
const getLocalState = function (state, id, def) {
|
|
63
60
|
const localKey = createLocalKey(id);
|
|
64
61
|
const obj = Object.prototype.hasOwnProperty.call(state, localKey)
|
|
65
62
|
? state[localKey]
|
|
@@ -70,12 +67,10 @@ export const getLocalState = function (state, id, def) {
|
|
|
70
67
|
};
|
|
71
68
|
};
|
|
72
69
|
// ---------- ---------- ---------- ---------- ----------
|
|
73
|
-
// setLocalState
|
|
74
|
-
// ---------- ---------- ---------- ---------- ----------
|
|
75
70
|
/**
|
|
76
|
-
*
|
|
71
|
+
* state にローカルステートをぶら下げる
|
|
77
72
|
*/
|
|
78
|
-
|
|
73
|
+
const setLocalState = function (state, id, value) {
|
|
79
74
|
const localKey = createLocalKey(id);
|
|
80
75
|
const obj = Object.prototype.hasOwnProperty.call(state, localKey)
|
|
81
76
|
? state[localKey]
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
2
|
+
// exports
|
|
3
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
4
|
+
export { withLoadingDialog };
|
|
5
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
6
|
+
// implementation
|
|
7
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
8
|
+
/**
|
|
9
|
+
* タスク実行中にローディングダイアログを表示する
|
|
10
|
+
* onCancel を指定した場合は、Esc キーで onCancel が呼び出される
|
|
11
|
+
*/
|
|
12
|
+
const withLoadingDialog = async function (task, onCancel) {
|
|
13
|
+
// dialog
|
|
14
|
+
const dialog = document.createElement("dialog");
|
|
15
|
+
dialog.className = "withLoadingDialog";
|
|
16
|
+
// Esc
|
|
17
|
+
let canceled = false;
|
|
18
|
+
dialog.addEventListener("cancel", e => {
|
|
19
|
+
if (!onCancel) {
|
|
20
|
+
e.preventDefault();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (canceled)
|
|
24
|
+
return;
|
|
25
|
+
canceled = true;
|
|
26
|
+
onCancel();
|
|
27
|
+
});
|
|
28
|
+
dialog.style.margin = "auto auto";
|
|
29
|
+
dialog.style.padding = "0";
|
|
30
|
+
dialog.style.border = "0";
|
|
31
|
+
dialog.style.outline = "none";
|
|
32
|
+
dialog.style.backgroundColor = "transparent";
|
|
33
|
+
// svg
|
|
34
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
35
|
+
svg.setAttribute("viewBox", "0 -960 960 960");
|
|
36
|
+
svg.setAttribute("width", "24px");
|
|
37
|
+
svg.setAttribute("height", "24px");
|
|
38
|
+
svg.setAttribute("fill", "#1F1F1F");
|
|
39
|
+
svg.animate([
|
|
40
|
+
{ transform: "rotate(0deg)" },
|
|
41
|
+
{ transform: "rotate(360deg)" }
|
|
42
|
+
], {
|
|
43
|
+
duration: 1000,
|
|
44
|
+
iterations: Infinity,
|
|
45
|
+
easing: "linear"
|
|
46
|
+
});
|
|
47
|
+
// path
|
|
48
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
49
|
+
path.setAttribute("d", "M325-111.5q-73-31.5-127.5-86t-86-127.5Q80-398 80-480.5t31.5-155q31.5-72.5 86-127t127.5-86Q398-880 480-880q17 0 28.5 11.5T520-840q0 17-11.5 28.5T480-800q-133 0-226.5 93.5T160-480q0 133 93.5 226.5T480-160q133 0 226.5-93.5T800-480q0-17 11.5-28.5T840-520q17 0 28.5 11.5T880-480q0 82-31.5 155t-86 127.5q-54.5 54.5-127 86T480.5-80Q398-80 325-111.5Z");
|
|
50
|
+
// span
|
|
51
|
+
const span = document.createElement("span");
|
|
52
|
+
span.textContent = "Loading...";
|
|
53
|
+
span.style.marginLeft = "0.5rem";
|
|
54
|
+
// append
|
|
55
|
+
svg.appendChild(path);
|
|
56
|
+
dialog.appendChild(svg);
|
|
57
|
+
dialog.appendChild(span);
|
|
58
|
+
// result
|
|
59
|
+
let timerID = undefined;
|
|
60
|
+
try {
|
|
61
|
+
timerID = setTimeout(() => {
|
|
62
|
+
if (timerID === undefined)
|
|
63
|
+
return;
|
|
64
|
+
document.body.appendChild(dialog);
|
|
65
|
+
try {
|
|
66
|
+
dialog.showModal();
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
dialog.remove();
|
|
70
|
+
}
|
|
71
|
+
}, 250);
|
|
72
|
+
return await task();
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
// clear timer
|
|
76
|
+
if (timerID !== 0) {
|
|
77
|
+
clearTimeout(timerID);
|
|
78
|
+
timerID = undefined;
|
|
79
|
+
}
|
|
80
|
+
// remove dialog
|
|
81
|
+
if (dialog.open)
|
|
82
|
+
dialog.close();
|
|
83
|
+
dialog.remove();
|
|
84
|
+
}
|
|
85
|
+
};
|