hyperapp-is 0.1.8 → 0.1.10
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 +10 -2
- package/dist/hyperapp-is/animation/properties.d.ts +0 -12
- package/dist/hyperapp-is/animation/properties.js +6 -10
- package/dist/hyperapp-is/animation/raf.d.ts +1 -9
- package/dist/hyperapp-is/animation/raf.js +16 -9
- package/dist/hyperapp-is/animationView/carousel.d.ts +2 -48
- package/dist/hyperapp-is/animationView/carousel.js +7 -16
- package/dist/hyperapp-is/core/component.d.ts +3 -48
- package/dist/hyperapp-is/core/component.js +21 -61
- package/dist/hyperapp-is/core/navigator.d.ts +22 -30
- package/dist/hyperapp-is/core/navigator.js +170 -49
- package/dist/hyperapp-is/core/state.d.ts +0 -32
- package/dist/hyperapp-is/core/state.js +0 -28
- package/dist/hyperapp-is/dom/utils.d.ts +0 -12
- package/dist/hyperapp-is/dom/utils.js +0 -6
- package/package.json +1 -4
package/README.md
CHANGED
|
@@ -549,13 +549,17 @@ NavigatorFinder に渡すヘッダーと値
|
|
|
549
549
|
|
|
550
550
|
```ts
|
|
551
551
|
export interface NavigatorColumn {
|
|
552
|
-
name: string
|
|
553
|
-
val
|
|
552
|
+
name : string
|
|
553
|
+
val : (item: NavigatorItem) => any
|
|
554
|
+
compare?: (a: NavigatorItem, b: NavigatorItem) => number
|
|
554
555
|
}
|
|
555
556
|
```
|
|
556
557
|
|
|
557
558
|
- name: 名前
|
|
558
559
|
- val : 値を返す関数
|
|
560
|
+
- compare: 比較関数
|
|
561
|
+
|
|
562
|
+
`compare` を設置したカラムだけ、ソート対象となります
|
|
559
563
|
|
|
560
564
|
---
|
|
561
565
|
|
|
@@ -606,6 +610,7 @@ export const getParentItems = (
|
|
|
606
610
|
export const NavigatorFinder = function <S> (
|
|
607
611
|
props: {
|
|
608
612
|
state : S
|
|
613
|
+
id : string
|
|
609
614
|
currentKeys : Keys_NavigatorItem
|
|
610
615
|
columns ?: (directory: NavigatorItem | undefined) => NavigatorColumn[]
|
|
611
616
|
maxItemsCount?: number
|
|
@@ -622,6 +627,7 @@ export const NavigatorFinder = function <S> (
|
|
|
622
627
|
```
|
|
623
628
|
|
|
624
629
|
- state : ステート
|
|
630
|
+
- id : ユニークID (DOM ID)
|
|
625
631
|
- currentKeys : カレント NavigatorItem までのパス
|
|
626
632
|
- columns : NavigatorColumn の配列を返す関数
|
|
627
633
|
- maxItemsCount: 最大表示するアイテム数
|
|
@@ -629,6 +635,8 @@ export const NavigatorFinder = function <S> (
|
|
|
629
635
|
- afterRender : レンダーフック
|
|
630
636
|
- extension : レンダーフックに渡す拡張情報
|
|
631
637
|
|
|
638
|
+
`maxItemsCount` は、そのうち表示数コントロールを作成するかも
|
|
639
|
+
|
|
632
640
|
---
|
|
633
641
|
|
|
634
642
|
## hyperapp-is/animation
|
|
@@ -2,10 +2,6 @@ import { Dispatch } from "hyperapp";
|
|
|
2
2
|
import { InternalEffect, RAFTask } from "./raf";
|
|
3
3
|
/**
|
|
4
4
|
* アニメーション進捗 (0〜1) を受け取り CSS 値を返す関数
|
|
5
|
-
*
|
|
6
|
-
* @type {Object.<string, Object.<string, (progress: number) => string>>} CSSProperty
|
|
7
|
-
* @property {Object.<string, (progress: number) => string>} [selector]
|
|
8
|
-
* @param {number} progress
|
|
9
5
|
*/
|
|
10
6
|
export interface CSSProperty {
|
|
11
7
|
[selector: string]: {
|
|
@@ -14,9 +10,6 @@ export interface CSSProperty {
|
|
|
14
10
|
}
|
|
15
11
|
/**
|
|
16
12
|
* CSSProperty[] から、doms と styles のセットに変換
|
|
17
|
-
*
|
|
18
|
-
* @param {CSSProperty[]} properties - プロパティ配列
|
|
19
|
-
* @returns {doms: HTMLElement[], styles:{ [name: string]: (progress: number) => string}}
|
|
20
13
|
*/
|
|
21
14
|
export declare const createUnits: (properties: CSSProperty[]) => {
|
|
22
15
|
doms: HTMLElement[];
|
|
@@ -27,8 +20,6 @@ export declare const createUnits: (properties: CSSProperty[]) => {
|
|
|
27
20
|
/**
|
|
28
21
|
* subscription_RAFManager をベースにした CSS アニメーション RAFTask を作成する
|
|
29
22
|
* props は基本的に RAFTask の値
|
|
30
|
-
*
|
|
31
|
-
* @param {CSSProperty[]} props.properties - セレクタとスタイル設定のセット配列
|
|
32
23
|
*/
|
|
33
24
|
export declare const createRAFProperties: <S>(props: {
|
|
34
25
|
id: string;
|
|
@@ -43,9 +34,6 @@ export declare const createRAFProperties: <S>(props: {
|
|
|
43
34
|
/**
|
|
44
35
|
* subscription_RAFManager をベースにした CSS アニメーションエフェクト
|
|
45
36
|
* props は基本的に RAFTask の値
|
|
46
|
-
*
|
|
47
|
-
* @param {CSSProperty[]} props.properties - セレクタとスタイル設定のセット配列
|
|
48
|
-
* @param {string[]} props.keyNames - RAFTask 配列までのパス
|
|
49
37
|
*/
|
|
50
38
|
export declare const effect_RAFProperties: <S>(props: {
|
|
51
39
|
id: string;
|
|
@@ -6,9 +6,6 @@ import { RAFTask } from "./raf";
|
|
|
6
6
|
// ---------- ---------- ---------- ---------- ----------
|
|
7
7
|
/**
|
|
8
8
|
* CSSProperty[] から、doms と styles のセットに変換
|
|
9
|
-
*
|
|
10
|
-
* @param {CSSProperty[]} properties - プロパティ配列
|
|
11
|
-
* @returns {doms: HTMLElement[], styles:{ [name: string]: (progress: number) => string}}
|
|
12
9
|
*/
|
|
13
10
|
export const createUnits = function (properties) {
|
|
14
11
|
return properties.map(p => {
|
|
@@ -25,12 +22,12 @@ export const createUnits = function (properties) {
|
|
|
25
22
|
/**
|
|
26
23
|
* subscription_RAFManager をベースにした CSS アニメーション RAFTask を作成する
|
|
27
24
|
* props は基本的に RAFTask の値
|
|
28
|
-
*
|
|
29
|
-
* @param {CSSProperty[]} props.properties - セレクタとスタイル設定のセット配列
|
|
30
25
|
*/
|
|
31
26
|
export const createRAFProperties = function (props) {
|
|
32
27
|
const { id, groupID, duration, delay, priority, extension, properties } = props;
|
|
28
|
+
// ---------- ---------- ----------
|
|
33
29
|
// action
|
|
30
|
+
// ---------- ---------- ----------
|
|
34
31
|
const action = (state, rafTask) => {
|
|
35
32
|
var _a;
|
|
36
33
|
const progress = (_a = rafTask.progress) !== null && _a !== void 0 ? _a : 0;
|
|
@@ -42,8 +39,10 @@ export const createRAFProperties = function (props) {
|
|
|
42
39
|
}
|
|
43
40
|
});
|
|
44
41
|
return state;
|
|
45
|
-
};
|
|
42
|
+
}; // end action
|
|
43
|
+
// ---------- ---------- ----------
|
|
46
44
|
// finish
|
|
45
|
+
// ---------- ---------- ----------
|
|
47
46
|
const finish = (state, rafTask) => {
|
|
48
47
|
const units = createUnits(properties);
|
|
49
48
|
// release gpu layer
|
|
@@ -59,7 +58,7 @@ export const createRAFProperties = function (props) {
|
|
|
59
58
|
}
|
|
60
59
|
}
|
|
61
60
|
];
|
|
62
|
-
};
|
|
61
|
+
}; // end finish
|
|
63
62
|
return new RAFTask({
|
|
64
63
|
id, groupID, duration, delay,
|
|
65
64
|
action, finish,
|
|
@@ -77,9 +76,6 @@ const GPU_LAYER = new Set(["transform", "opacity"]);
|
|
|
77
76
|
/**
|
|
78
77
|
* subscription_RAFManager をベースにした CSS アニメーションエフェクト
|
|
79
78
|
* props は基本的に RAFTask の値
|
|
80
|
-
*
|
|
81
|
-
* @param {CSSProperty[]} props.properties - セレクタとスタイル設定のセット配列
|
|
82
|
-
* @param {string[]} props.keyNames - RAFTask 配列までのパス
|
|
83
79
|
*/
|
|
84
80
|
export const effect_RAFProperties = function (props) {
|
|
85
81
|
const { id, groupID, duration, delay, finish, priority, extension, properties, keyNames } = props;
|
|
@@ -44,9 +44,6 @@ export declare class RAFTask<S> {
|
|
|
44
44
|
* アクションを開始して良いか判定する
|
|
45
45
|
* 現在時間等のアップデートも同時に行われる
|
|
46
46
|
* subscription_RAFManager でのみ使用される
|
|
47
|
-
*
|
|
48
|
-
* @param {number} now - requestAnimatinFrame が返す絶対時間
|
|
49
|
-
* @returns {boolan} - アクションを実行して良いか判定
|
|
50
47
|
*/
|
|
51
48
|
private [_isStart];
|
|
52
49
|
/**
|
|
@@ -55,12 +52,7 @@ export declare class RAFTask<S> {
|
|
|
55
52
|
clone(): RAFTask<S>;
|
|
56
53
|
}
|
|
57
54
|
/**
|
|
58
|
-
* RAFTask
|
|
59
|
-
*
|
|
60
|
-
* @template S
|
|
61
|
-
* @param {S} state - ステート
|
|
62
|
-
* @param {Keys_ArrayRAFTask} keyNames - RAFTask 配列までのパス
|
|
63
|
-
* @returns {Subscription<S>}
|
|
55
|
+
* RAFTask 配列の実行を管理するサブスクリプション
|
|
64
56
|
*/
|
|
65
57
|
export declare const subscription_RAFManager: <S>(state: S, keyNames: Keys_ArrayRAFTask) => Subscription<S>;
|
|
66
58
|
export {};
|
|
@@ -20,10 +20,14 @@ import { getValue, setValue } from "../core/state";
|
|
|
20
20
|
// Symbol を知らない限り、モジュールの外からは呼べない
|
|
21
21
|
const _isStart = Symbol("RAFTask.isStart");
|
|
22
22
|
export class RAFTask {
|
|
23
|
+
// ---------- ---------- ----------
|
|
23
24
|
// constructor
|
|
25
|
+
// ---------- ---------- ----------
|
|
24
26
|
constructor(props) {
|
|
25
27
|
var _a, _b, _c;
|
|
28
|
+
// ---------- ---------- ----------
|
|
26
29
|
// field
|
|
30
|
+
// ---------- ---------- ----------
|
|
27
31
|
_RAFTask_id.set(this, void 0);
|
|
28
32
|
_RAFTask_groupID.set(this, void 0);
|
|
29
33
|
_RAFTask_duration.set(this, void 0);
|
|
@@ -49,7 +53,9 @@ export class RAFTask {
|
|
|
49
53
|
__classPrivateFieldSet(this, _RAFTask_isDone, false, "f");
|
|
50
54
|
__classPrivateFieldSet(this, _RAFTask_paused, false, "f");
|
|
51
55
|
}
|
|
56
|
+
// ---------- ---------- ----------
|
|
52
57
|
// getter
|
|
58
|
+
// ---------- ---------- ----------
|
|
53
59
|
get id() { return __classPrivateFieldGet(this, _RAFTask_id, "f"); }
|
|
54
60
|
get groupID() { return __classPrivateFieldGet(this, _RAFTask_groupID, "f"); }
|
|
55
61
|
get duration() { return __classPrivateFieldGet(this, _RAFTask_duration, "f"); }
|
|
@@ -73,20 +79,21 @@ export class RAFTask {
|
|
|
73
79
|
return this.progress === 1;
|
|
74
80
|
}
|
|
75
81
|
get paused() { return __classPrivateFieldGet(this, _RAFTask_paused, "f"); }
|
|
82
|
+
// ---------- ---------- ----------
|
|
76
83
|
// setter
|
|
84
|
+
// ---------- ---------- ----------
|
|
77
85
|
set groupID(val) { __classPrivateFieldSet(this, _RAFTask_groupID, val, "f"); }
|
|
78
86
|
set priority(val) { __classPrivateFieldSet(this, _RAFTask_priority, val, "f"); }
|
|
79
87
|
set extension(val) { __classPrivateFieldSet(this, _RAFTask_extension, val, "f"); }
|
|
80
88
|
set isDone(val) { __classPrivateFieldSet(this, _RAFTask_isDone, val, "f"); }
|
|
81
89
|
set paused(val) { __classPrivateFieldSet(this, _RAFTask_paused, val, "f"); }
|
|
90
|
+
// ---------- ---------- ----------
|
|
82
91
|
// private method: _isStart
|
|
92
|
+
// ---------- ---------- ----------
|
|
83
93
|
/**
|
|
84
94
|
* アクションを開始して良いか判定する
|
|
85
95
|
* 現在時間等のアップデートも同時に行われる
|
|
86
96
|
* subscription_RAFManager でのみ使用される
|
|
87
|
-
*
|
|
88
|
-
* @param {number} now - requestAnimatinFrame が返す絶対時間
|
|
89
|
-
* @returns {boolan} - アクションを実行して良いか判定
|
|
90
97
|
*/
|
|
91
98
|
[(_RAFTask_id = new WeakMap(), _RAFTask_groupID = new WeakMap(), _RAFTask_duration = new WeakMap(), _RAFTask_delay = new WeakMap(), _RAFTask_action = new WeakMap(), _RAFTask_finish = new WeakMap(), _RAFTask_priority = new WeakMap(), _RAFTask_extension = new WeakMap(), _RAFTask_startTime = new WeakMap(), _RAFTask_currentTime = new WeakMap(), _RAFTask_pausedTime = new WeakMap(), _RAFTask_paused = new WeakMap(), _RAFTask_deltaTime = new WeakMap(), _RAFTask_isDone = new WeakMap(), _isStart)](now) {
|
|
92
99
|
var _a;
|
|
@@ -119,7 +126,9 @@ export class RAFTask {
|
|
|
119
126
|
__classPrivateFieldSet(this, _RAFTask_isDone, this.progress === 1, "f");
|
|
120
127
|
return !__classPrivateFieldGet(this, _RAFTask_isDone, "f");
|
|
121
128
|
}
|
|
129
|
+
// ---------- ---------- ----------
|
|
122
130
|
// method: clone
|
|
131
|
+
// ---------- ---------- ----------
|
|
123
132
|
/**
|
|
124
133
|
* 時間を初期化したクローンを作成して返す
|
|
125
134
|
*/
|
|
@@ -140,12 +149,7 @@ export class RAFTask {
|
|
|
140
149
|
// subscription_RAFManager
|
|
141
150
|
// ---------- ---------- ---------- ---------- ----------
|
|
142
151
|
/**
|
|
143
|
-
* RAFTask
|
|
144
|
-
*
|
|
145
|
-
* @template S
|
|
146
|
-
* @param {S} state - ステート
|
|
147
|
-
* @param {Keys_ArrayRAFTask} keyNames - RAFTask 配列までのパス
|
|
148
|
-
* @returns {Subscription<S>}
|
|
152
|
+
* RAFTask 配列の実行を管理するサブスクリプション
|
|
149
153
|
*/
|
|
150
154
|
export const subscription_RAFManager = function (state, keyNames) {
|
|
151
155
|
let rID = 0; // rAF timerID
|
|
@@ -157,10 +161,13 @@ export const subscription_RAFManager = function (state, keyNames) {
|
|
|
157
161
|
if (rID !== 0)
|
|
158
162
|
cancelAnimationFrame(rID);
|
|
159
163
|
};
|
|
164
|
+
// ---------- ---------- ----------
|
|
160
165
|
// rAF callback
|
|
166
|
+
// ---------- ---------- ----------
|
|
161
167
|
const loop = (now) => {
|
|
162
168
|
dispatch((state) => {
|
|
163
169
|
const tasks = getValue(state, keyNames, []);
|
|
170
|
+
// newTasks
|
|
164
171
|
const newTasks = tasks.map(task => {
|
|
165
172
|
if (task.isDone)
|
|
166
173
|
return null;
|
|
@@ -3,34 +3,11 @@ import { Keys_Number, Keys_ArrayRAFTask } from "../core/state";
|
|
|
3
3
|
import { RAFEvent, RAFTask } from "../animation/raf";
|
|
4
4
|
/**
|
|
5
5
|
* Carousel コンポーネント情報
|
|
6
|
-
* RAFTask.extension
|
|
6
|
+
* RAFTask.extension に格納される
|
|
7
7
|
*
|
|
8
8
|
* 実行後に id を変更しても、反映されません
|
|
9
9
|
* 実行後に step, duration, delay を変更した場合、次のタスクに反映されます
|
|
10
10
|
* groupID, priority は未実装であり、値を設定しても動作に反映されません
|
|
11
|
-
*
|
|
12
|
-
* @template S
|
|
13
|
-
* @typedef {Object} CarouselState
|
|
14
|
-
*
|
|
15
|
-
* @property {string} id - ユニークID
|
|
16
|
-
* @property {number} step - 移動するページ数。負で逆順。0で停止
|
|
17
|
-
*
|
|
18
|
-
* option
|
|
19
|
-
* @property {string} [groupID] - 任意のグループナンバー (未実装)
|
|
20
|
-
* @property {number} [duration] - 1回あたりの実行時間 (ms)
|
|
21
|
-
* @property {number} [delay] - 待機時間 (ms)
|
|
22
|
-
* @property {number} [priority] - 処理優先巡視 (未実装)
|
|
23
|
-
* @property {Record<string, any>} [extension] - 拡張用プロパティ
|
|
24
|
-
*
|
|
25
|
-
* event
|
|
26
|
-
* @property {RAFEvent<S>} [action] - 毎フレーム発生するイベント
|
|
27
|
-
* @property {RAFEvent<S>} [finish] - ページ切替後に発生するイベント
|
|
28
|
-
*
|
|
29
|
-
* animation
|
|
30
|
-
* @property {(t: number) => number} easing - easing 関数
|
|
31
|
-
*
|
|
32
|
-
* report
|
|
33
|
-
* @property {Keys_Number} [reportPageIndex] - 現在表示中インデックスの出力パス
|
|
34
11
|
*/
|
|
35
12
|
export interface CarouselState<S> {
|
|
36
13
|
id: string;
|
|
@@ -47,16 +24,7 @@ export interface CarouselState<S> {
|
|
|
47
24
|
}
|
|
48
25
|
/**
|
|
49
26
|
* 外部から Carousel コンポーネントを操作するためのクラス
|
|
50
|
-
* RAFTask.extension
|
|
51
|
-
*
|
|
52
|
-
* @template S
|
|
53
|
-
* @typedef {Object} CarouselController
|
|
54
|
-
*
|
|
55
|
-
* - ページ移動を行う (移動中の場合は割り込む)
|
|
56
|
-
* @property {(rafTask: RAFTask<S>, delta: number, skipSpeedRate?: number) => Promise<RAFTask<S>>} step
|
|
57
|
-
*
|
|
58
|
-
* @property {(rafTask: RAFTask<S>, index: number, skipSpeedRate?: number) => Pronise<RAFTask<S>>} moveTo
|
|
59
|
-
* - 指定インデックス番号に移動する (移動中の場合は割り込む)
|
|
27
|
+
* RAFTask.extension に格納される
|
|
60
28
|
*/
|
|
61
29
|
export interface CarouselController<S> {
|
|
62
30
|
step: (rafTask: RAFTask<S>, delta: number, skipSpeedRate?: number) => Promise<RAFTask<S>>;
|
|
@@ -64,16 +32,6 @@ export interface CarouselController<S> {
|
|
|
64
32
|
}
|
|
65
33
|
/**
|
|
66
34
|
* Carousel Component
|
|
67
|
-
*
|
|
68
|
-
* @template S
|
|
69
|
-
* @param {Object} props - props
|
|
70
|
-
* @param {S} props.state - ステート
|
|
71
|
-
* @param {string} props.id - ユニークID (DOM id)
|
|
72
|
-
* @param {Keys_ArrayRAFTask} props.keyNames - RAFTask 配列までのパス
|
|
73
|
-
* @param {boolean} [props.controlButton] - ページ切り替えボタンを表示する (未実装)
|
|
74
|
-
* @param {boolean} [props.controlBar] - 現在位置を示すステータスバーを表示する
|
|
75
|
-
* @param {number} [skipSpeedRate] - skip 時に duration に乗じる値
|
|
76
|
-
* @param {any} children - 表示するページ (HTMLLIElement の子になる)
|
|
77
35
|
*/
|
|
78
36
|
export declare const Carousel: <S>(props: {
|
|
79
37
|
state: S;
|
|
@@ -86,9 +44,5 @@ export declare const Carousel: <S>(props: {
|
|
|
86
44
|
}, children: any) => VNode<S>;
|
|
87
45
|
/**
|
|
88
46
|
* カルーセルを初期化し起動するエフェクト
|
|
89
|
-
*
|
|
90
|
-
* @param {Keys_ArrayRAFTask} keyNames - RAFTask 配列までのパス
|
|
91
|
-
* @param {CarouselState} carouselState - カルーセル情報
|
|
92
|
-
* @returns {(dispatch: Dispatch<S>) => void}
|
|
93
47
|
*/
|
|
94
48
|
export declare const effect_InitCarousel: <S>(keyNames: Keys_ArrayRAFTask, carouselState: CarouselState<S>) => (dispatch: Dispatch<S>) => void;
|
|
@@ -3,25 +3,17 @@ import { getValue, setValue, createLocalKey } from "../core/state";
|
|
|
3
3
|
import { el, deleteKeys } from "../core/component";
|
|
4
4
|
import { RAFTask } from "../animation/raf";
|
|
5
5
|
// ---------- ---------- ---------- ---------- ----------
|
|
6
|
-
//
|
|
6
|
+
// vnodes
|
|
7
7
|
// ---------- ---------- ---------- ---------- ----------
|
|
8
|
-
// element
|
|
9
8
|
const div = el("div");
|
|
10
9
|
const ul = el("ul");
|
|
11
10
|
const li = el("li");
|
|
12
11
|
const button = el("button");
|
|
12
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
13
|
+
// Carousel Component
|
|
14
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
13
15
|
/**
|
|
14
16
|
* Carousel Component
|
|
15
|
-
*
|
|
16
|
-
* @template S
|
|
17
|
-
* @param {Object} props - props
|
|
18
|
-
* @param {S} props.state - ステート
|
|
19
|
-
* @param {string} props.id - ユニークID (DOM id)
|
|
20
|
-
* @param {Keys_ArrayRAFTask} props.keyNames - RAFTask 配列までのパス
|
|
21
|
-
* @param {boolean} [props.controlButton] - ページ切り替えボタンを表示する (未実装)
|
|
22
|
-
* @param {boolean} [props.controlBar] - 現在位置を示すステータスバーを表示する
|
|
23
|
-
* @param {number} [skipSpeedRate] - skip 時に duration に乗じる値
|
|
24
|
-
* @param {any} children - 表示するページ (HTMLLIElement の子になる)
|
|
25
17
|
*/
|
|
26
18
|
export const Carousel = function (props, children) {
|
|
27
19
|
var _a;
|
|
@@ -124,12 +116,11 @@ export const Carousel = function (props, children) {
|
|
|
124
116
|
? button({ onclick: action_nextPage }, ">")
|
|
125
117
|
: null) : null);
|
|
126
118
|
};
|
|
119
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
120
|
+
// effect_InitCarousel
|
|
121
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
127
122
|
/**
|
|
128
123
|
* カルーセルを初期化し起動するエフェクト
|
|
129
|
-
*
|
|
130
|
-
* @param {Keys_ArrayRAFTask} keyNames - RAFTask 配列までのパス
|
|
131
|
-
* @param {CarouselState} carouselState - カルーセル情報
|
|
132
|
-
* @returns {(dispatch: Dispatch<S>) => void}
|
|
133
124
|
*/
|
|
134
125
|
export const effect_InitCarousel = function (keyNames, carouselState) {
|
|
135
126
|
return (dispatch) => {
|
|
@@ -2,54 +2,27 @@ import { VNode, Effect } from "hyperapp";
|
|
|
2
2
|
import { Keys_String, Keys_ArrayString } from "./state";
|
|
3
3
|
/**
|
|
4
4
|
* h 関数のラッパー
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* @template S
|
|
8
|
-
* @param {string} tag - タグ名
|
|
9
|
-
* @returns {(props:{ [key: string] any }, ...children:any[]) => VNode<S>}
|
|
5
|
+
* hが競合する可能性があるので作成した
|
|
10
6
|
*/
|
|
11
7
|
export declare const el: (tag: string) => <S>(props?: {
|
|
12
8
|
[key: string]: any;
|
|
13
9
|
}, ...children: any[]) => VNode<S>;
|
|
14
10
|
/**
|
|
15
11
|
* アクションを結合して結果を返す
|
|
16
|
-
*
|
|
17
|
-
* @template S
|
|
18
|
-
* @template E
|
|
19
|
-
* @param {undefined | (state: S, e: E) => S | [S, Effect<S>]} action - 結合するアクション
|
|
20
|
-
* @param {S} newState - 結合するステート
|
|
21
|
-
* @param {E} e - イベント (任意のイベント型)
|
|
22
|
-
* @returns {S | [S, Effect<S>]}
|
|
23
12
|
*/
|
|
24
13
|
export declare const concatAction: <S, E>(action: undefined | ((state: S, e: E) => S | [S, Effect<S>]), newState: S, e: E) => S | [S, Effect<S>];
|
|
25
14
|
/**
|
|
26
15
|
* props から classList を取得
|
|
27
|
-
*
|
|
28
|
-
* @param {Record<string, any>} props - props
|
|
29
|
-
* @returns {string[]}
|
|
30
16
|
*/
|
|
31
17
|
export declare const getClassList: (props: {
|
|
32
18
|
[key: string]: any;
|
|
33
19
|
}) => string[];
|
|
34
20
|
/**
|
|
35
21
|
* props から不要なキーを削除する
|
|
36
|
-
*
|
|
37
|
-
* @template T
|
|
38
|
-
* @param {T} props - props
|
|
39
|
-
* @param {(keyof T)[])} keys - 削除するキー
|
|
40
|
-
* @returns {Omit<T, (typeof keys)[number]>}
|
|
41
22
|
*/
|
|
42
23
|
export declare const deleteKeys: <T extends Record<string, any>>(props: T, ...keys: (keyof T)[]) => Omit<T, (typeof keys)[number]>;
|
|
43
24
|
/**
|
|
44
25
|
* ステート内の文字とmatchした時、VNodeを返す
|
|
45
|
-
*
|
|
46
|
-
* @template S
|
|
47
|
-
* @param {Record<string, any>} props - props
|
|
48
|
-
* @param {S} props.state - ステート
|
|
49
|
-
* @param {Keys_String} props.keyNames - ステート内の文字までのパス
|
|
50
|
-
* @param {string} props.match - 一致判定する文字
|
|
51
|
-
* @param {any} children - 出力する内容 (VNode / 配列 / 文字など)
|
|
52
|
-
* @returns {VNode<S> | null}
|
|
53
26
|
*/
|
|
54
27
|
export declare const Route: <S>(props: {
|
|
55
28
|
state: S;
|
|
@@ -57,16 +30,7 @@ export declare const Route: <S>(props: {
|
|
|
57
30
|
match: string;
|
|
58
31
|
}, children: any) => VNode<S> | null;
|
|
59
32
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* @template S
|
|
63
|
-
* @param {Record<string, any>} props - props
|
|
64
|
-
* @param {S} props.state - ステート
|
|
65
|
-
* @param {Keys_ArrayString} props.keyNames - ステート内の文字配列までのパス
|
|
66
|
-
* @param {string} props.id - ユニークID
|
|
67
|
-
* @param {boolean} [props.reverse] - 反転選択するか
|
|
68
|
-
* @param {any} children - 子要素 (VNode / string / 配列など)
|
|
69
|
-
* @returns {VNode<S>}
|
|
33
|
+
* クリックで、クラス名 select をトグルするボタン
|
|
70
34
|
*/
|
|
71
35
|
export declare const SelectButton: <S>(props: {
|
|
72
36
|
state: S;
|
|
@@ -76,16 +40,7 @@ export declare const SelectButton: <S>(props: {
|
|
|
76
40
|
[key: string]: any;
|
|
77
41
|
}, children: any) => VNode<S>;
|
|
78
42
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* @template S
|
|
82
|
-
* @param {Record<string, any>} props - props
|
|
83
|
-
* @param {S} props.state - ステート
|
|
84
|
-
* @param {Keys_String} props.keyNames - ステート内の文字までのパス
|
|
85
|
-
* @param {string} props.id - ユニークID
|
|
86
|
-
* @param {boolean} [props.reverse] - 反転選択するか
|
|
87
|
-
* @param {any} children - 子要素 (VNode / string / 配列など)
|
|
88
|
-
* @returns {VNode<S>}
|
|
43
|
+
* クリックで、クラス名 select を排他的に選択するボタン
|
|
89
44
|
*/
|
|
90
45
|
export declare const OptionButton: <S>(props: {
|
|
91
46
|
state: S;
|
|
@@ -1,44 +1,29 @@
|
|
|
1
1
|
// hyperapp-is / core / component.ts
|
|
2
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
3
|
+
// import
|
|
4
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
2
5
|
import { h, text } from "hyperapp";
|
|
3
6
|
import { getValue, setValue } from "./state";
|
|
4
|
-
// ========== ========== ========== ========== ==========
|
|
5
|
-
// 補助関数
|
|
6
|
-
// ========== ========== ========== ========== ==========
|
|
7
7
|
// ---------- ---------- ---------- ---------- ----------
|
|
8
8
|
// el
|
|
9
9
|
// ---------- ---------- ---------- ---------- ----------
|
|
10
10
|
/**
|
|
11
11
|
* h 関数のラッパー
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* @template S
|
|
15
|
-
* @param {string} tag - タグ名
|
|
16
|
-
* @returns {(props:{ [key: string] any }, ...children:any[]) => VNode<S>}
|
|
12
|
+
* hが競合する可能性があるので作成した
|
|
17
13
|
*/
|
|
18
14
|
export const el = (tag) => (props, ...children) => h(tag, props !== null && props !== void 0 ? props : {}, children
|
|
19
15
|
.flat()
|
|
20
16
|
.map((child) => typeof child === "object" ? child : text(child)));
|
|
21
|
-
/* element */
|
|
22
|
-
const button = el("button");
|
|
23
17
|
// ---------- ---------- ---------- ---------- ----------
|
|
24
18
|
// concatAction
|
|
25
19
|
// ---------- ---------- ---------- ---------- ----------
|
|
26
20
|
/**
|
|
27
21
|
* アクションを結合して結果を返す
|
|
28
|
-
*
|
|
29
|
-
* @template S
|
|
30
|
-
* @template E
|
|
31
|
-
* @param {undefined | (state: S, e: E) => S | [S, Effect<S>]} action - 結合するアクション
|
|
32
|
-
* @param {S} newState - 結合するステート
|
|
33
|
-
* @param {E} e - イベント (任意のイベント型)
|
|
34
|
-
* @returns {S | [S, Effect<S>]}
|
|
35
22
|
*/
|
|
36
23
|
export const concatAction = function (action, newState, e) {
|
|
37
24
|
if (!action)
|
|
38
25
|
return newState;
|
|
39
26
|
const effect = (dispatch) => {
|
|
40
|
-
// 次の描画を待たないと、newStateと同時にdispatchが走ってしまい、DOMが存在しない可能性がある
|
|
41
|
-
// effect_initializeNodesを機能させるため、dispatch を描画後まで保留する
|
|
42
27
|
requestAnimationFrame(() => {
|
|
43
28
|
dispatch((state) => action(state, e));
|
|
44
29
|
});
|
|
@@ -50,9 +35,6 @@ export const concatAction = function (action, newState, e) {
|
|
|
50
35
|
// ---------- ---------- ---------- ---------- ----------
|
|
51
36
|
/**
|
|
52
37
|
* props から classList を取得
|
|
53
|
-
*
|
|
54
|
-
* @param {Record<string, any>} props - props
|
|
55
|
-
* @returns {string[]}
|
|
56
38
|
*/
|
|
57
39
|
export const getClassList = (props) => {
|
|
58
40
|
return props.class
|
|
@@ -64,33 +46,17 @@ export const getClassList = (props) => {
|
|
|
64
46
|
// ---------- ---------- ---------- ---------- ----------
|
|
65
47
|
/**
|
|
66
48
|
* props から不要なキーを削除する
|
|
67
|
-
*
|
|
68
|
-
* @template T
|
|
69
|
-
* @param {T} props - props
|
|
70
|
-
* @param {(keyof T)[])} keys - 削除するキー
|
|
71
|
-
* @returns {Omit<T, (typeof keys)[number]>}
|
|
72
49
|
*/
|
|
73
50
|
export const deleteKeys = (props, ...keys) => {
|
|
74
51
|
const result = { ...props };
|
|
75
52
|
keys.forEach(key => delete result[key]);
|
|
76
53
|
return result;
|
|
77
54
|
};
|
|
78
|
-
// ========== ========== ========== ========== ==========
|
|
79
|
-
// コンポーネント
|
|
80
|
-
// ========== ========== ========== ========== ==========
|
|
81
55
|
// ---------- ---------- ---------- ---------- ----------
|
|
82
|
-
// Route
|
|
56
|
+
// Route Component
|
|
83
57
|
// ---------- ---------- ---------- ---------- ----------
|
|
84
58
|
/**
|
|
85
59
|
* ステート内の文字とmatchした時、VNodeを返す
|
|
86
|
-
*
|
|
87
|
-
* @template S
|
|
88
|
-
* @param {Record<string, any>} props - props
|
|
89
|
-
* @param {S} props.state - ステート
|
|
90
|
-
* @param {Keys_String} props.keyNames - ステート内の文字までのパス
|
|
91
|
-
* @param {string} props.match - 一致判定する文字
|
|
92
|
-
* @param {any} children - 出力する内容 (VNode / 配列 / 文字など)
|
|
93
|
-
* @returns {VNode<S> | null}
|
|
94
60
|
*/
|
|
95
61
|
export const Route = function (props, children) {
|
|
96
62
|
const { state, keyNames, match } = props;
|
|
@@ -99,20 +65,15 @@ export const Route = function (props, children) {
|
|
|
99
65
|
return selectedName === match ? children : null;
|
|
100
66
|
};
|
|
101
67
|
// ---------- ---------- ---------- ---------- ----------
|
|
102
|
-
//
|
|
68
|
+
// vnodes
|
|
69
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
70
|
+
const button = el("button");
|
|
71
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
72
|
+
// SelectButton Component
|
|
103
73
|
// ---------- ---------- ---------- ---------- ----------
|
|
104
74
|
const REVERSE_PREFIX = "r_";
|
|
105
75
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* @template S
|
|
109
|
-
* @param {Record<string, any>} props - props
|
|
110
|
-
* @param {S} props.state - ステート
|
|
111
|
-
* @param {Keys_ArrayString} props.keyNames - ステート内の文字配列までのパス
|
|
112
|
-
* @param {string} props.id - ユニークID
|
|
113
|
-
* @param {boolean} [props.reverse] - 反転選択するか
|
|
114
|
-
* @param {any} children - 子要素 (VNode / string / 配列など)
|
|
115
|
-
* @returns {VNode<S>}
|
|
76
|
+
* クリックで、クラス名 select をトグルするボタン
|
|
116
77
|
*/
|
|
117
78
|
export const SelectButton = function (props, children) {
|
|
118
79
|
const { state, keyNames, id, reverse = false } = props;
|
|
@@ -126,7 +87,9 @@ export const SelectButton = function (props, children) {
|
|
|
126
87
|
classList.push("select");
|
|
127
88
|
if (selectedNames.includes(`${REVERSE_PREFIX}${id}`))
|
|
128
89
|
classList.push("reverse");
|
|
90
|
+
// ---------- ---------- ----------
|
|
129
91
|
// action
|
|
92
|
+
// ---------- ---------- ----------
|
|
130
93
|
const action = (state, e) => {
|
|
131
94
|
const selectedNames = getValue(state, keyNames, []);
|
|
132
95
|
const newList = selectedNames.includes(id)
|
|
@@ -139,7 +102,9 @@ export const SelectButton = function (props, children) {
|
|
|
139
102
|
const newState = setValue(state, keyNames, newList);
|
|
140
103
|
return concatAction(props.onclick, newState, e);
|
|
141
104
|
};
|
|
105
|
+
// ---------- ---------- ----------
|
|
142
106
|
// VNode
|
|
107
|
+
// ---------- ---------- ----------
|
|
143
108
|
return button({
|
|
144
109
|
type: "button",
|
|
145
110
|
...deleteKeys(props, "state", "keyNames", "reverse"),
|
|
@@ -148,19 +113,10 @@ export const SelectButton = function (props, children) {
|
|
|
148
113
|
}, children);
|
|
149
114
|
};
|
|
150
115
|
// ---------- ---------- ---------- ---------- ----------
|
|
151
|
-
// OptionButton
|
|
116
|
+
// OptionButton Component
|
|
152
117
|
// ---------- ---------- ---------- ---------- ----------
|
|
153
118
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* @template S
|
|
157
|
-
* @param {Record<string, any>} props - props
|
|
158
|
-
* @param {S} props.state - ステート
|
|
159
|
-
* @param {Keys_String} props.keyNames - ステート内の文字までのパス
|
|
160
|
-
* @param {string} props.id - ユニークID
|
|
161
|
-
* @param {boolean} [props.reverse] - 反転選択するか
|
|
162
|
-
* @param {any} children - 子要素 (VNode / string / 配列など)
|
|
163
|
-
* @returns {VNode<S>}
|
|
119
|
+
* クリックで、クラス名 select を排他的に選択するボタン
|
|
164
120
|
*/
|
|
165
121
|
export const OptionButton = function (props, children) {
|
|
166
122
|
const { state, keyNames, id, reverse = false } = props;
|
|
@@ -174,7 +130,9 @@ export const OptionButton = function (props, children) {
|
|
|
174
130
|
classList.push("select");
|
|
175
131
|
if (selectedName === `${REVERSE_PREFIX}${id}`)
|
|
176
132
|
classList.push("reverse");
|
|
133
|
+
// ---------- ---------- ----------
|
|
177
134
|
// action
|
|
135
|
+
// ---------- ---------- ----------
|
|
178
136
|
const action = (state, e) => {
|
|
179
137
|
const selectedName = getValue(state, keyNames, "");
|
|
180
138
|
const newValue = selectedName === id && reverse
|
|
@@ -183,7 +141,9 @@ export const OptionButton = function (props, children) {
|
|
|
183
141
|
const newState = setValue(state, keyNames, newValue);
|
|
184
142
|
return concatAction(props.onclick, newState, e);
|
|
185
143
|
};
|
|
144
|
+
// ---------- ---------- ----------
|
|
186
145
|
// VNode
|
|
146
|
+
// ---------- ---------- ----------
|
|
187
147
|
return button({
|
|
188
148
|
type: "button",
|
|
189
149
|
...deleteKeys(props, "state", "keyNames", "reverse"),
|
|
@@ -1,47 +1,23 @@
|
|
|
1
1
|
import { VNode, Effect } from "hyperapp";
|
|
2
2
|
import { Keys_NavigatorItem } from "./state";
|
|
3
|
-
/**
|
|
4
|
-
* ツリー構造となるナビゲーションオブジェクト
|
|
5
|
-
*
|
|
6
|
-
* parent - 親アイテム
|
|
7
|
-
* name - 名前
|
|
8
|
-
* properties - プロパティオブジェクト
|
|
9
|
-
* children - 子アイテムリスト (undefinedのときはファイル)
|
|
10
|
-
* path - パス
|
|
11
|
-
* extension - 拡張情報
|
|
12
|
-
*/
|
|
13
3
|
export interface NavigatorItem {
|
|
14
4
|
parent: NavigatorItem | null;
|
|
15
5
|
name: string;
|
|
6
|
+
path: string;
|
|
16
7
|
properties?: Record<string, any>;
|
|
17
8
|
children?: NavigatorItem[];
|
|
18
|
-
path: string;
|
|
19
9
|
extension?: Record<string, any>;
|
|
20
10
|
}
|
|
21
|
-
/**
|
|
22
|
-
* getEntriesで返すオブジェクト
|
|
23
|
-
*
|
|
24
|
-
* name - 名前
|
|
25
|
-
* data - データ
|
|
26
|
-
* isNode - ディレクトリか
|
|
27
|
-
*/
|
|
28
11
|
export interface JsonEntry<D> {
|
|
29
12
|
name: string;
|
|
30
13
|
data: D;
|
|
31
14
|
isNode: boolean;
|
|
32
15
|
}
|
|
33
|
-
/**
|
|
34
|
-
* ヘッダー名と値
|
|
35
|
-
*/
|
|
36
16
|
export interface NavigatorColumn {
|
|
37
17
|
name: string;
|
|
38
18
|
val: (item: NavigatorItem) => any;
|
|
19
|
+
compare?: (a: NavigatorItem, b: NavigatorItem) => number;
|
|
39
20
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Json から NavigatorItem に変換
|
|
42
|
-
* getEntries の採用により、JSON の形を問わない
|
|
43
|
-
* extension により、任意情報を保存できる
|
|
44
|
-
*/
|
|
45
21
|
export declare const convertJsonToNavigatorItem: <D>(props: {
|
|
46
22
|
parent: NavigatorItem | null;
|
|
47
23
|
name: string;
|
|
@@ -51,15 +27,31 @@ export declare const convertJsonToNavigatorItem: <D>(props: {
|
|
|
51
27
|
depth?: number;
|
|
52
28
|
extension?: (item: NavigatorItem, data: D, depth: number) => Record<string, any> | undefined;
|
|
53
29
|
}) => NavigatorItem;
|
|
54
|
-
/**
|
|
55
|
-
* NavigatorItem の親をリストで取得する
|
|
56
|
-
*/
|
|
57
30
|
export declare const getParentItems: (item: NavigatorItem | undefined) => NavigatorItem[];
|
|
58
31
|
/**
|
|
59
|
-
*
|
|
32
|
+
* ファインダー
|
|
33
|
+
*
|
|
34
|
+
* - 必須項目
|
|
35
|
+
* state, id, currentKeys
|
|
36
|
+
*
|
|
37
|
+
* - columns
|
|
38
|
+
* カラムの表示設定
|
|
39
|
+
*
|
|
40
|
+
* - maxItemsCount
|
|
41
|
+
* 最大表示させるアイテム数
|
|
42
|
+
*
|
|
43
|
+
* - itemClick
|
|
44
|
+
* 非ノードをクリックした際のアクション
|
|
45
|
+
*
|
|
46
|
+
* - afterRender
|
|
47
|
+
* レンダーフック
|
|
48
|
+
*
|
|
49
|
+
* - extension
|
|
50
|
+
* レンダーフックで参照できる拡張情報
|
|
60
51
|
*/
|
|
61
52
|
export declare const NavigatorFinder: <S>(props: {
|
|
62
53
|
state: S;
|
|
54
|
+
id: string;
|
|
63
55
|
currentKeys: Keys_NavigatorItem;
|
|
64
56
|
columns?: (directory: NavigatorItem | undefined) => NavigatorColumn[];
|
|
65
57
|
maxItemsCount?: number;
|
|
@@ -1,28 +1,9 @@
|
|
|
1
1
|
// hyperapp-is / core / navigator.ts
|
|
2
|
-
import { getValue, setValue } from "./state";
|
|
3
|
-
import { el, deleteKeys } from "./component";
|
|
4
|
-
/* element */
|
|
5
|
-
const div = el("div");
|
|
6
|
-
const table = el("table");
|
|
7
|
-
const thead = el("thead");
|
|
8
|
-
const tbody = el("tbody");
|
|
9
|
-
const tr = el("tr");
|
|
10
|
-
const th = el("th");
|
|
11
|
-
const td = el("td");
|
|
12
|
-
const ul = el("ul");
|
|
13
|
-
const ol = el("ol");
|
|
14
|
-
const li = el("li");
|
|
15
|
-
const button = el("button");
|
|
16
|
-
const input = el("input");
|
|
17
|
-
const span = el("span");
|
|
2
|
+
import { getValue, setValue, getLocalState, setLocalState, createLocalKey } from "./state";
|
|
3
|
+
import { el, deleteKeys, SelectButton } from "./component";
|
|
18
4
|
// ---------- ---------- ---------- ---------- ----------
|
|
19
5
|
// convertJsonToNavigatorItem
|
|
20
6
|
// ---------- ---------- ---------- ---------- ----------
|
|
21
|
-
/**
|
|
22
|
-
* Json から NavigatorItem に変換
|
|
23
|
-
* getEntries の採用により、JSON の形を問わない
|
|
24
|
-
* extension により、任意情報を保存できる
|
|
25
|
-
*/
|
|
26
7
|
export const convertJsonToNavigatorItem = function (props) {
|
|
27
8
|
const { parent, name, data, getEntries, isNode, depth = 0, extension } = props;
|
|
28
9
|
const result = {
|
|
@@ -30,7 +11,6 @@ export const convertJsonToNavigatorItem = function (props) {
|
|
|
30
11
|
name,
|
|
31
12
|
path: parent ? parent.path + "/" + name : "/" + name
|
|
32
13
|
};
|
|
33
|
-
// 拡張情報
|
|
34
14
|
if (extension) {
|
|
35
15
|
const ext = extension(result, data, depth);
|
|
36
16
|
if (ext)
|
|
@@ -41,11 +21,9 @@ export const convertJsonToNavigatorItem = function (props) {
|
|
|
41
21
|
const children = [];
|
|
42
22
|
getEntries(data, depth).forEach(entry => {
|
|
43
23
|
const isProperty = typeof entry.data !== "object" || Array.isArray(entry.data);
|
|
44
|
-
// プロパティ
|
|
45
24
|
if (isProperty) {
|
|
46
25
|
properties[entry.name] = entry.data;
|
|
47
26
|
hasProperty = true;
|
|
48
|
-
// 子アイテム
|
|
49
27
|
}
|
|
50
28
|
else {
|
|
51
29
|
children.push(convertJsonToNavigatorItem({
|
|
@@ -62,15 +40,12 @@ export const convertJsonToNavigatorItem = function (props) {
|
|
|
62
40
|
if (hasProperty)
|
|
63
41
|
result.properties = properties;
|
|
64
42
|
if (isNode)
|
|
65
|
-
result.children = children;
|
|
43
|
+
result.children = children;
|
|
66
44
|
return result;
|
|
67
45
|
};
|
|
68
46
|
// ---------- ---------- ---------- ---------- ----------
|
|
69
47
|
// getParentItems
|
|
70
48
|
// ---------- ---------- ---------- ---------- ----------
|
|
71
|
-
/**
|
|
72
|
-
* NavigatorItem の親をリストで取得する
|
|
73
|
-
*/
|
|
74
49
|
export const getParentItems = (item) => {
|
|
75
50
|
if (!item)
|
|
76
51
|
return [];
|
|
@@ -83,31 +58,76 @@ export const getParentItems = (item) => {
|
|
|
83
58
|
return result.reverse();
|
|
84
59
|
};
|
|
85
60
|
// ---------- ---------- ---------- ---------- ----------
|
|
61
|
+
// vnodes
|
|
62
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
63
|
+
const div = el("div");
|
|
64
|
+
const table = el("table");
|
|
65
|
+
const thead = el("thead");
|
|
66
|
+
const tbody = el("tbody");
|
|
67
|
+
const tr = el("tr");
|
|
68
|
+
const th = el("th");
|
|
69
|
+
const td = el("td");
|
|
70
|
+
const ol = el("ol");
|
|
71
|
+
const li = el("li");
|
|
72
|
+
const button = el("button");
|
|
73
|
+
const input = el("input");
|
|
74
|
+
const span = el("span");
|
|
75
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
86
76
|
// NavigatorFinder Component
|
|
87
77
|
// ---------- ---------- ---------- ---------- ----------
|
|
88
78
|
/**
|
|
89
|
-
*
|
|
79
|
+
* ファインダー
|
|
80
|
+
*
|
|
81
|
+
* - 必須項目
|
|
82
|
+
* state, id, currentKeys
|
|
83
|
+
*
|
|
84
|
+
* - columns
|
|
85
|
+
* カラムの表示設定
|
|
86
|
+
*
|
|
87
|
+
* - maxItemsCount
|
|
88
|
+
* 最大表示させるアイテム数
|
|
89
|
+
*
|
|
90
|
+
* - itemClick
|
|
91
|
+
* 非ノードをクリックした際のアクション
|
|
92
|
+
*
|
|
93
|
+
* - afterRender
|
|
94
|
+
* レンダーフック
|
|
95
|
+
*
|
|
96
|
+
* - extension
|
|
97
|
+
* レンダーフックで参照できる拡張情報
|
|
90
98
|
*/
|
|
91
99
|
export const NavigatorFinder = function (props) {
|
|
92
100
|
var _a, _b;
|
|
93
|
-
const { state, currentKeys, maxItemsCount = 0, itemClick, afterRender, extension } = props;
|
|
101
|
+
const { state, id, currentKeys, maxItemsCount = 0, itemClick, afterRender, extension } = props;
|
|
94
102
|
const current = getValue(state, currentKeys, undefined);
|
|
103
|
+
// localState
|
|
104
|
+
const { searchText, selected, sortType, reverse, sortKey } = getLocalState(state, id, {
|
|
105
|
+
searchText: "", // 検索テキスト
|
|
106
|
+
selected: [], // 選択されているボタン名
|
|
107
|
+
sortType: undefined, // ソート用比較関数
|
|
108
|
+
reverse: false, // ソートを逆順にするか
|
|
109
|
+
sortKey: undefined // 使用されているソート名 (column.name)
|
|
110
|
+
});
|
|
111
|
+
// selected filter
|
|
112
|
+
const isFilter = selected.includes(`${createLocalKey(id)}_filter`);
|
|
113
|
+
// ---------- ---------- ----------
|
|
95
114
|
// createColumns
|
|
115
|
+
// ---------- ---------- ----------
|
|
96
116
|
const createColumns = (_a = props.columns) !== null && _a !== void 0 ? _a : ((directory) => {
|
|
97
117
|
const result = [];
|
|
98
118
|
if (!directory)
|
|
99
119
|
return result;
|
|
100
120
|
result.push({
|
|
101
121
|
name: "name",
|
|
102
|
-
val: (item) => item.name
|
|
122
|
+
val: (item) => item.name,
|
|
123
|
+
compare: (a, b) => {
|
|
124
|
+
return a.name.localeCompare(b.name);
|
|
125
|
+
}
|
|
103
126
|
});
|
|
104
|
-
// get properties
|
|
105
127
|
const children = directory.children;
|
|
106
128
|
if (children) {
|
|
107
|
-
// get names
|
|
108
129
|
const names = [];
|
|
109
|
-
//
|
|
110
|
-
// 子アイテムのプロパティをすべて確認して抽出しています
|
|
130
|
+
// 子アイテムのプロパティをすべて抽出
|
|
111
131
|
children.forEach(child => {
|
|
112
132
|
if (child.properties) {
|
|
113
133
|
Object.keys(child.properties).forEach(key => names.push(key));
|
|
@@ -129,65 +149,166 @@ export const NavigatorFinder = function (props) {
|
|
|
129
149
|
}
|
|
130
150
|
return result;
|
|
131
151
|
}); // end createColumns
|
|
152
|
+
// columns
|
|
132
153
|
const columns = createColumns(current);
|
|
133
154
|
// parentItems
|
|
134
155
|
const parentItems = getParentItems(current);
|
|
135
156
|
if (current)
|
|
136
157
|
parentItems.push(current);
|
|
158
|
+
// ---------- ---------- ----------
|
|
159
|
+
// hitTest
|
|
160
|
+
// ---------- ---------- ----------
|
|
161
|
+
const hitTest = (text) => {
|
|
162
|
+
if (typeof text !== "string")
|
|
163
|
+
return false;
|
|
164
|
+
const S = searchText.trim().toLowerCase();
|
|
165
|
+
if (S === "")
|
|
166
|
+
return false;
|
|
167
|
+
const keys = S.replace(/[ ]+/g, " ").split(" ").filter(Boolean);
|
|
168
|
+
if (keys.length === 0)
|
|
169
|
+
return false;
|
|
170
|
+
const sText = text.toLowerCase();
|
|
171
|
+
return keys.every(key => sText.includes(key));
|
|
172
|
+
}; // end hitTest
|
|
173
|
+
// ---------- ---------- ----------
|
|
137
174
|
// getItems
|
|
175
|
+
// ---------- ---------- ----------
|
|
138
176
|
const getItems = (item) => {
|
|
139
177
|
if (!item || item.children === undefined)
|
|
140
178
|
return [];
|
|
179
|
+
// filter
|
|
180
|
+
const result = isFilter && searchText !== ""
|
|
181
|
+
? item.children.filter(child => {
|
|
182
|
+
return columns.some(col => hitTest(col.val(child)));
|
|
183
|
+
})
|
|
184
|
+
: item.children;
|
|
185
|
+
// maxCount
|
|
141
186
|
const count = maxItemsCount === 0
|
|
142
|
-
?
|
|
143
|
-
: Math.min(maxItemsCount,
|
|
144
|
-
return
|
|
187
|
+
? result.length
|
|
188
|
+
: Math.min(maxItemsCount, result.length);
|
|
189
|
+
return result.slice(0, count);
|
|
145
190
|
}; // end getItems
|
|
146
191
|
// items
|
|
147
192
|
const items = getItems(current);
|
|
193
|
+
// sort
|
|
194
|
+
if (sortType) {
|
|
195
|
+
items.sort(sortType);
|
|
196
|
+
if (reverse)
|
|
197
|
+
items.reverse();
|
|
198
|
+
}
|
|
199
|
+
// items count
|
|
148
200
|
const count = current
|
|
149
201
|
? (_b = current.children) === null || _b === void 0 ? void 0 : _b.length
|
|
150
202
|
: 0;
|
|
203
|
+
// items hitCount
|
|
204
|
+
const hitCount = isFilter
|
|
205
|
+
? items.length
|
|
206
|
+
: items.filter(item => columns.some(col => hitTest(col.val(item)))).length;
|
|
207
|
+
// ---------- ---------- ----------
|
|
151
208
|
// action_parentClick
|
|
209
|
+
// ---------- ---------- ----------
|
|
152
210
|
const action_parentClick = (state, item) => {
|
|
153
|
-
return setValue(state, currentKeys, item)
|
|
211
|
+
return setLocalState(setValue(state, currentKeys, item), id, {
|
|
212
|
+
selected: []
|
|
213
|
+
});
|
|
154
214
|
};
|
|
215
|
+
// ---------- ---------- ----------
|
|
155
216
|
// action_itemClick
|
|
217
|
+
// ---------- ---------- ----------
|
|
156
218
|
const action_itemClick = (state, item) => {
|
|
157
219
|
// 子アイテムがすべてプロパティのときは移動しない
|
|
158
220
|
const children = item.children;
|
|
159
|
-
if (!children)
|
|
221
|
+
if (!children || children.length === 0)
|
|
160
222
|
return state;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
223
|
+
// filterは解除
|
|
224
|
+
return setLocalState(setValue(state, currentKeys, item), id, {
|
|
225
|
+
selected: []
|
|
226
|
+
});
|
|
164
227
|
};
|
|
228
|
+
// ---------- ---------- ----------
|
|
229
|
+
// action_inputSearchText
|
|
230
|
+
// ---------- ---------- ----------
|
|
231
|
+
const action_inputSearchText = (state, e) => {
|
|
232
|
+
const input = e.currentTarget;
|
|
233
|
+
if (!input)
|
|
234
|
+
return state;
|
|
235
|
+
return setLocalState(state, id, {
|
|
236
|
+
searchText: input.value
|
|
237
|
+
});
|
|
238
|
+
}; // end action_inputSearchText
|
|
239
|
+
// ---------- ---------- ----------
|
|
240
|
+
// action_copyFolderPath
|
|
241
|
+
// ---------- ---------- ----------
|
|
242
|
+
const action_copyFolderPath = (state) => {
|
|
243
|
+
if (!current)
|
|
244
|
+
return state;
|
|
245
|
+
navigator.clipboard.writeText(current.path);
|
|
246
|
+
return state;
|
|
247
|
+
}; // end action_copyFolderPath
|
|
248
|
+
// ---------- ---------- ----------
|
|
249
|
+
// action_sort
|
|
250
|
+
// ---------- ---------- ----------
|
|
251
|
+
const action_sort = (state, column) => {
|
|
252
|
+
if (column.compare === undefined)
|
|
253
|
+
return state;
|
|
254
|
+
return setLocalState(state, id, {
|
|
255
|
+
sortType: column.compare,
|
|
256
|
+
reverse: sortKey === column.name ? !reverse : false,
|
|
257
|
+
sortKey: column.name
|
|
258
|
+
});
|
|
259
|
+
}; // end action_sort
|
|
260
|
+
// ---------- ---------- ----------
|
|
165
261
|
// VNode
|
|
262
|
+
// ---------- ---------- ----------
|
|
166
263
|
const vnode = div({
|
|
167
264
|
...deleteKeys(props, "state", "currentKeys", "columns", "itemClick", "afterRender", "extension")
|
|
168
265
|
},
|
|
169
266
|
// toolBar
|
|
170
267
|
div({
|
|
171
268
|
class: "toolBar"
|
|
172
|
-
},
|
|
269
|
+
}, input({
|
|
270
|
+
type: "text",
|
|
271
|
+
placeholder: "search keys",
|
|
272
|
+
value: searchText,
|
|
273
|
+
oninput: action_inputSearchText
|
|
274
|
+
}), SelectButton({
|
|
275
|
+
state: state,
|
|
276
|
+
id: `${createLocalKey(id)}_filter`,
|
|
277
|
+
keyNames: [createLocalKey(id), "selected"]
|
|
278
|
+
}, "FILTER"), button({
|
|
279
|
+
type: "button",
|
|
280
|
+
title: "現在のフォルダパスを、クリップボードにコピー",
|
|
281
|
+
onclick: action_copyFolderPath
|
|
282
|
+
}, "COPY")),
|
|
173
283
|
// parentItems
|
|
174
284
|
ol({}, parentItems.map(parent => li({
|
|
175
285
|
key: parent.path,
|
|
176
286
|
onclick: [action_parentClick, parent]
|
|
177
287
|
}, parent.name))),
|
|
178
288
|
// items
|
|
179
|
-
table({}, thead({}, tr({}, columns.map(col => th({
|
|
289
|
+
table({}, thead({}, tr({}, columns.map(col => th({
|
|
290
|
+
onclick: [action_sort, col]
|
|
291
|
+
}, col.name + (sortKey === col.name
|
|
292
|
+
? (reverse ? " ▼" : " ▲")
|
|
293
|
+
: ""))))), tbody({}, items.map(item => tr({
|
|
180
294
|
key: item.path,
|
|
181
295
|
onclick: item.children === undefined
|
|
182
296
|
? itemClick ? [itemClick, item] : undefined
|
|
183
297
|
: [action_itemClick, item]
|
|
184
|
-
}, columns.map(col =>
|
|
185
|
-
|
|
186
|
-
|
|
298
|
+
}, columns.map(col => {
|
|
299
|
+
const v = col.val(item);
|
|
300
|
+
return td({
|
|
301
|
+
title: String(v)
|
|
302
|
+
}, span({
|
|
303
|
+
class: typeof v === "string" && hitTest(v) ? "hit" : ""
|
|
304
|
+
}, v));
|
|
305
|
+
}))))),
|
|
187
306
|
// statusBar
|
|
188
307
|
div({
|
|
189
308
|
class: "statusBar"
|
|
190
|
-
}, `items ${items.length} / ${count}`));
|
|
309
|
+
}, `items ${items.length} / ${count}` + (searchText !== "" ? ` (${hitCount} hit)` : "")));
|
|
310
|
+
// ---------- ---------- ----------
|
|
191
311
|
// afterRender
|
|
312
|
+
// ---------- ---------- ----------
|
|
192
313
|
return afterRender ? afterRender({ state, current, extension }, vnode) : vnode;
|
|
193
314
|
};
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ステートへのパス
|
|
3
|
-
* 参照する値の型がわかりやすいよう、複数パターンをここで集約
|
|
4
|
-
*/
|
|
5
1
|
export type Keys = readonly string[];
|
|
6
2
|
export type Keys_String = Keys;
|
|
7
3
|
export type Keys_ArrayString = Keys;
|
|
@@ -11,49 +7,21 @@ export type Keys_ArrayRAFTask = Keys;
|
|
|
11
7
|
export type Keys_NavigatorItem = Keys;
|
|
12
8
|
/**
|
|
13
9
|
* パスを辿って、ステートから値を取得する
|
|
14
|
-
*
|
|
15
|
-
* @template S
|
|
16
|
-
* @template D
|
|
17
|
-
* @param {S} state - ステート
|
|
18
|
-
* @param {Keys} keyNames - 値までのパス
|
|
19
|
-
* @param {D} def - デフォルト値
|
|
20
|
-
* @returns {D} - 型保証は呼び出し側の責任
|
|
21
10
|
*/
|
|
22
11
|
export declare const getValue: <S, D>(state: S, keyNames: Keys, def: D) => D;
|
|
23
12
|
/**
|
|
24
13
|
* パスを辿って、ステートに値を設定して返す
|
|
25
|
-
*
|
|
26
|
-
* @template S
|
|
27
|
-
* @param {S} state - ステート
|
|
28
|
-
* @param {Keys} keyNames - 値までのパス
|
|
29
|
-
* @param {any} value - 設定する値
|
|
30
|
-
* @returns {S}
|
|
31
14
|
*/
|
|
32
15
|
export declare const setValue: <S>(state: S, keyNames: Keys, value: any) => S;
|
|
33
16
|
/**
|
|
34
17
|
* IDからユニーク文字列を作成する
|
|
35
|
-
*
|
|
36
|
-
* @param {string} id - ユニークID
|
|
37
|
-
* @returns {string}
|
|
38
18
|
*/
|
|
39
19
|
export declare const createLocalKey: (id: string) => string;
|
|
40
20
|
/**
|
|
41
21
|
* ステートから、ローカルステートを取得する
|
|
42
|
-
*
|
|
43
|
-
* @template S
|
|
44
|
-
* @param {S} state - ステート
|
|
45
|
-
* @param {string} id - ユニークID
|
|
46
|
-
* @param {Record<string, any>} def - 初期値
|
|
47
|
-
* @returns {Record<string, any>}
|
|
48
22
|
*/
|
|
49
23
|
export declare const getLocalState: <S>(state: S, id: string, def: Record<string, any>) => Record<string, any>;
|
|
50
24
|
/**
|
|
51
25
|
* ローカルステートを更新してステートを返す
|
|
52
|
-
*
|
|
53
|
-
* @template S
|
|
54
|
-
* @param {S} state - ステート
|
|
55
|
-
* @param {string} id - ユニークID
|
|
56
|
-
* @param {Record<string, any>} value - 設定するローカルステート
|
|
57
|
-
* @returns {S}
|
|
58
26
|
*/
|
|
59
27
|
export declare const setLocalState: <S>(state: S, id: string, value: Record<string, any>) => S;
|
|
@@ -4,13 +4,6 @@
|
|
|
4
4
|
// ---------- ---------- ---------- ---------- ----------
|
|
5
5
|
/**
|
|
6
6
|
* パスを辿って、ステートから値を取得する
|
|
7
|
-
*
|
|
8
|
-
* @template S
|
|
9
|
-
* @template D
|
|
10
|
-
* @param {S} state - ステート
|
|
11
|
-
* @param {Keys} keyNames - 値までのパス
|
|
12
|
-
* @param {D} def - デフォルト値
|
|
13
|
-
* @returns {D} - 型保証は呼び出し側の責任
|
|
14
7
|
*/
|
|
15
8
|
export const getValue = function (state, keyNames, def) {
|
|
16
9
|
let result = state;
|
|
@@ -32,12 +25,6 @@ export const getValue = function (state, keyNames, def) {
|
|
|
32
25
|
// ---------- ---------- ---------- ---------- ----------
|
|
33
26
|
/**
|
|
34
27
|
* パスを辿って、ステートに値を設定して返す
|
|
35
|
-
*
|
|
36
|
-
* @template S
|
|
37
|
-
* @param {S} state - ステート
|
|
38
|
-
* @param {Keys} keyNames - 値までのパス
|
|
39
|
-
* @param {any} value - 設定する値
|
|
40
|
-
* @returns {S}
|
|
41
28
|
*/
|
|
42
29
|
export const setValue = function (state, keyNames, value) {
|
|
43
30
|
let result = { ...state };
|
|
@@ -64,9 +51,6 @@ export const setValue = function (state, keyNames, value) {
|
|
|
64
51
|
// ---------- ---------- ---------- ---------- ----------
|
|
65
52
|
/**
|
|
66
53
|
* IDからユニーク文字列を作成する
|
|
67
|
-
*
|
|
68
|
-
* @param {string} id - ユニークID
|
|
69
|
-
* @returns {string}
|
|
70
54
|
*/
|
|
71
55
|
export const createLocalKey = (id) => `local_key_${id}`;
|
|
72
56
|
// ---------- ---------- ---------- ---------- ----------
|
|
@@ -74,12 +58,6 @@ export const createLocalKey = (id) => `local_key_${id}`;
|
|
|
74
58
|
// ---------- ---------- ---------- ---------- ----------
|
|
75
59
|
/**
|
|
76
60
|
* ステートから、ローカルステートを取得する
|
|
77
|
-
*
|
|
78
|
-
* @template S
|
|
79
|
-
* @param {S} state - ステート
|
|
80
|
-
* @param {string} id - ユニークID
|
|
81
|
-
* @param {Record<string, any>} def - 初期値
|
|
82
|
-
* @returns {Record<string, any>}
|
|
83
61
|
*/
|
|
84
62
|
export const getLocalState = function (state, id, def) {
|
|
85
63
|
const localKey = createLocalKey(id);
|
|
@@ -96,12 +74,6 @@ export const getLocalState = function (state, id, def) {
|
|
|
96
74
|
// ---------- ---------- ---------- ---------- ----------
|
|
97
75
|
/**
|
|
98
76
|
* ローカルステートを更新してステートを返す
|
|
99
|
-
*
|
|
100
|
-
* @template S
|
|
101
|
-
* @param {S} state - ステート
|
|
102
|
-
* @param {string} id - ユニークID
|
|
103
|
-
* @param {Record<string, any>} value - 設定するローカルステート
|
|
104
|
-
* @returns {S}
|
|
105
77
|
*/
|
|
106
78
|
export const setLocalState = function (state, id, value) {
|
|
107
79
|
const localKey = createLocalKey(id);
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* スクロールの余白
|
|
3
|
-
*
|
|
4
|
-
* @type {Object} ScrollMargin
|
|
5
|
-
* @property {number} top - 上までの余白
|
|
6
|
-
* @property {number} left - 左までの余白
|
|
7
|
-
* @property {number} right - 右までの余白
|
|
8
|
-
* @property {number} bottom - 下までの余白
|
|
9
3
|
*/
|
|
10
4
|
export interface ScrollMargin {
|
|
11
5
|
top: number;
|
|
@@ -15,9 +9,6 @@ export interface ScrollMargin {
|
|
|
15
9
|
}
|
|
16
10
|
/**
|
|
17
11
|
* スクロールの余白を取得する
|
|
18
|
-
*
|
|
19
|
-
* @param {Event} e - イベント
|
|
20
|
-
* @returns {ScrollMargin}
|
|
21
12
|
*/
|
|
22
13
|
export declare const getScrollMargin: (e: Event) => ScrollMargin;
|
|
23
14
|
/**
|
|
@@ -42,8 +33,5 @@ export interface MatrixState {
|
|
|
42
33
|
}
|
|
43
34
|
/**
|
|
44
35
|
* DOM から transfrom 情報を取得する
|
|
45
|
-
*
|
|
46
|
-
* @param {HTMLElement} dom - 情報を取得する DOM
|
|
47
|
-
* @returns {MatrixState}
|
|
48
36
|
*/
|
|
49
37
|
export declare const getMatrixState: (dom: HTMLElement) => MatrixState | null;
|
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
// ---------- ---------- ---------- ---------- ----------
|
|
5
5
|
/**
|
|
6
6
|
* スクロールの余白を取得する
|
|
7
|
-
*
|
|
8
|
-
* @param {Event} e - イベント
|
|
9
|
-
* @returns {ScrollMargin}
|
|
10
7
|
*/
|
|
11
8
|
export const getScrollMargin = function (e) {
|
|
12
9
|
const el = e.currentTarget;
|
|
@@ -24,9 +21,6 @@ export const getScrollMargin = function (e) {
|
|
|
24
21
|
// ---------- ---------- ---------- ---------- ----------
|
|
25
22
|
/**
|
|
26
23
|
* DOM から transfrom 情報を取得する
|
|
27
|
-
*
|
|
28
|
-
* @param {HTMLElement} dom - 情報を取得する DOM
|
|
29
|
-
* @returns {MatrixState}
|
|
30
24
|
*/
|
|
31
25
|
export const getMatrixState = (dom) => {
|
|
32
26
|
const style = getComputedStyle(dom);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hyperapp-is",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "UI foundation library for Hyperapp by is4416",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -37,8 +37,5 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"typescript": "^5.0.0",
|
|
39
39
|
"vite": "^7.3.0"
|
|
40
|
-
},
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"marked": "^17.0.4"
|
|
43
40
|
}
|
|
44
41
|
}
|