hyperapp-is 0.1.5 → 0.1.7

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 CHANGED
@@ -46,6 +46,7 @@ import {
46
46
  Carousel, effect_InitCarousel
47
47
  } from "hyperapp-is"
48
48
 
49
+ // State
49
50
  interface State {
50
51
  tasks: RAFTask<State>[]
51
52
  }
@@ -54,8 +55,10 @@ const initState: State = {
54
55
  tasks: []
55
56
  }
56
57
 
58
+ // Entry Point
57
59
  app({
58
60
  node: document.getElementById("app") as HTMLElement,
61
+
59
62
  init: [initState, effect_InitCarousel(["tasks"], {
60
63
  id : "carousel",
61
64
  duration: 2000,
@@ -104,4 +107,1332 @@ https://github.com/is4416/hyperapp-is
104
107
 
105
108
  ## License
106
109
 
107
- MIT
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
+
148
+ **core / navigator.ts**
149
+ - [Keys_NavigatorItem](#keys_navigatoritem)
150
+ - [NavigatorItem](#navigatoritem)
151
+ - [JsonEntry](#jsonentry)
152
+ - [NavigatorColumn](#navigatorcolumn)
153
+ - [convertJsonToNavigatorItem](#convertjsontonavigatoritem)
154
+ - [getParentItems](#getparentitems)
155
+ - [NavigatorFinder](#navigatorfinder)
156
+
157
+ **animation / step.ts**
158
+ - [effect_throwMessageStart](#effect_throwmessagestart)
159
+ - [effect_throwMessagePause](#effect_throwmessagepause--effect_throwmessageresume)
160
+ - [effect_throwMessageResume](#effect_throwmessagepause--effect_throwmessageresume)
161
+ - [marquee](#marquee)
162
+
163
+ **animation / raf.ts**
164
+ - [InternalEffect](#internaleffect)
165
+ - [RAFEvent](#rafevent)
166
+ - [RAFTask](#raftask)
167
+ - [subscription_RAFManager](#subscription_rafmanager)
168
+
169
+ **animation / properties.ts**
170
+ - [CSSProperty](#cssproperty)
171
+ - [createUnits](#createunits)
172
+ - [createRAFProperties](#createrafproperties)
173
+ - [effect_RAFProperties](#effect_rafproperties)
174
+
175
+ **animation / easing.ts**
176
+ - [progress_easing](#progress_easing)
177
+
178
+ **animation / translate.ts**
179
+ - [TranslateState](#translatestate)
180
+ - [createRAFTranslate](#createraftranslate)
181
+ - [effect_translateStart](#effect_translatestart)
182
+ - [effect_translateRollback](#effect_translaterollback)
183
+ - [effect_translateRollforward](#effect_translaterollforward)
184
+ - [effect_translateSlide](#effect_translateslide)
185
+
186
+ **animationView / carouselts**
187
+ - [CarouselState](#carouselstate)
188
+ - [CarouselController](#carouselcontroller)
189
+ - [Carousel](#carousel)
190
+ - [effect_InitCarousel](#effect_initcarousel)
191
+
192
+ **dom / utils.ts**
193
+ - [ScrollMargin](#scrollmargin)
194
+ - [getScrollMargin](#getscrollmargin)
195
+ - [MatrixState](#matrixstate)
196
+ - [getMatrixState](#getmatrixstate)
197
+
198
+ **dom / lifecycle.ts**
199
+ - [effect_setTimedValue](#effect_settimedvalue)
200
+ - [effect_nodesInitialize](#effect_nodesinitialize)
201
+ - [subscription_nodesCleanup](#subscription_nodescleanup)
202
+ - [subscription_nodesLifecycleByIds](#subscription_nodeslifecyclebyids)
203
+
204
+ ## source file / ソースファイル
205
+
206
+ ```
207
+ src
208
+ └ hyperapp-is
209
+ ├ index.ts
210
+
211
+ ├ core
212
+ │ ├ state.ts
213
+ │ │ Keys
214
+ │ │ getValue, setValue, getLocalState, setLocalState, createLocalKey
215
+ │ │
216
+ │ ├ component.ts
217
+ │ │ Keys_String, Keys_ArrayString
218
+ │ │ el, concatAction, getClassList, deleteKeys
219
+ │ │ Route, SelectButton, OptionButton
220
+ │ │
221
+ │ └ navigator.ts
222
+ │ Keys_NavigatorItem, NavigatorItem, JsonEntry, NavigatorColumn
223
+ │ convertJsonToNavigatorItem, getParentItems, NavigatorFinder
224
+
225
+ ├ animation
226
+ │ ├ step.ts
227
+ │ │ effect_throwMessageStart, effect_throwMessagePause, effect_throwMessageResume, marquee
228
+ │ │
229
+ │ ├ raf.ts
230
+ │ │ InternalEffect
231
+ │ │ RAFEvent
232
+ │ │ RAFTask
233
+ │ │ subscription_RAFManager
234
+ │ │
235
+ │ ├ properties.ts
236
+ │ │ CSSProperty
237
+ │ │ createRAFProperties
238
+ │ │ effect_RAFProperties
239
+ │ │
240
+ │ ├ easing.ts
241
+ │ │ progress_easing
242
+ │ │
243
+ │ └ translate.ts
244
+ │ TranslateState
245
+ │ createRAFTranslate
246
+ │ effect_translateStart
247
+ │ effect_translateRollback
248
+ │ effect_translateRollforward
249
+ │ effect_translateSlide
250
+
251
+ ├ animationView
252
+ │ └ carousel.ts
253
+
254
+ └ dom
255
+ ├ utils.ts
256
+ │ ScrollMargin
257
+ │ getScrollMargin
258
+ │ MatrixState
259
+ │ getMatrixState
260
+
261
+ └ lifecycle.ts
262
+ effect_setTimedValue
263
+ effect_nodesInitialize
264
+ subscription_nodesCleanup
265
+ subscription_nodesLifecycleByIds
266
+ ```
267
+
268
+ ## hyperapp-is/core
269
+
270
+ ### Keys
271
+ ステートの任意の値までのパスを表す、文字配列の型エイリアス
272
+
273
+ ```ts
274
+ export type Keys = readonly string[]
275
+ ```
276
+
277
+ ---
278
+
279
+ ### getValue
280
+ パスを辿ってステートから値を取得
281
+ 安全にアクセス可能
282
+
283
+ ```ts
284
+ export const getValue = function <S, D> (
285
+ state : S,
286
+ keyNames: string[],
287
+ def : D
288
+ ): D
289
+ ```
290
+ *型保証は呼び出し側の責任*
291
+
292
+ - state : ステート
293
+ - keyNames: 値までのパス
294
+ - def : デフォルト値
295
+
296
+ ---
297
+
298
+ ### setValue
299
+ パスを辿ってステートに値を設定し、immutable な新しいステートを返す
300
+
301
+ ```ts
302
+ export const setValue = function <S> (
303
+ state : S,
304
+ keyNames: string[],
305
+ value : any
306
+ ): S
307
+ ```
308
+ - state : ステート
309
+ - keyNames: 値までのパス
310
+ - value : 設定する値
311
+
312
+ ---
313
+
314
+ ### getLocalState
315
+ ID に紐づいたローカルステートを取得
316
+
317
+ ```ts
318
+ export const getLocalState = function <S> (
319
+ state: S,
320
+ id : string,
321
+ def : { [key: string]: any }
322
+ ): { [key: string]: any }
323
+ ```
324
+
325
+ - state: ステート
326
+ - id : ユニークID
327
+ - def : 初期値
328
+
329
+ ---
330
+
331
+ ### setLocalState
332
+ ローカルステートを更新して新しいステートを返す
333
+
334
+ ```ts
335
+ export const setLocalState = function <S> (
336
+ state: S,
337
+ id : string,
338
+ value: { [key: string]: any }
339
+ ): S
340
+ ```
341
+
342
+ - state: ステート
343
+ - id : ユニークID
344
+ - value: 設定するローカルステート
345
+
346
+ ---
347
+
348
+ ### createLocalKey
349
+ ID からユニーク文字列を作成する
350
+
351
+ ```ts
352
+ export const createLocalKey = (id: string): string => `local_key_${ id }`
353
+ ```
354
+
355
+ ---
356
+
357
+ ### Keys_String, Keys_ArrayString
358
+ ステートの任意の値までのパスを表す、文字配列の型エイリアス
359
+
360
+ ---
361
+
362
+ ### el
363
+ Hyperapp の h 関数ラッパー。JSX と競合する場合に使用
364
+ children の処理も同時に行っているため、本ライブラリでは VNode を作成する際に使用しています
365
+
366
+ ```ts
367
+ export const el = (tag: string) => <S> (
368
+ props ?: { [key: string]: any },
369
+ children?: Array
370
+ ): VNode<S>
371
+ ```
372
+
373
+ - tag: タグ名
374
+
375
+ ---
376
+
377
+ ### concatAction
378
+ アクションを結合して結果を返す
379
+ `effect_nodesInitialize` と組み合わせ可能
380
+
381
+ ```ts
382
+ export const concatAction = function <S, E> (
383
+ action : undefined | ((state: S, e: E) => S | [S, Effect<S>]),
384
+ newState: S,
385
+ e : E
386
+ ): S | [S, Effect<S>]
387
+ ```
388
+ *newStateを設定後、DOM描画を待ち、次の action に結合します*
389
+
390
+ - action : 結合するアクション
391
+ - newState: 結合するステート
392
+ - e : イベント (任意のイベント型)
393
+
394
+ ---
395
+
396
+ ### getClassList
397
+ props オブジェクトから classList を取得
398
+
399
+ ```ts
400
+ export const getClassList = (
401
+ props: { [key: string]: any }
402
+ ): string[]
403
+ ```
404
+
405
+ - props: props
406
+
407
+ ---
408
+
409
+ ### deleteKeys
410
+ props から不要なキーを除去
411
+
412
+ ```ts
413
+ export const deleteKeys = <T extends Record<string, any>> (
414
+ props : T,
415
+ ...keys: (keyof T)[]
416
+ ): Omit<T, (typeof keys)[number]>
417
+ ```
418
+
419
+ - props : props
420
+ - ...keys: 削除するキー
421
+
422
+ ---
423
+
424
+ ### Route
425
+ ステート値と一致した場合に VNode を返す
426
+ 条件付きレンダリングに利用
427
+
428
+ ```ts
429
+ export const Route = function <S> (
430
+ props: {
431
+ state : S
432
+ keyNames: string[]
433
+ match : string
434
+ },
435
+ children: any
436
+ ): VNode<S> | null
437
+ ```
438
+ *返値に `null` が設定された場合 `VNode` は生成されません*
439
+
440
+ - props : props
441
+ - props.state : ステート
442
+ - props.keyNames: ステート内の文字までのパス
443
+ - props.match : 一致判定する文字
444
+ - children : 出力する内容 (VNode / 配列 / 文字など)
445
+
446
+ ---
447
+
448
+ ### SelectButton
449
+ クラス名 `select` をトグルするボタン
450
+ 複数選択可能
451
+
452
+ ```ts
453
+ export const SelectButton = function <S> (
454
+ props: {
455
+ state : S
456
+ keyNames : string[]
457
+ id : string
458
+ reverse? : boolean
459
+ [key: string]: any
460
+ },
461
+ children: any
462
+ ): VNode<S>
463
+ ```
464
+ *クリックにより、クラス名 `select` がトグルされます*
465
+
466
+ - props : props
467
+ - props.state : ステート
468
+ - props.keyNames: ステート内の文字配列までのパス
469
+ - props.id : ユニークID
470
+ - props.reverse?: 反転選択するか
471
+ - children : 子要素 (VNode / string / 配列など)
472
+
473
+ ---
474
+
475
+ ### OptionButton
476
+ クラス名 `select` を単一選択で切り替えるボタン
477
+ 単一選択用
478
+
479
+ ```ts
480
+ export const OptionButton = function <S> (
481
+ props: {
482
+ state : S
483
+ keyNames : string[]
484
+ id : string
485
+ reverse? : boolean
486
+ [key: string]: any
487
+ },
488
+ children: any
489
+ ): VNode<S>
490
+ ```
491
+ *クリックにより、クラス名 `select` が排他的に選択されます*
492
+
493
+ - props : props
494
+ - props.state : ステート
495
+ - props.keyNames: ステート内の文字までのパス
496
+ - props.id : ユニークID
497
+ - props.reverse?: 反転選択するか
498
+ - children : 子要素 (VNode / string / 配列など)
499
+
500
+ ---
501
+
502
+ ### Keys_NavigatorItem
503
+ ステートの任意の値までのパスを表す、文字配列の型エイリアス
504
+
505
+ ---
506
+
507
+ ### NavigatorItem
508
+ ツリー構造となるナビゲーションオブジェクト
509
+
510
+ ```ts
511
+ export interface NavigatorItem {
512
+ parent : NavigatorItem | null
513
+ name : string
514
+ properties?: Record<string, any>
515
+ children ?: NavigatorItem[]
516
+ path : string
517
+ extension ?: Record<string, any>
518
+ }
519
+ ```
520
+
521
+ - parent : 親アイテム
522
+ - name : 名前
523
+ - properties: プロパティ
524
+ - children : 子アイテム
525
+ - path : パス
526
+ - extension : 拡張オブジェクト
527
+
528
+ ---
529
+
530
+ ### JsonEntry
531
+ getEntriesの返す値
532
+
533
+ ```ts
534
+ export interface JsonEntry <D> {
535
+ name : string
536
+ data : D
537
+ isProperty: boolean
538
+ isNode : boolean
539
+ }
540
+ ```
541
+
542
+ - name : 名前
543
+ - data : データ
544
+ - isProperty: プロパティか
545
+ - isNode : ディレクトリか
546
+
547
+ ---
548
+
549
+ ### NavigatorColumn
550
+ NavigatorFinder に渡すヘッダーと値
551
+
552
+ ```ts
553
+ export interface NavigatorColumn {
554
+ name: string
555
+ val : (item: NavigatorItem) => any
556
+ }
557
+ ```
558
+
559
+ - name: 名前
560
+ - val : 値を返す関数
561
+
562
+ ---
563
+
564
+ ### convertJsonToNavigatorItem
565
+ Json から NavigatorItem に変換
566
+ getEntries の採用により、JSON の形を問わない
567
+
568
+ ```ts
569
+ export const convertJsonToNavigatorItem = function <D> (
570
+ props: {
571
+ parent : NavigatorItem | null
572
+ name : string
573
+ data : D
574
+ getEntries : (data: D, depth: number) => JsonEntry<D>[]
575
+ isNode : boolean
576
+ depth ?: number
577
+ extension ?: (item: NavigatorItem, data: D, depth: number) => Record<string, any> | undefined
578
+ }
579
+ ): NavigatorItem
580
+ ```
581
+
582
+ - parent : 親アイテム
583
+ - name : 名前
584
+ - data : データ
585
+ - getEntries: JsonEntry配列を返す関数
586
+ - isNode : ディレクトリか
587
+ - depth : 階層の深さ
588
+ - extension : 拡張オブジェクトを作成する関数
589
+
590
+ ---
591
+
592
+ ### getParentItems
593
+ NavigatorItem から 親アイテムのリストを取得する
594
+ 自分自信はリストに含まない
595
+
596
+ ```ts
597
+ export const getParentItems = (
598
+ item: NavigatorItem | undefined
599
+ ): NavigatorItem[]
600
+ ```
601
+
602
+ ---
603
+
604
+ ### NavigatorFinder
605
+ ナビゲーターファインダーコンポーネント
606
+
607
+ ```ts
608
+ export const NavigatorFinder = function <S> (
609
+ props: {
610
+ state : S
611
+ currentKeys : Keys_NavigatorItem
612
+ columns ?: NavigatorColumn[]
613
+ maxItemsCount?: number
614
+ itemClick ?: (state: S, item: NavigatorItem) => S | [S, Effect<S>]
615
+ afterRender ?: (props: {
616
+ state : S
617
+ current ?: NavigatorItem
618
+ extension?: Record<string, any>
619
+ }, vnode: VNode<S>) => VNode<S>
620
+ extension ?: Record<string, any>
621
+ [key: string]: any
622
+ }
623
+ ): VNode<S>
624
+ ```
625
+
626
+ - state : ステート
627
+ - currentKeys : カレント NavigatorItem までのパス
628
+ - columns : NavigatorColumn の配列
629
+ - maxItemsCount: 最大表示するアイテム数
630
+ - itemClick : アイテムをクリックした時のアクション
631
+ - afterRender : レンダーフック
632
+ - extension : レンダーフックに渡す拡張情報
633
+
634
+ ---
635
+
636
+ ## hyperapp-is/animation
637
+
638
+ ### effect_throwMessageStart
639
+ 文字を一文字ずつ流し込むエフェクト
640
+
641
+ *実験用コードのため、npm 非公開です*
642
+
643
+
644
+ ```ts
645
+ export const effect_throwMessageStart = function <S> (
646
+ keyNames: string[],
647
+ id : string,
648
+ text : string,
649
+ interval: number,
650
+ ): (dispatch: Dispatch<S>) => void
651
+ ```
652
+
653
+ - keyNames: 値までのパス
654
+ - id : ユニークID
655
+ - text : 流し込む文字
656
+ - interval: 次の文字を流し込むまでの間隔 (ms)
657
+
658
+ ---
659
+
660
+ ### effect_throwMessagePause / effect_throwMessageResume
661
+ throwMessage を一時停止・再開
662
+
663
+ *実験用コードのため、npm 非公開です*
664
+
665
+ ```ts
666
+ export const effect_throwMessagePause = function <S> (
667
+ id: string
668
+ ): (dispatch: Dispatch<S>) => void
669
+ ```
670
+ ```ts
671
+ export const effect_throwMessageResume = function <S> (
672
+ id: string
673
+ ): (dispatch: Dispatch<S>) => void
674
+ ```
675
+
676
+ - id: ユニークID
677
+
678
+ ---
679
+
680
+ ### marquee
681
+ Translate 風に DOM が流れるアニメーションを実行します
682
+
683
+ *実験用コードのため、npm 非公開です*
684
+
685
+ ```ts
686
+ export const marquee = function <S> (
687
+ props: {
688
+ ul : HTMLUListElement
689
+ duration: number
690
+ interval: number
691
+ easing ?: (t: number) => number
692
+ }
693
+ ): { start: () => void, stop : () => void }
694
+ ```
695
+ *ステートから独立して `requestAnimationFrame` により直接 DOM を変更します*
696
+
697
+ **パラメータ**
698
+ - props.ul : アニメーション対象の <ul> エレメント
699
+ - props.duration: 実行時間 (ms)
700
+ - props.interval: 待機時間 (ms)
701
+ - props.easing : easing 関数
702
+
703
+ **戻値**
704
+ - start(): アニメーションを開始
705
+ - stop() : アニメーションを停止
706
+
707
+ ---
708
+
709
+ ### InternalEffect
710
+ Dispatch の内部処理(finish / action)から呼び出されることを前提としたエフェクト
711
+ Action の戻り値としては返されず、Dispatch の実行フロー内で直接実行される
712
+ 型としては `Effect<S>` と同一で「Dispatch 内部専用」という役割と設計意図を明示するための型エイリアス
713
+
714
+ ```ts
715
+ type InternalEffect<S> = Effect<S>
716
+ ```
717
+
718
+ **説明**
719
+
720
+ Dispatch で呼ばれるアクションでは、エフェクトを直接返すことはできません
721
+ しかし、非同期処理でエフェクトを使用したいこともあります
722
+
723
+ このときアクションを `(state: S) => S | [S, Effect<S>]` とせず `(state: S) => S | [S, InternalEffect<S>]`とすることで、エフェクトが戻り値とならないことを明示します ( Dispatch 内でエフェクトが戻せない罠対策です )
724
+ 具体的には `requestAnimationFrame` などを使用して時間差で Dispatch してください
725
+
726
+ **ポイント**
727
+
728
+ - 戻り値として使用されず、Dispatch 内でのみ実行される
729
+ - `Effect<S>` と同一
730
+ - 内部専用であることを、型で明示
731
+
732
+ **Dispatch例**
733
+
734
+ ```ts
735
+ return [state, (dispatch: Dispatch) => {
736
+ requestAnimationFrame(() =>
737
+ dispatch(state: S) => [state, effect]
738
+ )
739
+ }]
740
+ ```
741
+ *requestAnimationFrame などで、Dispatch 外部に移動した後、Dispatch します (どうしても1フレーム遅延します)*
742
+
743
+ ---
744
+
745
+ ### RAFEvent
746
+ RAFTask で使用されるイベント
747
+ hyperapp で使用される通常のアクション と同一なものですが
748
+ `payload` と `Effect` の型名が再定義されています
749
+
750
+ ```ts
751
+ type RAFEvent = <S> (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
752
+ ```
753
+
754
+ ---
755
+
756
+ ### RAFTask
757
+ requestAnimationFrame (rAF) を管理するためのクラス
758
+
759
+ ```ts
760
+ export class RAFTask <S> {
761
+ // constructor
762
+ constructor (props: {
763
+ id : string
764
+ groupID ?: string
765
+ duration : number
766
+ delay ?: number
767
+ action : RAFEvent<S>
768
+ finish ?: RAFEvent<S>
769
+ priority ?: number
770
+ extension?: Record<string, any>
771
+ })
772
+
773
+ // getter
774
+ id : string
775
+ duration : number
776
+ delay : number
777
+ action : RAFEvent<S>
778
+ finish : RAFEvent<S>
779
+ progress : number
780
+ deltaTime: number
781
+
782
+ // getter / setter
783
+ groupID : string | undefined
784
+ priority : number
785
+ extension: Record<string, any>
786
+ isDone : boolean
787
+ paused : boolean
788
+
789
+ // method
790
+ clone: RAFTask<S>
791
+ }
792
+ ```
793
+
794
+ **constructor**
795
+
796
+ 基本
797
+ - id : rAF のユニークID
798
+ - duration: 1回の実行時間 (ms)
799
+ - action : 毎フレームごとのアクション
800
+
801
+ 拡張
802
+ - groupID : 任意のグループID
803
+ - delay : 初回実行までの待機時間 (ms)
804
+ - finish : 最終フレームで実行されるアクション
805
+ - priority : 処理の優先順位
806
+ - extension: 任意の拡張データ
807
+
808
+ **property**
809
+
810
+ getter
811
+ - id : rAF のユニークID
812
+ - duration : 1回の実行時間 (ms)
813
+ - delay : 初回実行までの待機時間 (ms)
814
+ - action : 毎フレームごとのアクション
815
+ - finish : 最終フレームで実行されるアクション
816
+ - progress : 進捗状況 (0 - 1)
817
+ - deltaTime: 前回アクションからの経過時間 (ms)
818
+
819
+ getter / setter
820
+ - groupID : 任意のグループID
821
+ - priority : 処理の優先順位
822
+ - extension: 任意の拡張データ
823
+ - isDone : 終了状況の取得 / 設定
824
+ - paused : 一時停止状況の取得 / 設定
825
+
826
+ **method**
827
+
828
+ - clone: 時間を初期化したクローンを作成して返す
829
+
830
+ ---
831
+
832
+ ### subscription_RAFManager
833
+ RAFTask 配列をフレームごとに実行するサブスクリプション
834
+
835
+ ```ts
836
+ export const subscription_RAFManager = function <S> (
837
+ state : S,
838
+ keyNames: string[]
839
+ ): Subscription<S>
840
+ ```
841
+
842
+ - state : ステート
843
+ - keyNames: RAFTask 配列までのパス
844
+
845
+ [詳細説明](animation-system.md)
846
+
847
+ ---
848
+
849
+ ### CSSProperty
850
+ CSS設定用オブジェクト
851
+
852
+ ```ts
853
+ export interface CSSProperty {
854
+ [selector: string]: {
855
+ [name: string]: (progress: number) => string
856
+ }
857
+ }
858
+ ```
859
+
860
+ - selector: セレクター
861
+ - selector.[name] => fn
862
+ - name: CSS プロパティ名
863
+ - fn(progress): CSS 値を計算する関数
864
+
865
+ ---
866
+
867
+ ### createUnits
868
+ CSSProperty を変換する補助関数
869
+ selector から、doms を取得してセットにします
870
+
871
+ ```ts
872
+ export const createUnits = function (
873
+ properties: CSSProperty[]
874
+ ): {
875
+ doms : HTMLElement[],
876
+ styles: {
877
+ [name: string]: (progress: number) => string
878
+ }
879
+ }[]
880
+ ```
881
+
882
+ - properties: プロパティ配列
883
+
884
+ ---
885
+
886
+ ### createRAFProperties
887
+ subscription_RAFManager をベースにした CSS アニメーション RAFTask を作成する
888
+
889
+ ```ts
890
+ export const createRAFProperties = function <S> (
891
+ props: {
892
+ id : string
893
+ groupID?: string
894
+ duration: number
895
+ delay ?: number
896
+
897
+ finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
898
+
899
+ priority ?: number
900
+ extension?: Record<string, any>
901
+
902
+ properties: CSSProperty[]
903
+ }
904
+ ): RAFTask<S>
905
+ ```
906
+
907
+ props は、基本的に RAFTask の値
908
+
909
+ - properties: セレクタとスタイル設定のセット配列
910
+
911
+ ---
912
+
913
+ ### effect_RAFProperties
914
+ CSS プロパティをフレーム単位で段階的に変更
915
+
916
+ ```ts
917
+ export const effect_RAFProperties = function <S>(
918
+ props: {
919
+ id : string
920
+ groupID?: string
921
+ duration: number
922
+ delay ?: number
923
+
924
+ finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
925
+
926
+ priority ?: number
927
+ extension?: Record<string, any>
928
+
929
+ properties: CSSProperty[]
930
+ keyNames : string[]
931
+ }
932
+ ): (dispatch : Dispatch<S>) => void
933
+ ```
934
+
935
+ props は、基本的に RAFTask の値
936
+
937
+ - properties: セレクタとスタイル設定のセット配列
938
+ - keyNames : RAFTask 配列までのパス
939
+
940
+ ---
941
+
942
+ ### TranslateState
943
+ Translate 管理用オブジェクト
944
+
945
+ *実験用コードのため、npm 非公開です*
946
+
947
+ ```ts
948
+ export interface TranslateState {
949
+ width : number
950
+ index : number
951
+ total : number
952
+ easing: (t: number) => number
953
+ }
954
+ ```
955
+
956
+ - width : 移動量
957
+ - index : 先頭のインデックス
958
+ - total : 子の数
959
+ - easing: easing 関数
960
+
961
+ ---
962
+
963
+ ### createRAFTranslate
964
+ subscription_RAFManager をベースにした Translate アニメーション RAFTask を作成する
965
+
966
+ *実験用コードのため、npm 非公開です*
967
+
968
+ ```ts
969
+ export const createRAFTranslate = function <S> (
970
+ props: {
971
+ id : string
972
+ groupID?: string
973
+ duration: number
974
+ delay : number
975
+
976
+ finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
977
+
978
+ priority ?: number
979
+ extension?: Record<string, any>
980
+
981
+ translateState: TranslateState
982
+ }
983
+ ): RAFTask<S>
984
+ ```
985
+
986
+ - props は、基本的に RAFTask の値
987
+ - translateState: Translate情報
988
+
989
+ ---
990
+
991
+ ### effect_translateStart
992
+ `subscription_RAFManager` をベースにした Translate アニメーションエフェクトです
993
+
994
+ *実験用コードのため、npm 非公開です*
995
+
996
+ ```ts
997
+ export const effect_translateStart = function <S> (
998
+ props: {
999
+ id : string
1000
+ groupID?: string
1001
+ duration: number
1002
+ delay : number
1003
+
1004
+ finish?: (state: S, rafTask: RAFTask<S>) => S | [S, InternalEffect<S>]
1005
+
1006
+ priority ?: number
1007
+ extension?: Record<string, any>
1008
+
1009
+ easing ?: (t: number) => number
1010
+
1011
+ keyNames: string[]
1012
+ }
1013
+ ): (dispatch: Dispatch<S>) => void
1014
+ ```
1015
+
1016
+ - props は、基本的に RAFTask の値
1017
+ - easing : easing 関数
1018
+ - keyNames: RAFTask 配列までのパス
1019
+
1020
+ **説明**
1021
+
1022
+ marquee は単純な DOM に対しての副作用で、Translate としての動作は
1023
+ ステート経由で rAF を制御しているこちらに集約されることになります
1024
+
1025
+ marquee はステートを通さず直接 DOM に対して副作用を発生させるため
1026
+ 用途によっては marquee に優位性があります
1027
+
1028
+ - marquee : DOM 直接操作。軽量で即時反映
1029
+ - effect_translateStart : Hyperapp のステート経由で管理。RAFManager と連携可能
1030
+
1031
+ ### effect_translateRollback
1032
+ アニメーション中のTranslateを、元の位置に戻す
1033
+
1034
+ *実験用コードのため、npm 非公開です*
1035
+
1036
+ ```ts
1037
+ export const effect_translateRollback = function <S> (
1038
+ props: {
1039
+ id : string
1040
+ keyNames: string[]
1041
+ paused ?: boolean
1042
+ finish ?: RAFEvent<S>
1043
+ }
1044
+ ): (dispatch: Dispatch<S>)
1045
+ ```
1046
+
1047
+ - id : ユニークID
1048
+ - keyNames: RAFTask 配列までのパス
1049
+ - paused : 実行後、一時停止するか
1050
+ - finish : 実行後に呼び出されるイベント
1051
+
1052
+ **注意**
1053
+ `effect_translateStart` に依存しています
1054
+ 上記エフェクトでループしている id に対して使用します
1055
+
1056
+ ---
1057
+
1058
+ ### effect_translateRollforward
1059
+ アニメーション中のTranslateを、早送りする
1060
+
1061
+ *実験用コードのため、npm 非公開です*
1062
+
1063
+ ```ts
1064
+ export const effect_translateRollforward = function <S> (
1065
+ props: {
1066
+ id : string
1067
+ keyNames: string[]
1068
+ paused ?: boolean
1069
+ finish ?: RAFEvent<S>
1070
+ }
1071
+ ): (dispatch: Dispatch<S>)
1072
+ ```
1073
+
1074
+ - id : ユニークID
1075
+ - keyNames: RAFTask 配列までのパス
1076
+ - paused : 実行後、一時停止するか
1077
+ - finish : 実行後に呼び出されるイベント
1078
+
1079
+ **注意**
1080
+ `effect_translateStart` に依存しています
1081
+ 上記エフェクトでループしている id に対して使用します
1082
+
1083
+ ---
1084
+
1085
+ ### effect_translateSlide
1086
+ Translateを任意のインデックスまで移動する
1087
+
1088
+ *実験用コードのため、npm 非公開です*
1089
+
1090
+ ```ts
1091
+ export const effect_translateSlide = function <S> (
1092
+ props: {
1093
+ id : string
1094
+ keyNames: string[]
1095
+ index : number
1096
+ paused ?: boolean
1097
+ finish ?: RAFEvent<S>
1098
+ }
1099
+ ): (dispatch: Dispatch<S>) => void
1100
+ ```
1101
+
1102
+ - id : ユニークID
1103
+ - keyNames: RAFTask 配列までのパス
1104
+ - index : 移動先のインデックス
1105
+ - paused : 実行後、一時停止するか
1106
+ - finish : 実行後に呼び出されるイベント
1107
+
1108
+ **注意**
1109
+ `effect_translateStart` に依存しています
1110
+ 上記エフェクトでループしている id に対して使用します
1111
+
1112
+ ---
1113
+
1114
+ ### progress_easing
1115
+ easing プリセット
1116
+
1117
+ ```ts
1118
+ export const progress_easing = {
1119
+
1120
+ // basic
1121
+ linear : (t: number) => t,
1122
+ easeInQuad : (t: number) => t * t,
1123
+ easeOutQuad : (t: number) => 1 - (1 - t) * (1 - t),
1124
+ easeInOutQuad: (t: number) => t < 0.5
1125
+ ? 2 * t * t
1126
+ : 1 - Math.pow(-2 * t + 2, 2) / 2,
1127
+
1128
+ // cubic
1129
+ easeInCubic : (t: number) => t * t * t,
1130
+ easeOutCubic : (t: number) => 1 - Math.pow(1 - t, 3),
1131
+ easeInOutCubic: (t: number) => t < 0.5
1132
+ ? 4 * t * t * t
1133
+ : 1 - Math.pow(-2 * t + 2, 3) / 2,
1134
+
1135
+ // quart
1136
+ easeInQuart : (t: number) => t * t * t * t,
1137
+ easeOutQuart : (t: number) => 1 - Math.pow(1 - t, 4),
1138
+ easeInOutQuart: (t: number) => t < 0.5
1139
+ ? 8 * t * t * t * t
1140
+ : 1 - Math.pow(-2 * t + 2, 4) / 2,
1141
+
1142
+ // back (跳ねる)
1143
+ easeOutBack: (t: number) => {
1144
+ const c1 = 1.70158
1145
+ const c3 = c1 + 1
1146
+ return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2)
1147
+ },
1148
+
1149
+ // bounce
1150
+ easeOutBounce: (t: number) => {
1151
+ const n1 = 7.5625
1152
+ const d1 = 2.75
1153
+
1154
+ if (t < 1 / d1) {
1155
+ return n1 * t * t
1156
+ } else if (t < 2 / d1) {
1157
+ return n1 * (t -= 1.5 / d1) * t + 0.75
1158
+ } else if (t < 2.5 / d1) {
1159
+ return n1 * (t -= 2.25 / d1) * t + 0.9375
1160
+ } else {
1161
+ return n1 * (t -= 2.625 / d1) * t + 0.984375
1162
+ }
1163
+ },
1164
+
1165
+ // elastic
1166
+ easeOutElastic: (t: number) => {
1167
+ const c4 = (2 * Math.PI) / 3
1168
+
1169
+ return t === 0
1170
+ ? 0
1171
+ : t === 1
1172
+ ? 1
1173
+ : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1
1174
+ }
1175
+ }
1176
+ ```
1177
+
1178
+ ## hyperapp-is/animationView
1179
+
1180
+ ### CarouselState
1181
+ Carousel コンポーネント情報
1182
+ RAFTask.extension に保存されます
1183
+
1184
+ ```ts
1185
+ export interface CarouselState <S> {
1186
+ id : string
1187
+ step: number
1188
+
1189
+ // option
1190
+ groupID ?: string
1191
+ duration ?: number
1192
+ delay ?: number
1193
+ priority ?: number
1194
+ extension?: Record<string, any>
1195
+
1196
+ // event
1197
+ action?: RAFEvent<S>
1198
+ finish?: RAFEvent<S>
1199
+
1200
+ // animation
1201
+ easing?: (t: number) => number
1202
+
1203
+ // report
1204
+ reportPageIndex?: string[]
1205
+ }
1206
+ ```
1207
+ 基本的には `RAFTask` に準拠します
1208
+ カルーセルを動作せるため `effect_InitCarousel` に渡すための値です
1209
+
1210
+ 必須項目
1211
+ - id: `Carousel` コンポーネントの id を指定してください
1212
+ - step: 移動するアイテムの数で、負の数は逆回転。0 は停止となります
1213
+
1214
+ 拡張項目
1215
+ - easing: アニメーションの動作を指定する関数
1216
+ 指定しない場合は `(t: number) => t` (linear) となります
1217
+
1218
+ - reportPagreIndex: 現在一番左端に表示されているアイテムのインデックスを受けるパス
1219
+ コントロールバーを自作したい時などに利用できます
1220
+
1221
+ ---
1222
+
1223
+ ### CarouselController
1224
+ 外部から Carousel コンポーネントを操作するためのクラス
1225
+ RAFTask.extension に保存されます
1226
+
1227
+ ```ts
1228
+ export interface CarouselController <S> {
1229
+ step : (rafTask: RAFTask<S>, delta: number, skipSpeedRate?: number) => Promise <RAFTask<S>>
1230
+ moveTo: (rafTask: RAFTask<S>, index: number, skipSpeedRage?: number) => Promise <RAFTask<S>>
1231
+ }
1232
+ ```
1233
+
1234
+ - step: `delta` で指定した方向にページを移動します (相対値)
1235
+ スキップ時のスピードは、変更前の `duration` に `skipSpeedRate` を乗じたものになります
1236
+ 終了時に処理を割り込ませたい場合は、`Promsie` により処理します
1237
+
1238
+ - moveTo: `index` で指定したページに移動します (絶対値)
1239
+ スキップ時のスピードは、変更前の `duration` に `skipSpeedRate` を乗じたものになります
1240
+ 終了時に処理を割り込ませたい場合は、`Promsie` により処理します
1241
+
1242
+ ### Carousel
1243
+ カルーセルコンポーネントです
1244
+ `CarouselState` を引数に `effect_InitCarousel` を実行することで動作開始します
1245
+ `subscription_RAFManager` を使用するので、予め `subscriptions` に追加してください
1246
+
1247
+ ```ts
1248
+ export const Carousel = function <S> (
1249
+ props: {
1250
+ state : S
1251
+ id : string
1252
+ keyNames : string[]
1253
+ controlButton?: boolean
1254
+ controlBar ?: boolean
1255
+ skipSpeedRate?: number
1256
+ [key: string] : any
1257
+ },
1258
+ children: any
1259
+ ): VNode<S>
1260
+ ```
1261
+
1262
+ - state : ステート
1263
+ - id : ユニークID (DOM の id)
1264
+ - keyNames : RAFTask 配列までのパス
1265
+ - controlButton: 操作ボタンを表示するか (未実装)
1266
+ - controlBar : 操作バーを表示するか
1267
+ - skipSpeedRate: スキップ時の動作速度
1268
+
1269
+ ### effect_InitCarousel
1270
+ カルーセルを初期化し起動するエフェクト
1271
+
1272
+ ```ts
1273
+ export const effect_InitCarousel = function <S> (
1274
+ keyNames : string[],
1275
+ carouselState: CarouselState<S>
1276
+ ): (dispatch: Dispatch<S>) => void
1277
+ ```
1278
+
1279
+ - keyNames : RAFTask 配列までのパス
1280
+ - carouselState: カルーセルの動作設定
1281
+
1282
+ ## hyperapp-is/dom
1283
+
1284
+ ### ScrollMargin
1285
+ スクロールの余白を管理するオブジェクト
1286
+
1287
+ ```ts
1288
+ export interface ScrollMargin {
1289
+ top : number
1290
+ left : number
1291
+ right : number
1292
+ bottom: number
1293
+ }
1294
+ ```
1295
+
1296
+ - top : 上までの余白
1297
+ - left : 左までの余白
1298
+ - right : 右までの余白
1299
+ - bottom: 下までの余白
1300
+
1301
+ ---
1302
+
1303
+ ### getScrollMargin
1304
+ スクロールの余白を取得
1305
+
1306
+ ```ts
1307
+ export const getScrollMargin = function (e: Event): ScrollMargin
1308
+ ```
1309
+
1310
+ - e: イベント
1311
+
1312
+ ---
1313
+
1314
+ ### MatrixState
1315
+ transform 情報
1316
+
1317
+ ```ts
1318
+ export interface MatrixState {
1319
+ translate: {
1320
+ x: number
1321
+ y: number
1322
+ z: number
1323
+ }
1324
+
1325
+ scale: {
1326
+ x: number
1327
+ y: number
1328
+ z: number
1329
+ }
1330
+
1331
+ // radian
1332
+ rotate: {
1333
+ x: number
1334
+ y: number
1335
+ z: number
1336
+ }
1337
+ }
1338
+ ```
1339
+
1340
+ ---
1341
+
1342
+ ### getMatrixState
1343
+ DOM から transfrom 情報を取得する
1344
+
1345
+ ```ts
1346
+ export const getMatrixState = (
1347
+ dom: HTMLElement
1348
+ ): MatrixState | null
1349
+ ```
1350
+
1351
+ - dom : 情報を取得する DOM
1352
+
1353
+ ---
1354
+
1355
+ ### effect_setTimedValue
1356
+ ステートに存在時間制限付きの値を設定
1357
+
1358
+ *実験用コードのため、npm 非公開です*
1359
+
1360
+ ```ts
1361
+ export const effect_setTimedValue = function <S, T> (
1362
+ keyNames: string[],
1363
+ id : string,
1364
+ timeout : number,
1365
+ value : T,
1366
+ reset : T | null = null
1367
+ ): (dispatch: Dispatch<S>) => void
1368
+ ```
1369
+
1370
+ - keyNames: 値までのパス
1371
+ - id : ユニークID
1372
+ - timeout : 存在可能時間 (ms)
1373
+ - value : 一時的に設定する値
1374
+ - reset : タイムアウト後に設定する値
1375
+
1376
+ ---
1377
+
1378
+ ### effect_nodesInitialize
1379
+ VNode マウント後の初期化処理を実行
1380
+
1381
+ *実験用コードのため、npm 非公開です*
1382
+
1383
+ ```ts
1384
+ export const effect_nodesInitialize = function <S> (
1385
+ nodes: {
1386
+ id : string
1387
+ event: (state: S, element: Element) => S | [S, Effect<S>]
1388
+ }[]
1389
+ ): (dispatch: Dispatch<S>) => void
1390
+ ```
1391
+
1392
+ - nodes : 初期化対象ノード定義配列
1393
+ - nodes.id : ユニークID
1394
+ - nodes.event: 初期化イベント
1395
+
1396
+ ---
1397
+
1398
+ ### subscription_nodesCleanup
1399
+ DOM 消失時にクリーンアップ処理を実行
1400
+
1401
+ *実験用コードのため、npm 非公開です*
1402
+
1403
+ ```ts
1404
+ export const subscription_nodesCleanup = function <S>(
1405
+ nodes: {
1406
+ id : string
1407
+ finalize: (state: S) => S | [S, Effect<S>]
1408
+ }[]
1409
+ ): Subscription<S>[]
1410
+ ```
1411
+
1412
+ - nodes : クリーンアップ対象ノード定義配列
1413
+ - nodes.id : ユニークID
1414
+ - nodes.finalize: 終了時イベント
1415
+
1416
+ ---
1417
+
1418
+ ### subscription_nodesLifecycleByIds
1419
+ ステート上の ID 配列変化に応じて initialize / finalize を自動管理
1420
+
1421
+ *実験用コードのため、npm 非公開です*
1422
+
1423
+ ```ts
1424
+ export const subscription_nodesLifecycleByIds = function <S> (
1425
+ keyNames: string[],
1426
+ nodes: {
1427
+ id : string
1428
+ initialize: (state: S, element: Element | null) => S | [S, Effect<S>]
1429
+ finalize : (state: S, element: Element | null) => S | [S, Effect<S>]
1430
+ }[]
1431
+ ): Subscription<S>[]
1432
+ ```
1433
+
1434
+ - keyNames : 文字配列までのパス
1435
+ - nodes : 監視対象ノード定義配列
1436
+ - nodes.id : ユニークID
1437
+ - nodes.initialize: 初期化イベント
1438
+ - nodes.finalize : 終了時イベント