hyperapp-is 0.1.5 → 0.1.6

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