hyperapp-is 0.1.50 → 0.2.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.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 +1 -0
- package/dist/index.js +1 -0
- package/dist/services/google.d.ts +69 -0
- package/dist/services/google.js +170 -0
- package/package.json +14 -40
- 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
package/README.md
CHANGED
|
@@ -1,1682 +1,345 @@
|
|
|
1
1
|
# hyperapp-is
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
hyperapp 用ユーティリティ集
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
// State
|
|
50
|
-
interface State {
|
|
51
|
-
tasks: RAFTask<State>[]
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const initState: State = {
|
|
55
|
-
tasks: []
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Entry Point
|
|
59
|
-
app({
|
|
60
|
-
node: document.getElementById("app") as HTMLElement,
|
|
61
|
-
|
|
62
|
-
init: [initState, effect_InitCarousel(["tasks"], {
|
|
63
|
-
id : "carousel",
|
|
64
|
-
duration: 2000,
|
|
65
|
-
delay : 1000,
|
|
66
|
-
step : 1
|
|
67
|
-
})],
|
|
68
|
-
|
|
69
|
-
subscriptions: (state) => [
|
|
70
|
-
subscription_RAFManager(state, ["tasks"])
|
|
71
|
-
],
|
|
72
|
-
|
|
73
|
-
view: (state) => (<Carousel
|
|
74
|
-
state = { state }
|
|
75
|
-
id = "carousel"
|
|
76
|
-
keyNames = { ["tasks"] }
|
|
77
|
-
>
|
|
78
|
-
<div>Slide 1</div>
|
|
79
|
-
<div>Slide 2</div>
|
|
80
|
-
<div>Slide 3</div>
|
|
81
|
-
</Carousel>)
|
|
82
|
-
})
|
|
83
|
-
```
|
|
5
|
+
ライブラリ名の is は、is4416 の is です\
|
|
6
|
+
自分用に作成しているユーティリティをまとめたライブラリです
|
|
84
7
|
|
|
85
8
|
---
|
|
86
9
|
|
|
87
|
-
##
|
|
88
|
-
|
|
89
|
-
hyperapp-is allows components to:
|
|
90
|
-
|
|
91
|
-
- Remain independent from root state structure
|
|
92
|
-
- Store internal state without polluting user state
|
|
93
|
-
- Compose actions safely
|
|
94
|
-
- Manage animations declaratively via RAFTask
|
|
95
|
-
|
|
96
|
-
Designed for building reusable UI components on top of Hyperapp.
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## Documentation
|
|
101
|
-
|
|
102
|
-
Full documentation and detailed design notes are available on GitHub:
|
|
103
|
-
|
|
104
|
-
https://github.com/is4416/hyperapp-is
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
## License
|
|
109
|
-
|
|
110
|
-
MIT
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
# hyperapp-is
|
|
115
|
-
|
|
116
|
-
Hyperapp で再利用可能なコンポーネントを作成するためのライブラリです
|
|
117
|
-
hyperapp-is の is は、is4416 の略です
|
|
118
|
-
|
|
119
|
-
[example](https://is4416.github.io/hyperapp-is/)
|
|
120
|
-
※ 本ライブラリの実装サンプル
|
|
121
|
-
|
|
122
|
-
本ライブラリは **イミュータブルなステート更新** と **シンプルな副作用管理** を前提として設計されています。
|
|
123
|
-
JSX を使用する場合は `hyperapp-jsx-pragma` を前提としています。
|
|
124
|
-
|
|
125
|
-
## Functions / 関数リスト
|
|
126
|
-
|
|
127
|
-
npm で非公開の関数 (実験用)は、解説に記載します
|
|
128
|
-
|
|
129
|
-
**core / state.ts**
|
|
130
|
-
- [Keys](#keys)
|
|
131
|
-
- [getValue](#getvalue)
|
|
132
|
-
- [setValue](#setvalue)
|
|
133
|
-
- [getLocalState](#getlocalstate)
|
|
134
|
-
- [setLocalState](#setlocalstate)
|
|
135
|
-
- [createLocalKey](#createlocalkey)
|
|
136
|
-
|
|
137
|
-
**core / component.ts**
|
|
138
|
-
- [Keys_String](#keys_string-keys_arraystring)
|
|
139
|
-
- [Keys_ArrayString](#keys_string-keys_arraystring)
|
|
140
|
-
- [el](#el)
|
|
141
|
-
- [concatAction](#concataction)
|
|
142
|
-
- [getClassList](#getclasslist)
|
|
143
|
-
- [deleteKeys](#deletekeys)
|
|
144
|
-
- [Route](#route)
|
|
145
|
-
- [SelectButton](#selectbutton)
|
|
146
|
-
- [OptionButton](#optionbutton)
|
|
147
|
-
- [HistoryInput](#historyinput)
|
|
148
|
-
|
|
149
|
-
**core / navigator.ts**
|
|
150
|
-
- [Keys_NavigatorItem](#keys_navigatoritem)
|
|
151
|
-
- [NavigatorItem](#navigatoritem)
|
|
152
|
-
- [JsonEntry](#jsonentry)
|
|
153
|
-
- [NavigatorColumn](#navigatorcolumn)
|
|
154
|
-
- [convertJsonToNavigatorItem](#convertjsontonavigatoritem)
|
|
155
|
-
- [getParentItems](#getparentitems)
|
|
156
|
-
- [NavigatorFinder](#navigatorfinder)
|
|
157
|
-
- [SearchResult](#searchresult)
|
|
158
|
-
- [NavigatorSearch](#navigatorsearch)
|
|
159
|
-
|
|
160
|
-
**animation / step.ts**
|
|
161
|
-
- [effect_throwMessageStart](#effect_throwmessagestart)
|
|
162
|
-
- [effect_throwMessagePause](#effect_throwmessagepause--effect_throwmessageresume)
|
|
163
|
-
- [effect_throwMessageResume](#effect_throwmessagepause--effect_throwmessageresume)
|
|
164
|
-
- [marquee](#marquee)
|
|
165
|
-
|
|
166
|
-
**animation / raf.ts**
|
|
167
|
-
- [InternalEffect](#internaleffect)
|
|
168
|
-
- [RAFEvent](#rafevent)
|
|
169
|
-
- [RAFTask](#raftask)
|
|
170
|
-
- [subscription_RAFManager](#subscription_rafmanager)
|
|
171
|
-
|
|
172
|
-
**animation / properties.ts**
|
|
173
|
-
- [CSSProperty](#cssproperty)
|
|
174
|
-
- [createUnits](#createunits)
|
|
175
|
-
- [createRAFProperties](#createrafproperties)
|
|
176
|
-
- [effect_RAFProperties](#effect_rafproperties)
|
|
177
|
-
|
|
178
|
-
**animation / easing.ts**
|
|
179
|
-
- [progress_easing](#progress_easing)
|
|
180
|
-
|
|
181
|
-
**animation / translate.ts**
|
|
182
|
-
- [TranslateState](#translatestate)
|
|
183
|
-
- [createRAFTranslate](#createraftranslate)
|
|
184
|
-
- [effect_translateStart](#effect_translatestart)
|
|
185
|
-
- [effect_translateRollback](#effect_translaterollback)
|
|
186
|
-
- [effect_translateRollforward](#effect_translaterollforward)
|
|
187
|
-
- [effect_translateSlide](#effect_translateslide)
|
|
188
|
-
|
|
189
|
-
**animationView / carouselts**
|
|
190
|
-
- [CarouselState](#carouselstate)
|
|
191
|
-
- [CarouselController](#carouselcontroller)
|
|
192
|
-
- [Carousel](#carousel)
|
|
193
|
-
- [effect_InitCarousel](#effect_initcarousel)
|
|
194
|
-
|
|
195
|
-
**dom / utils.ts**
|
|
196
|
-
- [ScrollMargin](#scrollmargin)
|
|
197
|
-
- [getScrollMargin](#getscrollmargin)
|
|
198
|
-
- [MatrixState](#matrixstate)
|
|
199
|
-
- [getMatrixState](#getmatrixstate)
|
|
200
|
-
|
|
201
|
-
**dom / lifecycle.ts**
|
|
202
|
-
- [effect_setTimedValue](#effect_settimedvalue)
|
|
203
|
-
- [effect_nodesInitialize](#effect_nodesinitialize)
|
|
204
|
-
- [subscription_nodesCleanup](#subscription_nodescleanup)
|
|
205
|
-
- [subscription_nodesLifecycleByIds](#subscription_nodeslifecyclebyids)
|
|
206
|
-
|
|
207
|
-
**services / google**
|
|
208
|
-
- [getGoogle](#getgoogle)
|
|
209
|
-
- [getGoogleAuthResult](#getgoogleauthresult)
|
|
210
|
-
- [getAccessToken](#getaccesstoken)
|
|
211
|
-
- [GoogleAuth](#googleauth)
|
|
212
|
-
|
|
213
|
-
## source file / ソースファイル
|
|
10
|
+
## ファイル構成
|
|
214
11
|
|
|
215
12
|
```
|
|
216
|
-
|
|
217
|
-
└ hyperapp-is
|
|
218
|
-
├ index.ts
|
|
219
|
-
│
|
|
220
|
-
├ core
|
|
221
|
-
│ ├ state.ts
|
|
222
|
-
│ │ Keys
|
|
223
|
-
│ │ getValue, setValue, getLocalState, setLocalState, createLocalKey
|
|
224
|
-
│ │
|
|
225
|
-
│ ├ component.ts
|
|
226
|
-
│ │ Keys_String, Keys_ArrayString
|
|
227
|
-
│ │ el, concatAction, getClassList, deleteKeys
|
|
228
|
-
│ │ Route, SelectButton, OptionButton
|
|
229
|
-
│ │
|
|
230
|
-
│ └ navigator.ts
|
|
231
|
-
│ Keys_NavigatorItem, NavigatorItem, JsonEntry, NavigatorColumn
|
|
232
|
-
│ convertJsonToNavigatorItem, getParentItems, NavigatorFinder
|
|
233
|
-
│ SearchResult, NavigatorSearch
|
|
234
|
-
│
|
|
235
|
-
├ animation
|
|
236
|
-
│ ├ step.ts
|
|
237
|
-
│ │ effect_throwMessageStart, effect_throwMessagePause, effect_throwMessageResume, marquee
|
|
238
|
-
│ │
|
|
239
|
-
│ ├ raf.ts
|
|
240
|
-
│ │ InternalEffect
|
|
241
|
-
│ │ RAFEvent
|
|
242
|
-
│ │ RAFTask
|
|
243
|
-
│ │ subscription_RAFManager
|
|
244
|
-
│ │
|
|
245
|
-
│ ├ properties.ts
|
|
246
|
-
│ │ CSSProperty
|
|
247
|
-
│ │ createRAFProperties
|
|
248
|
-
│ │ effect_RAFProperties
|
|
249
|
-
│ │
|
|
250
|
-
│ ├ easing.ts
|
|
251
|
-
│ │ progress_easing
|
|
252
|
-
│ │
|
|
253
|
-
│ └ translate.ts
|
|
254
|
-
│ TranslateState
|
|
255
|
-
│ createRAFTranslate
|
|
256
|
-
│ effect_translateStart
|
|
257
|
-
│ effect_translateRollback
|
|
258
|
-
│ effect_translateRollforward
|
|
259
|
-
│ effect_translateSlide
|
|
260
|
-
│
|
|
261
|
-
├ animationView
|
|
262
|
-
│ └ carousel.ts
|
|
263
|
-
│
|
|
264
|
-
├ dom
|
|
265
|
-
│ ├ utils.ts
|
|
266
|
-
│ │ ScrollMargin
|
|
267
|
-
│ │ getScrollMargin
|
|
268
|
-
│ │ MatrixState
|
|
269
|
-
│ │ getMatrixState
|
|
270
|
-
│ │
|
|
271
|
-
│ └ lifecycle.ts
|
|
272
|
-
│ effect_setTimedValue
|
|
273
|
-
│ effect_nodesInitialize
|
|
274
|
-
│ subscription_nodesCleanup
|
|
275
|
-
│ subscription_nodesLifecycleByIds
|
|
276
|
-
│
|
|
277
|
-
└ service
|
|
278
|
-
└ google.ts
|
|
279
|
-
getGoogle
|
|
280
|
-
googleAuth
|
|
281
|
-
getAccessToken
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
## hyperapp-is/core
|
|
13
|
+
index.ts: エクスポートの一覧
|
|
285
14
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
export type Keys = readonly string[]
|
|
291
|
-
```
|
|
15
|
+
[core]
|
|
16
|
+
├ state.ts: state 操作に関するもの
|
|
17
|
+
├ component.ts: VNode の作成に関するもの
|
|
18
|
+
└ effects.ts: Effectに関するもの
|
|
292
19
|
|
|
293
|
-
|
|
20
|
+
[dom]
|
|
21
|
+
├ utils.ts: DOM 操作に関するユーティリティ
|
|
22
|
+
└ dialog.ts: DOM を利用したダイアログ
|
|
294
23
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
24
|
+
[animation]
|
|
25
|
+
├ raf.ts: requestAnimationFrame を state と連携する仕組み
|
|
26
|
+
├ easing.ts: イージング関数集
|
|
27
|
+
└ properties.ts: raf.tsを利用した CSS アニメーション
|
|
298
28
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
state : S,
|
|
302
|
-
keyNames: string[],
|
|
303
|
-
def : D
|
|
304
|
-
): D
|
|
29
|
+
[services]
|
|
30
|
+
└ google.ts: Google 認証ユーティリティ
|
|
305
31
|
```
|
|
306
|
-
*型保証は呼び出し側の責任*
|
|
307
|
-
|
|
308
|
-
- state : ステート
|
|
309
|
-
- keyNames: 値までのパス
|
|
310
|
-
- def : デフォルト値
|
|
311
32
|
|
|
312
33
|
---
|
|
313
34
|
|
|
314
|
-
|
|
315
|
-
パスを辿ってステートに値を設定し、immutable な新しいステートを返す
|
|
316
|
-
|
|
317
|
-
```ts
|
|
318
|
-
export const setValue = function <S> (
|
|
319
|
-
state : S,
|
|
320
|
-
keyNames: string[],
|
|
321
|
-
value : any
|
|
322
|
-
): S
|
|
323
|
-
```
|
|
324
|
-
- state : ステート
|
|
325
|
-
- keyNames: 値までのパス
|
|
326
|
-
- value : 設定する値
|
|
327
|
-
|
|
328
|
-
---
|
|
329
|
-
|
|
330
|
-
### getLocalState
|
|
331
|
-
ID に紐づいたローカルステートを取得
|
|
332
|
-
|
|
333
|
-
```ts
|
|
334
|
-
export const getLocalState = function <S> (
|
|
335
|
-
state: S,
|
|
336
|
-
id : string,
|
|
337
|
-
def : { [key: string]: any }
|
|
338
|
-
): { [key: string]: any }
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
- state: ステート
|
|
342
|
-
- id : ユニークID
|
|
343
|
-
- def : 初期値
|
|
344
|
-
|
|
345
|
-
---
|
|
346
|
-
|
|
347
|
-
### setLocalState
|
|
348
|
-
ローカルステートを更新して新しいステートを返す
|
|
349
|
-
|
|
350
|
-
```ts
|
|
351
|
-
export const setLocalState = function <S> (
|
|
352
|
-
state: S,
|
|
353
|
-
id : string,
|
|
354
|
-
value: { [key: string]: any }
|
|
355
|
-
): S
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
- state: ステート
|
|
359
|
-
- id : ユニークID
|
|
360
|
-
- value: 設定するローカルステート
|
|
361
|
-
|
|
362
|
-
---
|
|
363
|
-
|
|
364
|
-
### createLocalKey
|
|
365
|
-
ID からユニーク文字列を作成する
|
|
366
|
-
|
|
367
|
-
```ts
|
|
368
|
-
export const createLocalKey = (id: string): string => `local_key_${ id }`
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
---
|
|
372
|
-
|
|
373
|
-
### Keys_String, Keys_ArrayString
|
|
374
|
-
ステートの任意の値までのパスを表す、文字配列の型エイリアス
|
|
375
|
-
|
|
376
|
-
---
|
|
377
|
-
|
|
378
|
-
### el
|
|
379
|
-
Hyperapp の h 関数ラッパー。JSX と競合する場合に使用
|
|
380
|
-
children の処理も同時に行っているため、本ライブラリでは VNode を作成する際に使用しています
|
|
381
|
-
|
|
382
|
-
```ts
|
|
383
|
-
export const el = <S = any> (tag: string) => (
|
|
384
|
-
props ?: { [key: string]: any },
|
|
385
|
-
children?: Array
|
|
386
|
-
): VNode<S>
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
- tag: タグ名
|
|
390
|
-
|
|
391
|
-
---
|
|
392
|
-
|
|
393
|
-
### concatAction
|
|
394
|
-
アクションを結合して結果を返す
|
|
395
|
-
`effect_nodesInitialize` と組み合わせ可能
|
|
396
|
-
|
|
397
|
-
```ts
|
|
398
|
-
export const concatAction = function <S, E> (
|
|
399
|
-
action : undefined | ((state: S, e: E) => S | [S, Effect<S>]),
|
|
400
|
-
newState: S,
|
|
401
|
-
e : E
|
|
402
|
-
): S | [S, Effect<S>]
|
|
403
|
-
```
|
|
404
|
-
*newStateを設定後、DOM描画を待ち、次の action に結合します*
|
|
405
|
-
|
|
406
|
-
- action : 結合するアクション
|
|
407
|
-
- newState: 結合するステート
|
|
408
|
-
- e : イベント (任意のイベント型)
|
|
409
|
-
|
|
410
|
-
---
|
|
411
|
-
|
|
412
|
-
### getClassList
|
|
413
|
-
props オブジェクトから classList を取得
|
|
414
|
-
|
|
415
|
-
```ts
|
|
416
|
-
export const getClassList = (
|
|
417
|
-
props: { [key: string]: any }
|
|
418
|
-
): string[]
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
- props: props
|
|
422
|
-
|
|
423
|
-
---
|
|
424
|
-
|
|
425
|
-
### deleteKeys
|
|
426
|
-
props から不要なキーを除去
|
|
427
|
-
|
|
428
|
-
```ts
|
|
429
|
-
export const deleteKeys = <T extends Record<string, any>> (
|
|
430
|
-
props : T,
|
|
431
|
-
...keys: (keyof T)[]
|
|
432
|
-
): Omit<T, (typeof keys)[number]>
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
- props : props
|
|
436
|
-
- ...keys: 削除するキー
|
|
437
|
-
|
|
438
|
-
---
|
|
439
|
-
|
|
440
|
-
### Route
|
|
441
|
-
ステート値と一致した場合に VNode を返す
|
|
442
|
-
条件付きレンダリングに利用
|
|
443
|
-
|
|
444
|
-
```ts
|
|
445
|
-
export const Route = function <S> (
|
|
446
|
-
props: {
|
|
447
|
-
state : S
|
|
448
|
-
keyNames: string[]
|
|
449
|
-
match : string
|
|
450
|
-
},
|
|
451
|
-
children: any
|
|
452
|
-
): VNode<S> | null
|
|
453
|
-
```
|
|
454
|
-
*返値に `null` が設定された場合 `VNode` は生成されません*
|
|
455
|
-
|
|
456
|
-
- props : props
|
|
457
|
-
- props.state : ステート
|
|
458
|
-
- props.keyNames: ステート内の文字までのパス
|
|
459
|
-
- props.match : 一致判定する文字
|
|
460
|
-
- children : 出力する内容 (VNode / 配列 / 文字など)
|
|
35
|
+
## 関数一覧 (interfaceは省略)
|
|
461
36
|
|
|
462
|
-
|
|
37
|
+
**core**
|
|
38
|
+
- state: getValue, setValue, getLocalState, setLocalState, createLocalKey
|
|
39
|
+
- component: el, concatAction, getClassList, deleteKeys
|
|
40
|
+
- effects: effect_toast
|
|
463
41
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
42
|
+
**dom**
|
|
43
|
+
- utils: getScrollMargin
|
|
44
|
+
- dialog: withLoadingDialog
|
|
467
45
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
keyNames : string[]
|
|
473
|
-
id : string
|
|
474
|
-
reverse? : boolean
|
|
475
|
-
[key: string]: any
|
|
476
|
-
},
|
|
477
|
-
children: any
|
|
478
|
-
): VNode<S>
|
|
479
|
-
```
|
|
480
|
-
*クリックにより、クラス名 `select` がトグルされます*
|
|
46
|
+
**animation**
|
|
47
|
+
- raf: RAFTask, subscription_RAFManager
|
|
48
|
+
- easing: progress_easing
|
|
49
|
+
- properties: createRAFProperties, effect_RAFProperties
|
|
481
50
|
|
|
482
|
-
|
|
483
|
-
-
|
|
484
|
-
- props.keyNames: ステート内の文字配列までのパス
|
|
485
|
-
- props.id : ユニークID
|
|
486
|
-
- props.reverse?: 反転選択するか
|
|
487
|
-
- children : 子要素 (VNode / string / 配列など)
|
|
51
|
+
**services**
|
|
52
|
+
- google: getAccessToken, GoogleAuth
|
|
488
53
|
|
|
489
54
|
---
|
|
490
55
|
|
|
491
|
-
|
|
492
|
-
クラス名 `select` を単一選択で切り替えるボタン
|
|
493
|
-
単一選択用
|
|
56
|
+
## 使い方
|
|
494
57
|
|
|
495
|
-
|
|
496
|
-
export const OptionButton = function <S> (
|
|
497
|
-
props: {
|
|
498
|
-
state : S
|
|
499
|
-
keyNames : string[]
|
|
500
|
-
id : string
|
|
501
|
-
reverse? : boolean
|
|
502
|
-
[key: string]: any
|
|
503
|
-
},
|
|
504
|
-
children: any
|
|
505
|
-
): VNode<S>
|
|
506
|
-
```
|
|
507
|
-
*クリックにより、クラス名 `select` が排他的に選択されます*
|
|
508
|
-
|
|
509
|
-
- props : props
|
|
510
|
-
- props.state : ステート
|
|
511
|
-
- props.keyNames: ステート内の文字までのパス
|
|
512
|
-
- props.id : ユニークID
|
|
513
|
-
- props.reverse?: 反転選択するか
|
|
514
|
-
- children : 子要素 (VNode / string / 配列など)
|
|
58
|
+
**core**
|
|
515
59
|
|
|
516
|
-
|
|
60
|
+
- `getValue`, `setValue`: keyNames には、取得・設定したい値までのパス
|
|
517
61
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
localState: { histories: string[] }
|
|
62
|
+
> ステートの構造に依存せずに目的の値が取得・設定できます\
|
|
63
|
+
> 汎用コンポーネントの作成に利用できます
|
|
521
64
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
afterRender ?: (state: S, localState: Record<string, any>, vnode: VNode<S>[]) => VNode<S>[]
|
|
530
|
-
[key: string] : any
|
|
65
|
+
例
|
|
66
|
+
```js
|
|
67
|
+
const state = {
|
|
68
|
+
title: "ユーザー情報",
|
|
69
|
+
user: {
|
|
70
|
+
name: "青年",
|
|
71
|
+
age : 20
|
|
531
72
|
}
|
|
532
|
-
): VNode<S>[]
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
- props : props
|
|
536
|
-
- props.state : ステート
|
|
537
|
-
- props.id : ユニークID
|
|
538
|
-
- props.keyNames: ステート内の文字までのパス
|
|
539
|
-
- props.historyLimit: 保持する履歴の最大数 (default = 10)
|
|
540
|
-
- props.afterRender : 全体のレンダーフック
|
|
541
|
-
- returns : [HTMLInputElement, HTMLDataListElement]
|
|
542
|
-
|
|
543
|
-
履歴は `[props.id].histories` に保存されます
|
|
544
|
-
履歴を動的にクリアしたい場合 `setLocalState(state, id, { histories: [] })` などとして下さい
|
|
545
|
-
|
|
546
|
-
---
|
|
547
|
-
|
|
548
|
-
### Keys_NavigatorItem
|
|
549
|
-
ステートの任意の値までのパスを表す、文字配列の型エイリアス
|
|
550
|
-
|
|
551
|
-
---
|
|
552
|
-
|
|
553
|
-
### NavigatorItem
|
|
554
|
-
ツリー構造となるナビゲーションオブジェクト
|
|
555
|
-
|
|
556
|
-
```ts
|
|
557
|
-
export interface NavigatorItem {
|
|
558
|
-
parent : NavigatorItem | null
|
|
559
|
-
name : string
|
|
560
|
-
properties?: Record<string, any>
|
|
561
|
-
children ?: NavigatorItem[]
|
|
562
|
-
path : string
|
|
563
|
-
extension ?: Record<string, any>
|
|
564
|
-
}
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
- parent : 親アイテム
|
|
568
|
-
- name : 名前
|
|
569
|
-
- properties: プロパティ
|
|
570
|
-
- children : 子アイテム
|
|
571
|
-
- path : パス
|
|
572
|
-
- extension : 拡張オブジェクト
|
|
573
|
-
|
|
574
|
-
---
|
|
575
|
-
|
|
576
|
-
### JsonEntry
|
|
577
|
-
getEntriesの返す値
|
|
578
|
-
|
|
579
|
-
```ts
|
|
580
|
-
export interface JsonEntry <D> {
|
|
581
|
-
name : string
|
|
582
|
-
data : D
|
|
583
|
-
isNode: boolean
|
|
584
73
|
}
|
|
585
|
-
```
|
|
586
74
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
---
|
|
592
|
-
|
|
593
|
-
### NavigatorColumn
|
|
594
|
-
NavigatorFinder に渡すヘッダーと値
|
|
595
|
-
|
|
596
|
-
```ts
|
|
597
|
-
export interface NavigatorColumn {
|
|
598
|
-
name : string
|
|
599
|
-
val : (item: NavigatorItem) => any
|
|
600
|
-
text ?: (item: NavigatorItem) => string
|
|
601
|
-
compare?: (a: NavigatorItem, b: NavigatorItem) => number
|
|
602
|
-
}
|
|
75
|
+
const title = getValue(state, ["title"], "タイトル情報") // res: ユーザー情報
|
|
76
|
+
const name = getValue(state, ["user", "name"], "名無し") // res: 青年
|
|
77
|
+
const age = getValue(state, ["user", "age"], 0) // res: 20
|
|
603
78
|
```
|
|
604
79
|
|
|
605
|
-
- name : 名前
|
|
606
|
-
- val : 値を返す関数 (VNode等も可)
|
|
607
|
-
- text : val が string ではない時に設定するテキスト
|
|
608
|
-
- compare: 比較関数
|
|
609
|
-
|
|
610
|
-
`compare` を設置したカラムだけ、ソート対象となります
|
|
611
|
-
|
|
612
80
|
---
|
|
613
81
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
getEntries の採用により、JSON の形を問わない
|
|
617
|
-
|
|
618
|
-
```ts
|
|
619
|
-
export const convertJsonToNavigatorItem = function <D> (
|
|
620
|
-
props: {
|
|
621
|
-
parent : NavigatorItem | null
|
|
622
|
-
name : string
|
|
623
|
-
data : D
|
|
624
|
-
getEntries : (data: D, depth: number) => JsonEntry<D>[]
|
|
625
|
-
isNode : boolean
|
|
626
|
-
depth ?: number
|
|
627
|
-
extension ?: (item: NavigatorItem, data: D, depth: number) => Record<string, any> | undefined
|
|
628
|
-
}
|
|
629
|
-
): NavigatorItem
|
|
630
|
-
```
|
|
631
|
-
|
|
632
|
-
- parent : 親アイテム
|
|
633
|
-
- name : 名前
|
|
634
|
-
- data : データ
|
|
635
|
-
- getEntries: JsonEntry配列を返す関数
|
|
636
|
-
- isNode : ディレクトリか
|
|
637
|
-
- depth : 階層の深さ
|
|
638
|
-
- extension : NavigatorItem.extensionに格納する拡張データ
|
|
82
|
+
- `getLocalState`, `setLocalState`: ローカルステートのように値を取得・設定できます
|
|
83
|
+
- `createLocalKey` は、基本的には内部で使うための関数ですが、外部からも利用可能です
|
|
639
84
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
NavigatorItem から 親アイテムのリストを取得する
|
|
644
|
-
自分自信はリストに含まない
|
|
85
|
+
> `setLocalState` は、メインステートに追加ツリーを追加します\
|
|
86
|
+
> ユーザーはメインステートの改変を意識することなく、ローカルステートのように値を取得・設定できます\
|
|
87
|
+
> 汎用コンポーネントの作成で、ローカルステートが欲しいときに利用できます
|
|
645
88
|
|
|
89
|
+
例
|
|
646
90
|
```ts
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
```
|
|
651
|
-
|
|
652
|
-
---
|
|
653
|
-
|
|
654
|
-
### NavigatorFinder
|
|
655
|
-
ナビゲーターファインダーコンポーネント
|
|
656
|
-
|
|
657
|
-
```ts
|
|
658
|
-
export const NavigatorFinder = function <S> (
|
|
659
|
-
props: {
|
|
660
|
-
state : S
|
|
661
|
-
id : string
|
|
662
|
-
currentKeys : Keys_NavigatorItem
|
|
663
|
-
columns ?: (directory: NavigatorItem | undefined) => NavigatorColumn[]
|
|
664
|
-
plugIn ?: (state: S, localState: Record<string, any>) => VNode<S>[]
|
|
665
|
-
toolBarNode ?: (state: S, localState: Record<string, any>, vnode: VNode<S>) => VNode<S>
|
|
666
|
-
parentItemsNode ?: (state: S, localState: Record<string, any>, vnode: VNode<S>) => VNode<S>
|
|
667
|
-
statusBarNode ?: (state: S, localState: Record<string, any>, vnode: VNode<S>) => VNode<S>
|
|
668
|
-
afterRender ?: (state: S, localState: Record<string, any>, vnode: VNode<S>) => VNode<S>
|
|
669
|
-
[key: string]: any
|
|
670
|
-
}
|
|
671
|
-
): VNode<S>
|
|
672
|
-
```
|
|
673
|
-
|
|
674
|
-
- state : ステート
|
|
675
|
-
- id : ユニークID (DOM ID)
|
|
676
|
-
- currentKeys : カレント NavigatorItem までのパス
|
|
677
|
-
- columns : NavigatorColumn の配列を返す関数
|
|
678
|
-
- plugIn : プラグインの挿入
|
|
679
|
-
- toolBarNode : `toolBar` レンダーフック
|
|
680
|
-
- parentItemsNode: `parentItems` レンダーフック
|
|
681
|
-
- statusBarNode : `statusBar` レンダーフック
|
|
682
|
-
- afterRender : 全体のレンダーフック
|
|
683
|
-
|
|
684
|
-
localState
|
|
685
|
-
- searchText: "" as string // 検索テキスト
|
|
686
|
-
- selected : [] as string[] // 選択されているボタン名
|
|
687
|
-
- sortType : undefined // ソート用比較関数: (a: NavigatorItem, b: NavigatorItem) => number
|
|
688
|
-
- reverse : false as boolean // ソートを逆順にするか
|
|
689
|
-
- sortKey : undefined as undefined | string // 使用されているソート名 (column.name)
|
|
690
|
-
|
|
691
|
-
vnode
|
|
692
|
-
```html
|
|
693
|
-
<div id={id}>
|
|
694
|
-
<div class="rapper">
|
|
695
|
-
<div class="toolBar">
|
|
696
|
-
<div>
|
|
697
|
-
<input type="text" id={id}_searchText list={id}_searchText-history/>
|
|
698
|
-
<datalist id={id}_searchText-history />
|
|
699
|
-
</div>
|
|
700
|
-
<input type="text" />
|
|
701
|
-
<button type="button">FILTER</button>
|
|
702
|
-
</div>
|
|
703
|
-
|
|
704
|
-
<div class="parentItems">
|
|
705
|
-
<ol>
|
|
706
|
-
<li>parent</li>
|
|
707
|
-
</ol>
|
|
708
|
-
<button type="button">COPY</button>
|
|
709
|
-
</div>
|
|
710
|
-
|
|
711
|
-
<div class="items">
|
|
712
|
-
<table>
|
|
713
|
-
<thead>
|
|
714
|
-
<tr>
|
|
715
|
-
<th>ヘッダー</th>
|
|
716
|
-
<th class="sort">ソート付きヘッダー</th>
|
|
717
|
-
</tr>
|
|
718
|
-
</thead>
|
|
719
|
-
<tbody>
|
|
720
|
-
<tr>
|
|
721
|
-
<td class="file"><span>value</span></td>
|
|
722
|
-
<td class="directory"><span>value</span></td>
|
|
723
|
-
</tr>
|
|
724
|
-
</tbody>
|
|
725
|
-
</table>
|
|
726
|
-
</div>
|
|
727
|
-
|
|
728
|
-
<div class="statusBar">message</div>
|
|
729
|
-
</div>
|
|
730
|
-
|
|
731
|
-
<!-- plugIn 必要な分だけ追加 -->
|
|
732
|
-
<div id={plugInID}>
|
|
733
|
-
</div>
|
|
734
|
-
</div>
|
|
735
|
-
```
|
|
736
|
-
|
|
737
|
-
---
|
|
738
|
-
|
|
739
|
-
### SearchResult
|
|
740
|
-
`NavigatorSearch` で検索結果となる構造体
|
|
741
|
-
|
|
742
|
-
```ts
|
|
743
|
-
export interface SearchResult {
|
|
744
|
-
item : NavigatorItem
|
|
745
|
-
depth: number
|
|
91
|
+
interface LocalState {
|
|
92
|
+
color?: string
|
|
93
|
+
size ?: number
|
|
746
94
|
}
|
|
747
|
-
```
|
|
748
95
|
|
|
749
|
-
|
|
96
|
+
const localState = getLocalState(state, name, {
|
|
97
|
+
color: "red"
|
|
98
|
+
}) // res: { color: "red" }
|
|
750
99
|
|
|
751
|
-
|
|
752
|
-
|
|
100
|
+
const newState = setLocalState(state, name, {
|
|
101
|
+
color: "blue"
|
|
102
|
+
size : 180
|
|
103
|
+
})
|
|
753
104
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
statusBarNode ?: (state: S, localState: Record<string, any>, vnode: VNode<S>) => VNode<S>
|
|
766
|
-
afterRender ?: (state: S, localState: Record<string, any>, vnode: VNode<S>) => VNode<S>
|
|
767
|
-
[key: string] : any
|
|
105
|
+
/* res:
|
|
106
|
+
{
|
|
107
|
+
title: "ユーザ情報",
|
|
108
|
+
user : {
|
|
109
|
+
name: "青年",
|
|
110
|
+
age : 20
|
|
111
|
+
},
|
|
112
|
+
local_key_青年: {
|
|
113
|
+
color : "blue",
|
|
114
|
+
size : 180
|
|
115
|
+
}
|
|
768
116
|
}
|
|
769
|
-
|
|
117
|
+
*/
|
|
770
118
|
```
|
|
771
119
|
|
|
772
|
-
- state : ステート
|
|
773
|
-
- id : ユニークID (DOM ID)
|
|
774
|
-
- currentKeys : カレント NavigatorItem までのパス
|
|
775
|
-
- searchResult : カードとして表示する VNode
|
|
776
|
-
- hitTest : 抽出条件
|
|
777
|
-
- maxItemsCount : 最初に表示するカードの最大数
|
|
778
|
-
- toolBarNode : `toolBar` レンダーフック
|
|
779
|
-
- parentItemsNode: `parentItems` レンダーフック
|
|
780
|
-
- statusBarNode : `statusBar` レンダーフック
|
|
781
|
-
- afterRender : 全体のレンダーフック
|
|
782
|
-
|
|
783
|
-
localState
|
|
784
|
-
- maxItemsCount: props.maxItemsCount as number // カードの最大表示数
|
|
785
|
-
- sortName : undefined as undefined | string // ソート名
|
|
786
|
-
- sortFn : undefined as undefined | ((a: SearchResult, b: SearchResult) => number) // 比較関数
|
|
787
|
-
- isDirectory : true // ディレクトリを表示
|
|
788
|
-
- isFile : true // ファイルを表示
|
|
789
|
-
|
|
790
120
|
---
|
|
791
121
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
### effect_throwMessageStart
|
|
795
|
-
文字を一文字ずつ流し込むエフェクト
|
|
796
|
-
|
|
797
|
-
*実験用コードのため、npm 非公開です*
|
|
122
|
+
- `el`: hyperapp の `h` 関数のラッパーです
|
|
798
123
|
|
|
124
|
+
> text関数の省略や、配列の省略などが可能です\
|
|
125
|
+
> JSXを使用する場合は、出番がありません
|
|
799
126
|
|
|
127
|
+
例
|
|
800
128
|
```ts
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
id : string,
|
|
804
|
-
text : string,
|
|
805
|
-
interval: number,
|
|
806
|
-
): (dispatch: Dispatch<S>) => void
|
|
807
|
-
```
|
|
129
|
+
const body = el("body")
|
|
130
|
+
const div = el("div")
|
|
808
131
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
---
|
|
815
|
-
|
|
816
|
-
### effect_throwMessagePause / effect_throwMessageResume
|
|
817
|
-
throwMessage を一時停止・再開
|
|
818
|
-
|
|
819
|
-
*実験用コードのため、npm 非公開です*
|
|
820
|
-
|
|
821
|
-
```ts
|
|
822
|
-
export const effect_throwMessagePause = function <S> (
|
|
823
|
-
id: string
|
|
824
|
-
): (dispatch: Dispatch<S>) => void
|
|
132
|
+
const vnode = body({},
|
|
133
|
+
div({}, "タイトル行"),
|
|
134
|
+
div({}, "メイン")
|
|
135
|
+
)
|
|
825
136
|
```
|
|
826
|
-
```ts
|
|
827
|
-
export const effect_throwMessageResume = function <S> (
|
|
828
|
-
id: string
|
|
829
|
-
): (dispatch: Dispatch<S>) => void
|
|
830
|
-
```
|
|
831
|
-
|
|
832
|
-
- id: ユニークID
|
|
833
137
|
|
|
834
138
|
---
|
|
835
139
|
|
|
836
|
-
|
|
837
|
-
|
|
140
|
+
- deleteKeys : props から指定したキーを削除します
|
|
141
|
+
- getClassList: props からクラスリストを取得します
|
|
142
|
+
- concatAction: アクションを結合します
|
|
838
143
|
|
|
839
|
-
|
|
144
|
+
> 汎用コンポーネントを作成する場合などに使用できます
|
|
840
145
|
|
|
146
|
+
例
|
|
841
147
|
```ts
|
|
842
|
-
|
|
148
|
+
const button = el("button")
|
|
149
|
+
|
|
150
|
+
const MyButton = function <S> (
|
|
843
151
|
props: {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
152
|
+
state: S
|
|
153
|
+
onclick?: (state: S, e: Event) => S | [S, Effect<S>],
|
|
154
|
+
keyNames: string[] // number までのパス
|
|
155
|
+
[key: string]: any
|
|
156
|
+
},
|
|
157
|
+
child: any
|
|
158
|
+
): VNode<S> {
|
|
159
|
+
const { state, onclick, keyNames } = props
|
|
160
|
+
const classList = getClassList(props)
|
|
161
|
+
|
|
162
|
+
// action
|
|
163
|
+
const action_click = (state: S, e: Event) => {
|
|
164
|
+
const count = getValue(state, keyNames, 0)
|
|
165
|
+
const newState = setValue(state, keyNames, count + 1)
|
|
166
|
+
|
|
167
|
+
// ユーザーが指定したアクションとの結合
|
|
168
|
+
return concatAction(onclick, newState, e)
|
|
848
169
|
}
|
|
849
|
-
): { start: () => void, stop : () => void }
|
|
850
|
-
```
|
|
851
|
-
*ステートから独立して `requestAnimationFrame` により直接 DOM を変更します*
|
|
852
|
-
|
|
853
|
-
**パラメータ**
|
|
854
|
-
- props.ul : アニメーション対象の <ul> エレメント
|
|
855
|
-
- props.duration: 実行時間 (ms)
|
|
856
|
-
- props.interval: 待機時間 (ms)
|
|
857
|
-
- props.easing : easing 関数
|
|
858
|
-
|
|
859
|
-
**戻値**
|
|
860
|
-
- start(): アニメーションを開始
|
|
861
|
-
- stop() : アニメーションを停止
|
|
862
|
-
|
|
863
|
-
---
|
|
864
|
-
|
|
865
|
-
### InternalEffect
|
|
866
|
-
Dispatch の内部処理(finish / action)から呼び出されることを前提としたエフェクト
|
|
867
|
-
Action の戻り値としては返されず、Dispatch の実行フロー内で直接実行される
|
|
868
|
-
型としては `Effect<S>` と同一で「Dispatch 内部専用」という役割と設計意図を明示するための型エイリアス
|
|
869
|
-
|
|
870
|
-
```ts
|
|
871
|
-
type InternalEffect<S> = Effect<S>
|
|
872
|
-
```
|
|
873
|
-
|
|
874
|
-
**説明**
|
|
875
|
-
|
|
876
|
-
Dispatch で呼ばれるアクションでは、エフェクトを直接返すことはできません
|
|
877
|
-
しかし、非同期処理でエフェクトを使用したいこともあります
|
|
878
|
-
|
|
879
|
-
このときアクションを `(state: S) => S | [S, Effect<S>]` とせず `(state: S) => S | [S, InternalEffect<S>]`とすることで、エフェクトが戻り値とならないことを明示します ( Dispatch 内でエフェクトが戻せない罠対策です )
|
|
880
|
-
具体的には `requestAnimationFrame` などを使用して時間差で Dispatch してください
|
|
881
|
-
|
|
882
|
-
**ポイント**
|
|
883
|
-
|
|
884
|
-
- 戻り値として使用されず、Dispatch 内でのみ実行される
|
|
885
|
-
- `Effect<S>` と同一
|
|
886
|
-
- 内部専用であることを、型で明示
|
|
887
|
-
|
|
888
|
-
**Dispatch例**
|
|
889
|
-
|
|
890
|
-
```ts
|
|
891
|
-
return [state, (dispatch: Dispatch) => {
|
|
892
|
-
requestAnimationFrame(() =>
|
|
893
|
-
dispatch(state: S) => [state, effect]
|
|
894
|
-
)
|
|
895
|
-
}]
|
|
896
|
-
```
|
|
897
|
-
*requestAnimationFrame などで、Dispatch 外部に移動した後、Dispatch します (どうしても1フレーム遅延します)*
|
|
898
|
-
|
|
899
|
-
---
|
|
900
|
-
|
|
901
|
-
### RAFEvent
|
|
902
|
-
RAFTask で使用されるイベント
|
|
903
|
-
hyperapp で使用される通常のアクション と同一なものですが
|
|
904
|
-
`payload` と `Effect` の型名が再定義されています
|
|
905
|
-
|
|
906
|
-
```ts
|
|
907
|
-
type RAFEvent = <S> (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
|
|
908
|
-
```
|
|
909
|
-
|
|
910
|
-
---
|
|
911
|
-
|
|
912
|
-
### RAFTask
|
|
913
|
-
requestAnimationFrame (rAF) を管理するためのクラス
|
|
914
170
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
delay ?: number
|
|
923
|
-
action : RAFEvent<S>
|
|
924
|
-
finish ?: RAFEvent<S>
|
|
925
|
-
priority ?: number
|
|
926
|
-
extension?: Record<string, any>
|
|
927
|
-
})
|
|
928
|
-
|
|
929
|
-
// getter
|
|
930
|
-
id : string
|
|
931
|
-
duration : number
|
|
932
|
-
delay : number
|
|
933
|
-
action : RAFEvent<S>
|
|
934
|
-
finish : RAFEvent<S>
|
|
935
|
-
progress : number
|
|
936
|
-
deltaTime: number
|
|
937
|
-
|
|
938
|
-
// getter / setter
|
|
939
|
-
groupID : string | undefined
|
|
940
|
-
priority : number
|
|
941
|
-
extension: Record<string, any>
|
|
942
|
-
isDone : boolean
|
|
943
|
-
paused : boolean
|
|
944
|
-
|
|
945
|
-
// method
|
|
946
|
-
clone: RAFTask<S>
|
|
171
|
+
// vnode
|
|
172
|
+
return button({
|
|
173
|
+
type: "button",
|
|
174
|
+
...deleteKeys(props, "state", "keyNames"), // DOM に設定しない値を削除
|
|
175
|
+
class : classList.concat("MyButton").join(" "), // 取得したクラス名に MyButton を追加
|
|
176
|
+
onclick: action_click
|
|
177
|
+
}, child)
|
|
947
178
|
}
|
|
948
179
|
```
|
|
949
180
|
|
|
950
|
-
**constructor**
|
|
951
|
-
|
|
952
|
-
基本
|
|
953
|
-
- id : rAF のユニークID
|
|
954
|
-
- duration: 1回の実行時間 (ms)
|
|
955
|
-
- action : 毎フレームごとのアクション
|
|
956
|
-
|
|
957
|
-
拡張
|
|
958
|
-
- groupID : 任意のグループID
|
|
959
|
-
- delay : 初回実行までの待機時間 (ms)
|
|
960
|
-
- finish : 最終フレームで実行されるアクション
|
|
961
|
-
- priority : 処理の優先順位
|
|
962
|
-
- extension: 任意の拡張データ
|
|
963
|
-
|
|
964
|
-
**property**
|
|
965
|
-
|
|
966
|
-
getter
|
|
967
|
-
- id : rAF のユニークID
|
|
968
|
-
- duration : 1回の実行時間 (ms)
|
|
969
|
-
- delay : 初回実行までの待機時間 (ms)
|
|
970
|
-
- action : 毎フレームごとのアクション
|
|
971
|
-
- finish : 最終フレームで実行されるアクション
|
|
972
|
-
- progress : 進捗状況 (0 - 1)
|
|
973
|
-
- deltaTime: 前回アクションからの経過時間 (ms)
|
|
974
|
-
|
|
975
|
-
getter / setter
|
|
976
|
-
- groupID : 任意のグループID
|
|
977
|
-
- priority : 処理の優先順位
|
|
978
|
-
- extension: 任意の拡張データ
|
|
979
|
-
- isDone : 終了状況の取得 / 設定
|
|
980
|
-
- paused : 一時停止状況の取得 / 設定
|
|
981
|
-
|
|
982
|
-
**method**
|
|
983
|
-
|
|
984
|
-
- clone: 時間を初期化したクローンを作成して返す
|
|
985
|
-
|
|
986
181
|
---
|
|
987
182
|
|
|
988
|
-
|
|
989
|
-
RAFTask 配列をフレームごとに実行するサブスクリプション
|
|
183
|
+
- effect_toast: 設定した値を、一定時間経過後に元に戻します
|
|
990
184
|
|
|
185
|
+
例
|
|
991
186
|
```ts
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
### CSSProperty
|
|
1006
|
-
CSS設定用オブジェクト
|
|
1007
|
-
|
|
1008
|
-
```ts
|
|
1009
|
-
export interface CSSProperty {
|
|
1010
|
-
[selector: string]: {
|
|
1011
|
-
[name: string]: (progress: number) => string
|
|
1012
|
-
}
|
|
187
|
+
const action = (state: S) => {
|
|
188
|
+
return [
|
|
189
|
+
{
|
|
190
|
+
...state,
|
|
191
|
+
message: "ready"
|
|
192
|
+
},
|
|
193
|
+
effect_toast({
|
|
194
|
+
keyNames: ["message"],
|
|
195
|
+
value : "toast message",
|
|
196
|
+
duration: 1000
|
|
197
|
+
})
|
|
198
|
+
]
|
|
1013
199
|
}
|
|
1014
200
|
```
|
|
1015
201
|
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
- name: CSS プロパティ名
|
|
1019
|
-
- fn(progress): CSS 値を計算する関数
|
|
1020
|
-
|
|
1021
|
-
---
|
|
1022
|
-
|
|
1023
|
-
### createUnits
|
|
1024
|
-
CSSProperty を変換する補助関数
|
|
1025
|
-
selector から、doms を取得してセットにします
|
|
1026
|
-
|
|
1027
|
-
```ts
|
|
1028
|
-
export const createUnits = function (
|
|
1029
|
-
properties: CSSProperty[]
|
|
1030
|
-
): {
|
|
1031
|
-
doms : HTMLElement[],
|
|
1032
|
-
styles: {
|
|
1033
|
-
[name: string]: (progress: number) => string
|
|
1034
|
-
}
|
|
1035
|
-
}[]
|
|
1036
|
-
```
|
|
1037
|
-
|
|
1038
|
-
- properties: プロパティ配列
|
|
202
|
+
> `message` に 1秒間 "toast message" と表示された後\
|
|
203
|
+
> "ready" という値に戻ります
|
|
1039
204
|
|
|
1040
205
|
---
|
|
1041
206
|
|
|
1042
|
-
|
|
1043
|
-
subscription_RAFManager をベースにした CSS アニメーション RAFTask を作成する
|
|
1044
|
-
|
|
1045
|
-
```ts
|
|
1046
|
-
export const createRAFProperties = function <S> (
|
|
1047
|
-
props: {
|
|
1048
|
-
id : string
|
|
1049
|
-
groupID?: string
|
|
1050
|
-
duration: number
|
|
1051
|
-
delay ?: number
|
|
1052
|
-
|
|
1053
|
-
finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
|
|
1054
|
-
|
|
1055
|
-
priority ?: number
|
|
1056
|
-
extension?: Record<string, any>
|
|
207
|
+
**dom**
|
|
1057
208
|
|
|
1058
|
-
|
|
1059
|
-
}
|
|
1060
|
-
): RAFTask<S>
|
|
1061
|
-
```
|
|
209
|
+
- getScrollMargin: スクロール状態を取得
|
|
1062
210
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
- properties: セレクタとスタイル設定のセット配列
|
|
1066
|
-
|
|
1067
|
-
---
|
|
1068
|
-
|
|
1069
|
-
### effect_RAFProperties
|
|
1070
|
-
CSS プロパティをフレーム単位で段階的に変更
|
|
211
|
+
> 無限スクロールなどに利用できます
|
|
1071
212
|
|
|
213
|
+
例:
|
|
1072
214
|
```ts
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
id : string
|
|
1076
|
-
groupID?: string
|
|
1077
|
-
duration: number
|
|
1078
|
-
delay ?: number
|
|
1079
|
-
|
|
1080
|
-
finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
|
|
1081
|
-
|
|
1082
|
-
priority ?: number
|
|
1083
|
-
extension?: Record<string, any>
|
|
215
|
+
const action = (state: S, e: Event) => {
|
|
216
|
+
const scrollMargin = getScrollMargin(e)
|
|
1084
217
|
|
|
1085
|
-
|
|
1086
|
-
|
|
218
|
+
if (scrollMargin.bottom < 100) {
|
|
219
|
+
// 残り 100px で、アイテムの追加処理などを実行
|
|
220
|
+
const newState = {
|
|
221
|
+
...state,
|
|
222
|
+
count: count + 10
|
|
223
|
+
}
|
|
224
|
+
return newState
|
|
1087
225
|
}
|
|
1088
|
-
): (dispatch : Dispatch<S>) => void
|
|
1089
|
-
```
|
|
1090
|
-
|
|
1091
|
-
props は、基本的に RAFTask の値
|
|
1092
|
-
|
|
1093
|
-
- properties: セレクタとスタイル設定のセット配列
|
|
1094
|
-
- keyNames : RAFTask 配列までのパス
|
|
1095
|
-
|
|
1096
|
-
---
|
|
1097
|
-
|
|
1098
|
-
### TranslateState
|
|
1099
|
-
Translate 管理用オブジェクト
|
|
1100
226
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
```ts
|
|
1104
|
-
export interface TranslateState {
|
|
1105
|
-
width : number
|
|
1106
|
-
index : number
|
|
1107
|
-
total : number
|
|
1108
|
-
easing: (t: number) => number
|
|
227
|
+
return state
|
|
1109
228
|
}
|
|
1110
229
|
```
|
|
1111
230
|
|
|
1112
|
-
- width : 移動量
|
|
1113
|
-
- index : 先頭のインデックス
|
|
1114
|
-
- total : 子の数
|
|
1115
|
-
- easing: easing 関数
|
|
1116
|
-
|
|
1117
231
|
---
|
|
1118
232
|
|
|
1119
|
-
|
|
1120
|
-
subscription_RAFManager をベースにした Translate アニメーション RAFTask を作成する
|
|
233
|
+
- withLoadingDialog: task 実行中、ローディングダイアログを表示します
|
|
1121
234
|
|
|
1122
|
-
|
|
235
|
+
> onCancel を指定した場合は、Esc キーで onCancel が呼び出されます
|
|
1123
236
|
|
|
237
|
+
例
|
|
1124
238
|
```ts
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
delay : number
|
|
1131
|
-
|
|
1132
|
-
finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
|
|
1133
|
-
|
|
1134
|
-
priority ?: number
|
|
1135
|
-
extension?: Record<string, any>
|
|
1136
|
-
|
|
1137
|
-
translateState: TranslateState
|
|
1138
|
-
}
|
|
1139
|
-
): RAFTask<S>
|
|
1140
|
-
```
|
|
1141
|
-
|
|
1142
|
-
- props は、基本的に RAFTask の値
|
|
1143
|
-
- translateState: Translate情報
|
|
1144
|
-
|
|
1145
|
-
---
|
|
1146
|
-
|
|
1147
|
-
### effect_translateStart
|
|
1148
|
-
`subscription_RAFManager` をベースにした Translate アニメーションエフェクトです
|
|
1149
|
-
|
|
1150
|
-
*実験用コードのため、npm 非公開です*
|
|
1151
|
-
|
|
1152
|
-
```ts
|
|
1153
|
-
export const effect_translateStart = function <S> (
|
|
1154
|
-
props: {
|
|
1155
|
-
id : string
|
|
1156
|
-
groupID?: string
|
|
1157
|
-
duration: number
|
|
1158
|
-
delay : number
|
|
1159
|
-
|
|
1160
|
-
finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
|
|
1161
|
-
|
|
1162
|
-
priority ?: number
|
|
1163
|
-
extension?: Record<string, any>
|
|
1164
|
-
|
|
1165
|
-
easing ?: (t: number) => number
|
|
1166
|
-
|
|
1167
|
-
keyNames: string[]
|
|
1168
|
-
}
|
|
1169
|
-
): (dispatch: Dispatch<S>) => void
|
|
1170
|
-
```
|
|
1171
|
-
|
|
1172
|
-
- props は、基本的に RAFTask の値
|
|
1173
|
-
- easing : easing 関数
|
|
1174
|
-
- keyNames: RAFTask 配列までのパス
|
|
1175
|
-
|
|
1176
|
-
**説明**
|
|
1177
|
-
|
|
1178
|
-
marquee は単純な DOM に対しての副作用で、Translate としての動作は
|
|
1179
|
-
ステート経由で rAF を制御しているこちらに集約されることになります
|
|
1180
|
-
|
|
1181
|
-
marquee はステートを通さず直接 DOM に対して副作用を発生させるため
|
|
1182
|
-
用途によっては marquee に優位性があります
|
|
1183
|
-
|
|
1184
|
-
- marquee : DOM 直接操作。軽量で即時反映
|
|
1185
|
-
- effect_translateStart : Hyperapp のステート経由で管理。RAFManager と連携可能
|
|
1186
|
-
|
|
1187
|
-
### effect_translateRollback
|
|
1188
|
-
アニメーション中のTranslateを、元の位置に戻す
|
|
1189
|
-
|
|
1190
|
-
*実験用コードのため、npm 非公開です*
|
|
1191
|
-
|
|
1192
|
-
```ts
|
|
1193
|
-
export const effect_translateRollback = function <S> (
|
|
1194
|
-
props: {
|
|
1195
|
-
id : string
|
|
1196
|
-
keyNames: string[]
|
|
1197
|
-
paused ?: boolean
|
|
1198
|
-
finish ?: RAFEvent<S>
|
|
1199
|
-
}
|
|
1200
|
-
): (dispatch: Dispatch<S>)
|
|
1201
|
-
```
|
|
1202
|
-
|
|
1203
|
-
- id : ユニークID
|
|
1204
|
-
- keyNames: RAFTask 配列までのパス
|
|
1205
|
-
- paused : 実行後、一時停止するか
|
|
1206
|
-
- finish : 実行後に呼び出されるイベント
|
|
1207
|
-
|
|
1208
|
-
**注意**
|
|
1209
|
-
`effect_translateStart` に依存しています
|
|
1210
|
-
上記エフェクトでループしている id に対して使用します
|
|
1211
|
-
|
|
1212
|
-
---
|
|
1213
|
-
|
|
1214
|
-
### effect_translateRollforward
|
|
1215
|
-
アニメーション中のTranslateを、早送りする
|
|
1216
|
-
|
|
1217
|
-
*実験用コードのため、npm 非公開です*
|
|
1218
|
-
|
|
1219
|
-
```ts
|
|
1220
|
-
export const effect_translateRollforward = function <S> (
|
|
1221
|
-
props: {
|
|
1222
|
-
id : string
|
|
1223
|
-
keyNames: string[]
|
|
1224
|
-
paused ?: boolean
|
|
1225
|
-
finish ?: RAFEvent<S>
|
|
1226
|
-
}
|
|
1227
|
-
): (dispatch: Dispatch<S>)
|
|
239
|
+
const json = await withLoadingDialog(async () => {
|
|
240
|
+
const res = await fetch("/api/hoge")
|
|
241
|
+
if (!res.ok) throw new Error("error: task")
|
|
242
|
+
return res.json()
|
|
243
|
+
})
|
|
1228
244
|
```
|
|
1229
245
|
|
|
1230
|
-
- id : ユニークID
|
|
1231
|
-
- keyNames: RAFTask 配列までのパス
|
|
1232
|
-
- paused : 実行後、一時停止するか
|
|
1233
|
-
- finish : 実行後に呼び出されるイベント
|
|
1234
|
-
|
|
1235
|
-
**注意**
|
|
1236
|
-
`effect_translateStart` に依存しています
|
|
1237
|
-
上記エフェクトでループしている id に対して使用します
|
|
1238
|
-
|
|
1239
246
|
---
|
|
1240
247
|
|
|
1241
|
-
|
|
1242
|
-
Translateを任意のインデックスまで移動する
|
|
1243
|
-
|
|
1244
|
-
*実験用コードのため、npm 非公開です*
|
|
1245
|
-
|
|
1246
|
-
```ts
|
|
1247
|
-
export const effect_translateSlide = function <S> (
|
|
1248
|
-
props: {
|
|
1249
|
-
id : string
|
|
1250
|
-
keyNames: string[]
|
|
1251
|
-
index : number
|
|
1252
|
-
paused ?: boolean
|
|
1253
|
-
finish ?: RAFEvent<S>
|
|
1254
|
-
}
|
|
1255
|
-
): (dispatch: Dispatch<S>) => void
|
|
1256
|
-
```
|
|
248
|
+
**animation**
|
|
1257
249
|
|
|
1258
|
-
-
|
|
1259
|
-
- keyNames: RAFTask 配列までのパス
|
|
1260
|
-
- index : 移動先のインデックス
|
|
1261
|
-
- paused : 実行後、一時停止するか
|
|
1262
|
-
- finish : 実行後に呼び出されるイベント
|
|
1263
|
-
|
|
1264
|
-
**注意**
|
|
1265
|
-
`effect_translateStart` に依存しています
|
|
1266
|
-
上記エフェクトでループしている id に対して使用します
|
|
1267
|
-
|
|
1268
|
-
---
|
|
250
|
+
- subscription_RAFManager: RAFTask 配列の実行を管理するサブスクリプション
|
|
1269
251
|
|
|
1270
|
-
|
|
1271
|
-
|
|
252
|
+
> ステートに `RAFTask[]` の配列を用意します\
|
|
253
|
+
> `RAFTask` が追加されると、自動的にタスクの実行管理を開始します\
|
|
254
|
+
> タスクが完了すると、自動的に `RAFTask[]` から削除されます
|
|
1272
255
|
|
|
256
|
+
例:
|
|
1273
257
|
```ts
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
easeInQuart : (t: number) => t * t * t * t,
|
|
1293
|
-
easeOutQuart : (t: number) => 1 - Math.pow(1 - t, 4),
|
|
1294
|
-
easeInOutQuart: (t: number) => t < 0.5
|
|
1295
|
-
? 8 * t * t * t * t
|
|
1296
|
-
: 1 - Math.pow(-2 * t + 2, 4) / 2,
|
|
1297
|
-
|
|
1298
|
-
// back (跳ねる)
|
|
1299
|
-
easeOutBack: (t: number) => {
|
|
1300
|
-
const c1 = 1.70158
|
|
1301
|
-
const c3 = c1 + 1
|
|
1302
|
-
return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2)
|
|
1303
|
-
},
|
|
1304
|
-
|
|
1305
|
-
// bounce
|
|
1306
|
-
easeOutBounce: (t: number) => {
|
|
1307
|
-
const n1 = 7.5625
|
|
1308
|
-
const d1 = 2.75
|
|
1309
|
-
|
|
1310
|
-
if (t < 1 / d1) {
|
|
1311
|
-
return n1 * t * t
|
|
1312
|
-
} else if (t < 2 / d1) {
|
|
1313
|
-
return n1 * (t -= 1.5 / d1) * t + 0.75
|
|
1314
|
-
} else if (t < 2.5 / d1) {
|
|
1315
|
-
return n1 * (t -= 2.25 / d1) * t + 0.9375
|
|
1316
|
-
} else {
|
|
1317
|
-
return n1 * (t -= 2.625 / d1) * t + 0.984375
|
|
258
|
+
app({
|
|
259
|
+
node,
|
|
260
|
+
init: [
|
|
261
|
+
{
|
|
262
|
+
tasks : [] as RAFTask[],
|
|
263
|
+
message: ""
|
|
264
|
+
},
|
|
265
|
+
(dispatch: S) => {
|
|
266
|
+
const newTask = new RAFTask({
|
|
267
|
+
id : "uniqueID",
|
|
268
|
+
duration: 2000,
|
|
269
|
+
action : (state: S, task: RAFTask<S>) => {
|
|
270
|
+
return {
|
|
271
|
+
...state,
|
|
272
|
+
message: `progress = ${ task.progress }`
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
})
|
|
1318
276
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
return t === 0
|
|
1326
|
-
? 0
|
|
1327
|
-
: t === 1
|
|
1328
|
-
? 1
|
|
1329
|
-
: Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1
|
|
1330
|
-
}
|
|
1331
|
-
}
|
|
1332
|
-
```
|
|
1333
|
-
|
|
1334
|
-
## hyperapp-is/animationView
|
|
1335
|
-
|
|
1336
|
-
### CarouselState
|
|
1337
|
-
Carousel コンポーネント情報
|
|
1338
|
-
RAFTask.extension に保存されます
|
|
1339
|
-
|
|
1340
|
-
```ts
|
|
1341
|
-
export interface CarouselState <S> {
|
|
1342
|
-
id : string
|
|
1343
|
-
step: number
|
|
1344
|
-
|
|
1345
|
-
// option
|
|
1346
|
-
groupID ?: string
|
|
1347
|
-
duration ?: number
|
|
1348
|
-
delay ?: number
|
|
1349
|
-
priority ?: number
|
|
1350
|
-
extension?: Record<string, any>
|
|
1351
|
-
|
|
1352
|
-
// event
|
|
1353
|
-
action?: RAFEvent<S>
|
|
1354
|
-
finish?: RAFEvent<S>
|
|
1355
|
-
|
|
1356
|
-
// animation
|
|
1357
|
-
easing?: (t: number) => number
|
|
1358
|
-
|
|
1359
|
-
// report
|
|
1360
|
-
reportPageIndex?: string[]
|
|
1361
|
-
}
|
|
1362
|
-
```
|
|
1363
|
-
基本的には `RAFTask` に準拠します
|
|
1364
|
-
カルーセルを動作せるため `effect_InitCarousel` に渡すための値です
|
|
1365
|
-
|
|
1366
|
-
必須項目
|
|
1367
|
-
- id: `Carousel` コンポーネントの id を指定してください
|
|
1368
|
-
- step: 移動するアイテムの数で、負の数は逆回転。0 は停止となります
|
|
1369
|
-
|
|
1370
|
-
拡張項目
|
|
1371
|
-
- easing: アニメーションの動作を指定する関数
|
|
1372
|
-
指定しない場合は `(t: number) => t` (linear) となります
|
|
1373
|
-
|
|
1374
|
-
- reportPagreIndex: 現在一番左端に表示されているアイテムのインデックスを受けるパス
|
|
1375
|
-
コントロールバーを自作したい時などに利用できます
|
|
1376
|
-
|
|
1377
|
-
---
|
|
1378
|
-
|
|
1379
|
-
### CarouselController
|
|
1380
|
-
外部から Carousel コンポーネントを操作するためのクラス
|
|
1381
|
-
RAFTask.extension に保存されます
|
|
1382
|
-
|
|
1383
|
-
```ts
|
|
1384
|
-
export interface CarouselController <S> {
|
|
1385
|
-
step : (rafTask: RAFTask<S>, delta: number, skipSpeedRate?: number) => Promise <RAFTask<S>>
|
|
1386
|
-
moveTo: (rafTask: RAFTask<S>, index: number, skipSpeedRage?: number) => Promise <RAFTask<S>>
|
|
1387
|
-
}
|
|
1388
|
-
```
|
|
1389
|
-
|
|
1390
|
-
- step: `delta` で指定した方向にページを移動します (相対値)
|
|
1391
|
-
スキップ時のスピードは、変更前の `duration` に `skipSpeedRate` を乗じたものになります
|
|
1392
|
-
終了時に処理を割り込ませたい場合は、`Promsie` により処理します
|
|
1393
|
-
|
|
1394
|
-
- moveTo: `index` で指定したページに移動します (絶対値)
|
|
1395
|
-
スキップ時のスピードは、変更前の `duration` に `skipSpeedRate` を乗じたものになります
|
|
1396
|
-
終了時に処理を割り込ませたい場合は、`Promsie` により処理します
|
|
1397
|
-
|
|
1398
|
-
### Carousel
|
|
1399
|
-
カルーセルコンポーネントです
|
|
1400
|
-
`CarouselState` を引数に `effect_InitCarousel` を実行することで動作開始します
|
|
1401
|
-
`subscription_RAFManager` を使用するので、予め `subscriptions` に追加してください
|
|
1402
|
-
|
|
1403
|
-
```ts
|
|
1404
|
-
export const Carousel = function <S> (
|
|
1405
|
-
props: {
|
|
1406
|
-
state : S
|
|
1407
|
-
id : string
|
|
1408
|
-
keyNames : string[]
|
|
1409
|
-
controlButton?: boolean
|
|
1410
|
-
controlBar ?: boolean
|
|
1411
|
-
skipSpeedRate?: number
|
|
1412
|
-
[key: string] : any
|
|
1413
|
-
},
|
|
1414
|
-
children: any
|
|
1415
|
-
): VNode<S>
|
|
1416
|
-
```
|
|
1417
|
-
|
|
1418
|
-
- state : ステート
|
|
1419
|
-
- id : ユニークID (DOM の id)
|
|
1420
|
-
- keyNames : RAFTask 配列までのパス
|
|
1421
|
-
- controlButton: 操作ボタンを表示するか (未実装)
|
|
1422
|
-
- controlBar : 操作バーを表示するか
|
|
1423
|
-
- skipSpeedRate: スキップ時の動作速度
|
|
1424
|
-
|
|
1425
|
-
### effect_InitCarousel
|
|
1426
|
-
カルーセルを初期化し起動するエフェクト
|
|
1427
|
-
|
|
1428
|
-
```ts
|
|
1429
|
-
export const effect_InitCarousel = function <S> (
|
|
1430
|
-
keyNames : string[],
|
|
1431
|
-
carouselState: CarouselState<S>
|
|
1432
|
-
): (dispatch: Dispatch<S>) => void
|
|
277
|
+
],
|
|
278
|
+
view,
|
|
279
|
+
subscription: (state: S) => [
|
|
280
|
+
subscription_RAFManager(state, ["tasks"])
|
|
281
|
+
]
|
|
282
|
+
})
|
|
1433
283
|
```
|
|
1434
284
|
|
|
1435
|
-
|
|
1436
|
-
- carouselState: カルーセルの動作設定
|
|
285
|
+
`RAFTask` クラスの作成には、最低限次の項目を設定する必要があります
|
|
1437
286
|
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
スクロールの余白を管理するオブジェクト
|
|
1442
|
-
|
|
1443
|
-
```ts
|
|
1444
|
-
export interface ScrollMargin {
|
|
1445
|
-
top : number
|
|
1446
|
-
left : number
|
|
1447
|
-
right : number
|
|
1448
|
-
bottom: number
|
|
1449
|
-
}
|
|
1450
|
-
```
|
|
1451
|
-
|
|
1452
|
-
- top : 上までの余白
|
|
1453
|
-
- left : 左までの余白
|
|
1454
|
-
- right : 右までの余白
|
|
1455
|
-
- bottom: 下までの余白
|
|
287
|
+
- id: タスク管理用のユニークIDを設定してください。DOMのIDとは関係ありません
|
|
288
|
+
- duration: 実行時間をミリ秒で指定してください
|
|
289
|
+
- action: 1フレームごとの処理内容を指定します。進捗状況は `RAFTask.progress` から取得できます
|
|
1456
290
|
|
|
1457
291
|
---
|
|
1458
292
|
|
|
1459
|
-
|
|
1460
|
-
スクロールの余白を取得
|
|
293
|
+
- effect_RAFProperties: RAFTask を利用して CSS プロパティをアニメーションする Effect
|
|
1461
294
|
|
|
1462
|
-
|
|
1463
|
-
export const getScrollMargin = function (e: Event): ScrollMargin
|
|
1464
|
-
```
|
|
1465
|
-
|
|
1466
|
-
- e: イベント
|
|
1467
|
-
|
|
1468
|
-
---
|
|
1469
|
-
|
|
1470
|
-
### MatrixState
|
|
1471
|
-
transform 情報
|
|
295
|
+
> CSSProperty により、複数の CSS アニメーションを同時処理することが可能です
|
|
1472
296
|
|
|
297
|
+
例:
|
|
1473
298
|
```ts
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
scale: {
|
|
1482
|
-
x: number
|
|
1483
|
-
y: number
|
|
1484
|
-
z: number
|
|
1485
|
-
}
|
|
299
|
+
const action = (state: S) => {
|
|
300
|
+
const property: CSSProperty = {
|
|
301
|
+
"button": {
|
|
302
|
+
"fontSize": (progress: number) => `${ 1 + 1 * progress }rem`,
|
|
303
|
+
"color" : (progress: number) => `rgb(${ 255 * progress }, 0, 0)`
|
|
304
|
+
}
|
|
305
|
+
}
|
|
1486
306
|
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
307
|
+
return [state, effect_RAFProperties({
|
|
308
|
+
id : "uniqueID",
|
|
309
|
+
duration : 1000,
|
|
310
|
+
properties: [ property ]
|
|
311
|
+
})]
|
|
1492
312
|
}
|
|
1493
|
-
}
|
|
1494
|
-
```
|
|
1495
|
-
|
|
1496
|
-
---
|
|
1497
|
-
|
|
1498
|
-
### getMatrixState
|
|
1499
|
-
DOM から transfrom 情報を取得する
|
|
1500
|
-
|
|
1501
|
-
```ts
|
|
1502
|
-
export const getMatrixState = (
|
|
1503
|
-
dom: HTMLElement
|
|
1504
|
-
): MatrixState | null
|
|
1505
313
|
```
|
|
1506
314
|
|
|
1507
|
-
|
|
315
|
+
> すべてのボタンに対して、1秒かけて文字サイズを拡大し、文字色を赤へ変化させるアニメーションのサンプルです
|
|
1508
316
|
|
|
1509
317
|
---
|
|
1510
318
|
|
|
1511
|
-
|
|
1512
|
-
ステートに存在時間制限付きの値を設定
|
|
319
|
+
**services**
|
|
1513
320
|
|
|
1514
|
-
|
|
321
|
+
- GoogleAuth: Google Identity Services を利用した Google 認証クラス
|
|
1515
322
|
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
keyNames: string[],
|
|
1519
|
-
id : string,
|
|
1520
|
-
timeout : number,
|
|
1521
|
-
value : T,
|
|
1522
|
-
reset : T | null = null
|
|
1523
|
-
): (dispatch: Dispatch<S>) => void
|
|
1524
|
-
```
|
|
1525
|
-
|
|
1526
|
-
- keyNames: 値までのパス
|
|
1527
|
-
- id : ユニークID
|
|
1528
|
-
- timeout : 存在可能時間 (ms)
|
|
1529
|
-
- value : 一時的に設定する値
|
|
1530
|
-
- reset : タイムアウト後に設定する値
|
|
1531
|
-
|
|
1532
|
-
---
|
|
1533
|
-
|
|
1534
|
-
### effect_nodesInitialize
|
|
1535
|
-
VNode マウント後の初期化処理を実行
|
|
1536
|
-
|
|
1537
|
-
*実験用コードのため、npm 非公開です*
|
|
323
|
+
> ログインボタンを作成しない場合は、`new GoogleAuth({ clientId: "hoge" })` だけで利用できます\
|
|
324
|
+
> インスタンス作成後、`initialize` を実行すると認証処理を開始します
|
|
1538
325
|
|
|
326
|
+
例
|
|
1539
327
|
```ts
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
id : string
|
|
1543
|
-
event: (state: S, element: Element) => S | [S, Effect<S>]
|
|
1544
|
-
}[]
|
|
1545
|
-
): (dispatch: Dispatch<S>) => void
|
|
1546
|
-
```
|
|
1547
|
-
|
|
1548
|
-
- nodes : 初期化対象ノード定義配列
|
|
1549
|
-
- nodes.id : ユニークID
|
|
1550
|
-
- nodes.event: 初期化イベント
|
|
1551
|
-
|
|
1552
|
-
---
|
|
1553
|
-
|
|
1554
|
-
### subscription_nodesCleanup
|
|
1555
|
-
DOM 消失時にクリーンアップ処理を実行
|
|
1556
|
-
|
|
1557
|
-
*実験用コードのため、npm 非公開です*
|
|
1558
|
-
|
|
1559
|
-
```ts
|
|
1560
|
-
export const subscription_nodesCleanup = function <S>(
|
|
1561
|
-
nodes: {
|
|
1562
|
-
id : string
|
|
1563
|
-
finalize: (state: S) => S | [S, Effect<S>]
|
|
1564
|
-
}[]
|
|
1565
|
-
): Subscription<S>[]
|
|
1566
|
-
```
|
|
1567
|
-
|
|
1568
|
-
- nodes : クリーンアップ対象ノード定義配列
|
|
1569
|
-
- nodes.id : ユニークID
|
|
1570
|
-
- nodes.finalize: 終了時イベント
|
|
1571
|
-
|
|
1572
|
-
---
|
|
1573
|
-
|
|
1574
|
-
### subscription_nodesLifecycleByIds
|
|
1575
|
-
ステート上の ID 配列変化に応じて initialize / finalize を自動管理
|
|
1576
|
-
|
|
1577
|
-
*実験用コードのため、npm 非公開です*
|
|
1578
|
-
|
|
1579
|
-
```ts
|
|
1580
|
-
export const subscription_nodesLifecycleByIds = function <S> (
|
|
1581
|
-
keyNames: string[],
|
|
1582
|
-
nodes: {
|
|
1583
|
-
id : string
|
|
1584
|
-
initialize: (state: S, element: Element | null) => S | [S, Effect<S>]
|
|
1585
|
-
finalize : (state: S, element: Element | null) => S | [S, Effect<S>]
|
|
1586
|
-
}[]
|
|
1587
|
-
): Subscription<S>[]
|
|
1588
|
-
```
|
|
1589
|
-
|
|
1590
|
-
- keyNames : 文字配列までのパス
|
|
1591
|
-
- nodes : 監視対象ノード定義配列
|
|
1592
|
-
- nodes.id : ユニークID
|
|
1593
|
-
- nodes.initialize: 初期化イベント
|
|
1594
|
-
- nodes.finalize : 終了時イベント
|
|
1595
|
-
|
|
1596
|
-
---
|
|
1597
|
-
|
|
1598
|
-
### getGoogle
|
|
1599
|
-
Google GIS 変数を取得する
|
|
1600
|
-
|
|
1601
|
-
```ts
|
|
1602
|
-
export const getGoogle = async (): Promise<Google>
|
|
1603
|
-
```
|
|
1604
|
-
|
|
1605
|
-
`<script src="https://accounts.google.com/gsi/client">` を読み込み、`window.google`の値(Promise結果)返却
|
|
1606
|
-
|
|
1607
|
-
---
|
|
1608
|
-
|
|
1609
|
-
### getGoogleAuthResult
|
|
1610
|
-
ユーザートークンから、ユーザー情報を取得する
|
|
1611
|
-
|
|
1612
|
-
```ts
|
|
1613
|
-
export const getGoogleAuthResult = (idToken: string): GoogleAuthResult
|
|
1614
|
-
---
|
|
1615
|
-
|
|
1616
|
-
### getAccessToken
|
|
1617
|
-
Googleのaccess token を取得
|
|
1618
|
-
|
|
1619
|
-
```ts
|
|
1620
|
-
export const getAccessToken = (config: GetAccessTokenConfig): Promise<string>
|
|
1621
|
-
```
|
|
1622
|
-
|
|
1623
|
-
```ts
|
|
1624
|
-
export interface GetAccessTokenConfig {
|
|
1625
|
-
clientId: string
|
|
1626
|
-
scope : GoogleScope[]
|
|
1627
|
-
prompt ?: "none" | "select_account" | "consent" // default: "select_account"
|
|
328
|
+
const config: GoogleAuthConfig = {
|
|
329
|
+
clientId: "your google api key"
|
|
1628
330
|
}
|
|
1629
|
-
```
|
|
1630
331
|
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
- prompt ?: ログイン制御 `none` の場合、先にログインしていなければエラーとなります
|
|
1634
|
-
|
|
1635
|
-
---
|
|
1636
|
-
|
|
1637
|
-
### GoogleAuth
|
|
1638
|
-
Google 認証をラップしたクラス
|
|
1639
|
-
|
|
1640
|
-
```ts
|
|
1641
|
-
interface GoogleAuthConfig {
|
|
1642
|
-
clientId : string
|
|
1643
|
-
autoSelect?: boolean // default: true
|
|
1644
|
-
uxMode ?: "popup" | "redirect" // default: "popup"
|
|
332
|
+
const option: GoogleButtonOption = {
|
|
333
|
+
renderButton: document.querySelector("article")
|
|
1645
334
|
}
|
|
1646
335
|
|
|
1647
|
-
|
|
1648
|
-
renderButton?: HTMLElement
|
|
1649
|
-
theme ?: "outline" | "filled_blue" | "filled_black" // default: outline
|
|
1650
|
-
size ?: "large" | "medium" | "small" // default: medium
|
|
1651
|
-
text ?: "signin_with" | "signup_with" | "continue_with" // default: signin_with
|
|
1652
|
-
shape ?: "rectangular" | "pill" | "circle" | "square" // default: rectangular
|
|
1653
|
-
}
|
|
336
|
+
const auth = new GoogleAuth(config, option)
|
|
1654
337
|
|
|
1655
|
-
|
|
1656
|
-
idToken
|
|
1657
|
-
user
|
|
1658
|
-
}
|
|
338
|
+
auth.initialize().then((res: GoogleAuthResult) => {
|
|
339
|
+
const idToken = res.idToken
|
|
340
|
+
const user = res.user
|
|
1659
341
|
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
email : string
|
|
1663
|
-
picture: string
|
|
1664
|
-
sub : string
|
|
1665
|
-
}
|
|
1666
|
-
```
|
|
342
|
+
alert("ログイン成功")
|
|
343
|
+
})
|
|
1667
344
|
|
|
1668
|
-
```ts
|
|
1669
|
-
class GoogleAuth {
|
|
1670
|
-
constructor (config: GoogleAuthConfig, option?: GoogleButtonOptions)
|
|
1671
|
-
async initialize(): Promise<GoogleAuthResult | null>
|
|
1672
|
-
logout (hit: string): void
|
|
1673
|
-
}
|
|
1674
345
|
```
|
|
1675
|
-
|
|
1676
|
-
*MEMO*
|
|
1677
|
-
必ず一度だけ `initialize` を実行します
|
|
1678
|
-
プロンプトがスキップされた場合 `null` が返ります
|
|
1679
|
-
`logout` を実行したあとであれば `initialize` を再実行することが可能です
|
|
1680
|
-
`logout` 前に 2度 `initialize` を実行した場合は、エラーが発生します
|
|
1681
|
-
`logout` の `hit` は `email' か 'sub` を指定する必要があります
|
|
1682
|
-
|