hyperapp-is 0.1.21 → 0.1.23
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
|
@@ -153,6 +153,8 @@ npm で非公開の関数 (実験用)は、解説に記載します
|
|
|
153
153
|
- [convertJsonToNavigatorItem](#convertjsontonavigatoritem)
|
|
154
154
|
- [getParentItems](#getparentitems)
|
|
155
155
|
- [NavigatorFinder](#navigatorfinder)
|
|
156
|
+
- [SearchResult](#searchresult)
|
|
157
|
+
- [NavigatorSearch](#navigatorsearch)
|
|
156
158
|
|
|
157
159
|
**animation / step.ts**
|
|
158
160
|
- [effect_throwMessageStart](#effect_throwmessagestart)
|
|
@@ -221,6 +223,7 @@ src
|
|
|
221
223
|
│ └ navigator.ts
|
|
222
224
|
│ Keys_NavigatorItem, NavigatorItem, JsonEntry, NavigatorColumn
|
|
223
225
|
│ convertJsonToNavigatorItem, getParentItems, NavigatorFinder
|
|
226
|
+
│ SearchResult, NavigatorSearch
|
|
224
227
|
│
|
|
225
228
|
├ animation
|
|
226
229
|
│ ├ step.ts
|
|
@@ -615,6 +618,10 @@ export const NavigatorFinder = function <S> (
|
|
|
615
618
|
id : string
|
|
616
619
|
currentKeys : Keys_NavigatorItem
|
|
617
620
|
columns ?: (directory: NavigatorItem | undefined) => NavigatorColumn[]
|
|
621
|
+
plugIn ?: (props: {
|
|
622
|
+
state : S
|
|
623
|
+
localState: Record<string, any>
|
|
624
|
+
}) => VNode<S>[]
|
|
618
625
|
afterRender ?: (props: {
|
|
619
626
|
state : S
|
|
620
627
|
localState: Recrod<string, any>
|
|
@@ -628,11 +635,20 @@ export const NavigatorFinder = function <S> (
|
|
|
628
635
|
- id : ユニークID (DOM ID)
|
|
629
636
|
- currentKeys : カレント NavigatorItem までのパス
|
|
630
637
|
- columns : NavigatorColumn の配列を返す関数
|
|
638
|
+
- plugIn : プラグインの挿入
|
|
631
639
|
- afterRender : レンダーフック
|
|
632
640
|
|
|
641
|
+
localState
|
|
642
|
+
- searchText: "" as string // 検索テキスト
|
|
643
|
+
- selected : [] as string[] // 選択されているボタン名
|
|
644
|
+
- sortType : undefined // ソート用比較関数: (a: NavigatorItem, b: NavigatorItem) => number
|
|
645
|
+
- reverse : false as boolean // ソートを逆順にするか
|
|
646
|
+
- sortKey : undefined as undefined | string // 使用されているソート名 (column.name)
|
|
647
|
+
|
|
633
648
|
vnode
|
|
634
649
|
```html
|
|
635
650
|
<div id={id}>
|
|
651
|
+
|
|
636
652
|
<div class="toolBar">
|
|
637
653
|
<input type="text" />
|
|
638
654
|
<button type="button">FILTER</button>
|
|
@@ -662,13 +678,65 @@ vnode
|
|
|
662
678
|
</table>
|
|
663
679
|
</div>
|
|
664
680
|
|
|
665
|
-
<!-- statusBar -->
|
|
666
681
|
<div class="statusBar">message</div>
|
|
682
|
+
|
|
683
|
+
<!-- plugIn 必要な文だけ追加 -->
|
|
684
|
+
<div id={plugInID}>
|
|
685
|
+
</div>
|
|
667
686
|
</div>
|
|
668
687
|
```
|
|
669
688
|
|
|
670
689
|
---
|
|
671
690
|
|
|
691
|
+
### SearchResult
|
|
692
|
+
`NavigatorSearch` で検索結果となる構造体
|
|
693
|
+
|
|
694
|
+
```ts
|
|
695
|
+
export interface SearchResult {
|
|
696
|
+
item : NavigatorItem
|
|
697
|
+
depth: number
|
|
698
|
+
}
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
---
|
|
702
|
+
|
|
703
|
+
### NavigatorSearch
|
|
704
|
+
`NavigatorFinder` プラグイン
|
|
705
|
+
|
|
706
|
+
```ts
|
|
707
|
+
export const NavigatorSearch = function <S> (
|
|
708
|
+
props: {
|
|
709
|
+
state : S
|
|
710
|
+
id : string
|
|
711
|
+
currentKeys : Keys_NavigatorItem
|
|
712
|
+
searchResult : (item: NavigatorItem, depth: number) => VNode<S> | VNode<S>[]
|
|
713
|
+
hitTest : (item: NavigatorItem) => boolean
|
|
714
|
+
maxItemsCount : number
|
|
715
|
+
afterRender ?: (props: {
|
|
716
|
+
state : S
|
|
717
|
+
localState: Record<string, any>
|
|
718
|
+
}, vnode: VNode<S>) => VNode<S>
|
|
719
|
+
[key: string]: any
|
|
720
|
+
}
|
|
721
|
+
): VNode<S>
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
- state : ステート
|
|
725
|
+
- id : ユニークID (DOM ID)
|
|
726
|
+
- searchResult : カードとして表示する VNode
|
|
727
|
+
- hitTest : 抽出条件
|
|
728
|
+
- maxItemsCount: 最初に表示するカードの最大数
|
|
729
|
+
- afterRender : レンダーフック
|
|
730
|
+
|
|
731
|
+
localState
|
|
732
|
+
- maxItemsCount: props.maxItemsCount as number // カードの最大表示数
|
|
733
|
+
- sortName : undefined as undefined | string // ソート名
|
|
734
|
+
- sortFn : undefined as undefined | ((a: SearchResult, b: SearchResult) => number) // 比較関数
|
|
735
|
+
- isDirectory : true // ディレクトリを表示
|
|
736
|
+
- isFile : true // ファイルを表示
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
672
740
|
## hyperapp-is/animation
|
|
673
741
|
|
|
674
742
|
### effect_throwMessageStart
|
|
@@ -35,30 +35,74 @@ export declare const getParentItems: (item: NavigatorItem | undefined) => Naviga
|
|
|
35
35
|
* - 必須項目
|
|
36
36
|
* state, id, currentKeys
|
|
37
37
|
*
|
|
38
|
+
* - 拡張項目
|
|
39
|
+
* columns, plugIn, afterRender
|
|
40
|
+
*
|
|
38
41
|
* - columns
|
|
39
42
|
* カラムの表示設定
|
|
40
43
|
*
|
|
41
|
-
* -
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* - itemClick
|
|
45
|
-
* 非ノードをクリックした際のアクション
|
|
44
|
+
* - plugIn
|
|
45
|
+
* プラグインの追加
|
|
46
46
|
*
|
|
47
47
|
* - afterRender
|
|
48
48
|
* レンダーフック
|
|
49
|
-
*
|
|
50
|
-
* - extension
|
|
51
|
-
* レンダーフックで参照できる拡張情報
|
|
52
49
|
*/
|
|
53
50
|
export declare const NavigatorFinder: <S>(props: {
|
|
54
51
|
state: S;
|
|
55
52
|
id: string;
|
|
56
53
|
currentKeys: Keys_NavigatorItem;
|
|
57
54
|
columns?: (directory: NavigatorItem | undefined) => NavigatorColumn[];
|
|
55
|
+
plugIn?: (state: S, localState: Record<string, any>) => VNode<S>[];
|
|
56
|
+
afterRender?: (props: {
|
|
57
|
+
state: S;
|
|
58
|
+
localState: Record<string, any>;
|
|
59
|
+
}, vnode: VNode<S>) => VNode<S>;
|
|
60
|
+
[key: string]: any;
|
|
61
|
+
}) => VNode<S>;
|
|
62
|
+
/**
|
|
63
|
+
* 検索結果
|
|
64
|
+
*
|
|
65
|
+
* - item
|
|
66
|
+
* ヒットしたアイテム
|
|
67
|
+
*
|
|
68
|
+
* - depth
|
|
69
|
+
* current からの深度
|
|
70
|
+
*/
|
|
71
|
+
export interface SearchResult {
|
|
72
|
+
item: NavigatorItem;
|
|
73
|
+
depth: number;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* ファイルサーチ - NavigatorFinder プラグイン
|
|
77
|
+
*
|
|
78
|
+
* - 必須項目
|
|
79
|
+
* state, id, currentKeys, searchResult, hitTest, maxItemsCount
|
|
80
|
+
*
|
|
81
|
+
* - searchResult
|
|
82
|
+
* カードとして表示するVNode
|
|
83
|
+
*
|
|
84
|
+
* - hitTest
|
|
85
|
+
* 抽出条件
|
|
86
|
+
*
|
|
87
|
+
* - maxItemsCount
|
|
88
|
+
* 最初に表示させるカードの最大数
|
|
89
|
+
*
|
|
90
|
+
* - 拡張項目
|
|
91
|
+
* afterRender
|
|
92
|
+
*
|
|
93
|
+
* - afterRender
|
|
94
|
+
* レンダーフック
|
|
95
|
+
*/
|
|
96
|
+
export declare const NavigatorSearch: <S>(props: {
|
|
97
|
+
state: S;
|
|
98
|
+
id: string;
|
|
99
|
+
currentKeys: Keys_NavigatorItem;
|
|
100
|
+
searchResult: (item: NavigatorItem, depth: number) => VNode<S> | VNode<S>[];
|
|
101
|
+
hitTest: (item: NavigatorItem) => boolean;
|
|
102
|
+
maxItemsCount: number;
|
|
58
103
|
afterRender?: (props: {
|
|
59
104
|
state: S;
|
|
60
105
|
localState: Record<string, any>;
|
|
61
106
|
}, vnode: VNode<S>) => VNode<S>;
|
|
62
|
-
extension?: Record<string, any>;
|
|
63
107
|
[key: string]: any;
|
|
64
108
|
}) => VNode<S>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// hyperapp-is / core / navigator.ts
|
|
2
|
-
import { getValue, setValue, getLocalState, setLocalState, createLocalKey } from "./state";
|
|
2
|
+
import { getValue, setValue, getLocalState, setLocalState, createLocalKey, } from "./state";
|
|
3
|
+
import { getScrollMargin } from "../dom/utils";
|
|
3
4
|
import { el, deleteKeys, SelectButton } from "./component";
|
|
4
5
|
// ---------- ---------- ---------- ---------- ----------
|
|
5
6
|
// convertJsonToNavigatorItem
|
|
@@ -61,7 +62,6 @@ export const getParentItems = (item) => {
|
|
|
61
62
|
// vnodes
|
|
62
63
|
// ---------- ---------- ---------- ---------- ----------
|
|
63
64
|
const div = el("div");
|
|
64
|
-
const section = el("section");
|
|
65
65
|
const table = el("table");
|
|
66
66
|
const thead = el("thead");
|
|
67
67
|
const tbody = el("tbody");
|
|
@@ -74,6 +74,9 @@ const li = el("li");
|
|
|
74
74
|
const button = el("button");
|
|
75
75
|
const input = el("input");
|
|
76
76
|
const span = el("span");
|
|
77
|
+
const svg = el("svg");
|
|
78
|
+
const rect = el("rect");
|
|
79
|
+
const path = el("path");
|
|
77
80
|
// ---------- ---------- ---------- ---------- ----------
|
|
78
81
|
// NavigatorFinder Component
|
|
79
82
|
// ---------- ---------- ---------- ---------- ----------
|
|
@@ -83,35 +86,33 @@ const span = el("span");
|
|
|
83
86
|
* - 必須項目
|
|
84
87
|
* state, id, currentKeys
|
|
85
88
|
*
|
|
89
|
+
* - 拡張項目
|
|
90
|
+
* columns, plugIn, afterRender
|
|
91
|
+
*
|
|
86
92
|
* - columns
|
|
87
93
|
* カラムの表示設定
|
|
88
94
|
*
|
|
89
|
-
* -
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* - itemClick
|
|
93
|
-
* 非ノードをクリックした際のアクション
|
|
95
|
+
* - plugIn
|
|
96
|
+
* プラグインの追加
|
|
94
97
|
*
|
|
95
98
|
* - afterRender
|
|
96
99
|
* レンダーフック
|
|
97
|
-
*
|
|
98
|
-
* - extension
|
|
99
|
-
* レンダーフックで参照できる拡張情報
|
|
100
100
|
*/
|
|
101
101
|
export const NavigatorFinder = function (props) {
|
|
102
102
|
var _a, _b;
|
|
103
|
-
const { state, id, currentKeys, afterRender } = props;
|
|
103
|
+
const { state, id, currentKeys, plugIn, afterRender } = props;
|
|
104
|
+
// current
|
|
104
105
|
const current = getValue(state, currentKeys, undefined);
|
|
105
106
|
// localState
|
|
106
|
-
const
|
|
107
|
+
const localState = getLocalState(state, id, {
|
|
107
108
|
searchText: "", // 検索テキスト
|
|
108
109
|
selected: [], // 選択されているボタン名
|
|
109
|
-
sortType: undefined, //
|
|
110
|
+
sortType: undefined, // ソート用比較関数: (a: NavigatorItem, b: NavigatorItem) => number
|
|
110
111
|
reverse: false, // ソートを逆順にするか
|
|
111
112
|
sortKey: undefined // 使用されているソート名 (column.name)
|
|
112
113
|
});
|
|
113
114
|
// selected filter
|
|
114
|
-
const isFilter = selected.includes(`${createLocalKey(id)}_filter`);
|
|
115
|
+
const isFilter = localState.selected.includes(`${createLocalKey(id)}_filter`);
|
|
115
116
|
// ---------- ---------- ----------
|
|
116
117
|
// createColumns
|
|
117
118
|
// ---------- ---------- ----------
|
|
@@ -163,7 +164,7 @@ export const NavigatorFinder = function (props) {
|
|
|
163
164
|
const hitTest = (text) => {
|
|
164
165
|
if (typeof text !== "string")
|
|
165
166
|
return false;
|
|
166
|
-
const S = searchText.trim().toLowerCase();
|
|
167
|
+
const S = localState.searchText.trim().toLowerCase();
|
|
167
168
|
if (S === "")
|
|
168
169
|
return false;
|
|
169
170
|
const keys = S.replace(/[ ]+/g, " ").split(" ").filter(Boolean);
|
|
@@ -179,7 +180,7 @@ export const NavigatorFinder = function (props) {
|
|
|
179
180
|
if (!item || item.children === undefined)
|
|
180
181
|
return [];
|
|
181
182
|
// filter
|
|
182
|
-
const result = isFilter && searchText !== ""
|
|
183
|
+
const result = isFilter && localState.searchText !== ""
|
|
183
184
|
? item.children.filter(child => {
|
|
184
185
|
return columns.some(col => hitTest(col.text ? col.text(child) : col.val(child)));
|
|
185
186
|
})
|
|
@@ -189,9 +190,9 @@ export const NavigatorFinder = function (props) {
|
|
|
189
190
|
// items
|
|
190
191
|
const items = getItems(current);
|
|
191
192
|
// sort
|
|
192
|
-
if (sortType) {
|
|
193
|
-
items.sort(sortType);
|
|
194
|
-
if (reverse)
|
|
193
|
+
if (localState.sortType) {
|
|
194
|
+
items.sort(localState.sortType);
|
|
195
|
+
if (localState.reverse)
|
|
195
196
|
items.reverse();
|
|
196
197
|
}
|
|
197
198
|
// items count
|
|
@@ -253,7 +254,7 @@ export const NavigatorFinder = function (props) {
|
|
|
253
254
|
return state;
|
|
254
255
|
return setLocalState(state, id, {
|
|
255
256
|
sortType: column.compare,
|
|
256
|
-
reverse: sortKey === column.name ? !reverse : false,
|
|
257
|
+
reverse: localState.sortKey === column.name ? !localState.reverse : false,
|
|
257
258
|
sortKey: column.name
|
|
258
259
|
});
|
|
259
260
|
}; // end action_sort
|
|
@@ -261,13 +262,13 @@ export const NavigatorFinder = function (props) {
|
|
|
261
262
|
// VNode
|
|
262
263
|
// ---------- ---------- ----------
|
|
263
264
|
const vnode = div({
|
|
264
|
-
...deleteKeys(props, "state", "currentKeys", "columns", "
|
|
265
|
+
...deleteKeys(props, "state", "currentKeys", "columns", "plugIn", "afterRender")
|
|
265
266
|
}, div({
|
|
266
267
|
class: "toolBar"
|
|
267
268
|
}, input({
|
|
268
269
|
type: "text",
|
|
269
270
|
placeholder: "search keys",
|
|
270
|
-
value: searchText,
|
|
271
|
+
value: localState.searchText,
|
|
271
272
|
oninput: action_inputSearchText
|
|
272
273
|
}), SelectButton({
|
|
273
274
|
state: state,
|
|
@@ -287,8 +288,8 @@ export const NavigatorFinder = function (props) {
|
|
|
287
288
|
}, table({}, thead({}, tr({}, columns.map(col => th({
|
|
288
289
|
class: col.compare ? "sort" : "",
|
|
289
290
|
onclick: [action_sort, col]
|
|
290
|
-
}, col.name + (sortKey === col.name
|
|
291
|
-
? (reverse ? " ▼" : " ▲")
|
|
291
|
+
}, col.name + (localState.sortKey === col.name
|
|
292
|
+
? (localState.reverse ? " ▼" : " ▲")
|
|
292
293
|
: ""))))), tbody({}, items.map(item => tr({
|
|
293
294
|
key: item.path,
|
|
294
295
|
class: item.children === undefined
|
|
@@ -307,18 +308,264 @@ export const NavigatorFinder = function (props) {
|
|
|
307
308
|
}, v));
|
|
308
309
|
})))))),
|
|
309
310
|
// statusBar
|
|
310
|
-
div({ class: "statusBar" }, message)
|
|
311
|
+
div({ class: "statusBar" }, message),
|
|
312
|
+
// plugIn
|
|
313
|
+
plugIn
|
|
314
|
+
? plugIn(state, localState)
|
|
315
|
+
: []);
|
|
311
316
|
// ---------- ---------- ----------
|
|
312
317
|
// afterRender
|
|
313
318
|
// ---------- ---------- ----------
|
|
314
|
-
return afterRender ? afterRender({
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
319
|
+
return afterRender ? afterRender({ state, localState }, vnode) : vnode;
|
|
320
|
+
};
|
|
321
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
322
|
+
// svg icon
|
|
323
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
324
|
+
// icon_depth
|
|
325
|
+
const icon_depth = svg({
|
|
326
|
+
width: 24,
|
|
327
|
+
height: 24,
|
|
328
|
+
viewBox: "0 0 24 24",
|
|
329
|
+
fill: "none",
|
|
330
|
+
stroke: "currentColor",
|
|
331
|
+
strokeWidth: 2,
|
|
332
|
+
strokeLinecap: "round",
|
|
333
|
+
strokeLinejoin: "round"
|
|
334
|
+
}, rect({
|
|
335
|
+
x: 9,
|
|
336
|
+
y: 3,
|
|
337
|
+
width: 6,
|
|
338
|
+
height: 4,
|
|
339
|
+
rx: 1
|
|
340
|
+
}), rect({
|
|
341
|
+
x: 3,
|
|
342
|
+
y: 15,
|
|
343
|
+
width: 6,
|
|
344
|
+
height: 4,
|
|
345
|
+
rx: 1
|
|
346
|
+
}), rect({
|
|
347
|
+
x: 15,
|
|
348
|
+
y: 15,
|
|
349
|
+
width: 6,
|
|
350
|
+
height: 4,
|
|
351
|
+
rx: 1
|
|
352
|
+
}), path({
|
|
353
|
+
d: "M12 7v4"
|
|
354
|
+
}), path({
|
|
355
|
+
d: "M6 15v-4h12v4"
|
|
356
|
+
}));
|
|
357
|
+
// icon_name
|
|
358
|
+
const icon_name = svg({
|
|
359
|
+
width: 24,
|
|
360
|
+
height: 24,
|
|
361
|
+
viewBox: "0 0 24 24",
|
|
362
|
+
fill: "none",
|
|
363
|
+
stroke: "currentColor",
|
|
364
|
+
strokeWidth: 2,
|
|
365
|
+
strokeLinecap: "round",
|
|
366
|
+
strokeLinejoin: "round"
|
|
367
|
+
}, path({ d: "M4 18l2-8 2 8M5 14h2" }), path({ d: "M10 10h6l-6 8h6" }), path({ d: "M20 6v12" }), path({ d: "M17 15l3 3 3-3" }));
|
|
368
|
+
// icon_directory
|
|
369
|
+
const icon_directory = svg({
|
|
370
|
+
width: 24,
|
|
371
|
+
height: 24,
|
|
372
|
+
viewBox: "0 0 24 24",
|
|
373
|
+
fill: "none",
|
|
374
|
+
stroke: "currentColor",
|
|
375
|
+
strokeWidth: 2,
|
|
376
|
+
strokeLinecap: "round",
|
|
377
|
+
strokeLinejoin: "round"
|
|
378
|
+
}, path({ d: "M3 7h6l2 2h10v8a2 2 0 0 1-2 2H3z" }));
|
|
379
|
+
// icon_file
|
|
380
|
+
const icon_file = svg({
|
|
381
|
+
width: 24,
|
|
382
|
+
height: 24,
|
|
383
|
+
viewBox: "0 0 24 24",
|
|
384
|
+
fill: "none",
|
|
385
|
+
stroke: "currentColor",
|
|
386
|
+
strokeWidth: 2,
|
|
387
|
+
strokeLinecap: "round",
|
|
388
|
+
strokeLinejoin: "round"
|
|
389
|
+
}, path({ d: "M6 2h9l5 5v15a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2z" }), path({ d: "M14 2v6h6" }));
|
|
390
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
391
|
+
// NavigatorSearch Component (NavigatorFinder plugIn)
|
|
392
|
+
// ---------- ---------- ---------- ---------- ----------
|
|
393
|
+
/**
|
|
394
|
+
* ファイルサーチ - NavigatorFinder プラグイン
|
|
395
|
+
*
|
|
396
|
+
* - 必須項目
|
|
397
|
+
* state, id, currentKeys, searchResult, hitTest, maxItemsCount
|
|
398
|
+
*
|
|
399
|
+
* - searchResult
|
|
400
|
+
* カードとして表示するVNode
|
|
401
|
+
*
|
|
402
|
+
* - hitTest
|
|
403
|
+
* 抽出条件
|
|
404
|
+
*
|
|
405
|
+
* - maxItemsCount
|
|
406
|
+
* 最初に表示させるカードの最大数
|
|
407
|
+
*
|
|
408
|
+
* - 拡張項目
|
|
409
|
+
* afterRender
|
|
410
|
+
*
|
|
411
|
+
* - afterRender
|
|
412
|
+
* レンダーフック
|
|
413
|
+
*/
|
|
414
|
+
export const NavigatorSearch = function (props) {
|
|
415
|
+
const { state, id, currentKeys, searchResult, hitTest, afterRender } = props;
|
|
416
|
+
// localKey
|
|
417
|
+
const localKey = createLocalKey(id);
|
|
418
|
+
// localState
|
|
419
|
+
const localState = getLocalState(state, id, {
|
|
420
|
+
maxItemsCount: props.maxItemsCount, // カードの最大表示数
|
|
421
|
+
sortName: undefined, // ソート名
|
|
422
|
+
sortFn: undefined, // 比較関数
|
|
423
|
+
isDirectory: true, // ディレクトリを表示
|
|
424
|
+
isFile: true // ファイルを表示
|
|
425
|
+
});
|
|
426
|
+
// current
|
|
427
|
+
const current = getValue(state, currentKeys, undefined);
|
|
428
|
+
// ---------- ---------- ----------
|
|
429
|
+
// searchItems
|
|
430
|
+
// ---------- ---------- ----------
|
|
431
|
+
/**
|
|
432
|
+
* アイテムの検索
|
|
433
|
+
* 検索アイテムのフラット化をしていないので、速度によっては拡張を検討
|
|
434
|
+
*/
|
|
435
|
+
const searchItems = (item, depth) => {
|
|
436
|
+
if (!item)
|
|
437
|
+
return [];
|
|
438
|
+
const result = [];
|
|
439
|
+
if (hitTest(item))
|
|
440
|
+
result.push({ item, depth });
|
|
441
|
+
if (item.children && item.children.length !== 0) {
|
|
442
|
+
item.children.forEach(child => {
|
|
443
|
+
const r = searchItems(child, depth + 1);
|
|
444
|
+
if (r.length !== 0)
|
|
445
|
+
result.push(...r);
|
|
446
|
+
});
|
|
322
447
|
}
|
|
323
|
-
|
|
448
|
+
return result;
|
|
449
|
+
}; // end searchItems
|
|
450
|
+
// get items
|
|
451
|
+
const items = current
|
|
452
|
+
? searchItems(current, 0)
|
|
453
|
+
: [];
|
|
454
|
+
// sort
|
|
455
|
+
if (localState.sortFn !== undefined)
|
|
456
|
+
items.sort(localState.sortFn);
|
|
457
|
+
// drawItems (filter, maxItemsCount の適用)
|
|
458
|
+
const drawItems = items.filter(item => {
|
|
459
|
+
return item.item.children
|
|
460
|
+
? localState.isDirectory
|
|
461
|
+
: localState.isFile;
|
|
462
|
+
}).slice(0, localState.maxItemsCount);
|
|
463
|
+
// get parentItems
|
|
464
|
+
const parentItems = current
|
|
465
|
+
? getParentItems(current).concat(current)
|
|
466
|
+
: [];
|
|
467
|
+
// message
|
|
468
|
+
const message = `hit ${items.length} items`;
|
|
469
|
+
// ---------- ---------- ----------
|
|
470
|
+
// action_itemsScroll
|
|
471
|
+
// ---------- ---------- ----------
|
|
472
|
+
/**
|
|
473
|
+
* items のスクロール状況で、maxItemsCount を追加
|
|
474
|
+
*/
|
|
475
|
+
const action_itemsScroll = (state, e) => {
|
|
476
|
+
const margin = getScrollMargin(e);
|
|
477
|
+
return setLocalState(state, id, {
|
|
478
|
+
maxItemsCount: margin.bottom < 10
|
|
479
|
+
? localState.maxItemsCount + 10 < items.length
|
|
480
|
+
? localState.maxItemsCount + 10
|
|
481
|
+
: Math.max(10, items.length)
|
|
482
|
+
: localState.maxItemsCount
|
|
483
|
+
});
|
|
484
|
+
};
|
|
485
|
+
// ---------- ---------- ----------
|
|
486
|
+
// action_setSort
|
|
487
|
+
// ---------- ---------- ----------
|
|
488
|
+
/**
|
|
489
|
+
* 仕様するソート名をセット
|
|
490
|
+
* sortFn をステートに持つように変更する場合、ここも修正
|
|
491
|
+
*/
|
|
492
|
+
const action_setSort = (state, newSortName) => {
|
|
493
|
+
const reverse = localState.sortName === newSortName;
|
|
494
|
+
const obj = {
|
|
495
|
+
"depth": (a, b) => a.depth - b.depth,
|
|
496
|
+
"name": (a, b) => {
|
|
497
|
+
if (a.item.name === b.item.name)
|
|
498
|
+
return 0;
|
|
499
|
+
return a.item.name < b.item.name ? -1 : 1;
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
const fn = obj[newSortName] !== undefined
|
|
503
|
+
? reverse
|
|
504
|
+
? (a, b) => obj[newSortName](b, a)
|
|
505
|
+
: (a, b) => obj[newSortName](a, b)
|
|
506
|
+
: (a, b) => {
|
|
507
|
+
return a.depth === b.depth
|
|
508
|
+
? obj["name"](a, b)
|
|
509
|
+
: obj["depth"](a, b);
|
|
510
|
+
};
|
|
511
|
+
return setLocalState(state, id, {
|
|
512
|
+
sortName: reverse ? `r_${newSortName}` : newSortName,
|
|
513
|
+
sortFn: fn
|
|
514
|
+
});
|
|
515
|
+
};
|
|
516
|
+
// ---------- ---------- ----------
|
|
517
|
+
// vnode
|
|
518
|
+
// ---------- ---------- ----------
|
|
519
|
+
const vnode = div({
|
|
520
|
+
...deleteKeys(props, "state", "currentKeys", "searchResult", "hitTest", "maxItemsCount", "afterRender")
|
|
521
|
+
},
|
|
522
|
+
// toolBar
|
|
523
|
+
div({
|
|
524
|
+
class: "toolBar"
|
|
525
|
+
},
|
|
526
|
+
// sort
|
|
527
|
+
button({
|
|
528
|
+
type: "button",
|
|
529
|
+
onclick: [action_setSort, "depth"]
|
|
530
|
+
}, icon_depth), button({
|
|
531
|
+
type: "button",
|
|
532
|
+
onclick: [action_setSort, "name"]
|
|
533
|
+
}, icon_name),
|
|
534
|
+
// filter
|
|
535
|
+
button({
|
|
536
|
+
type: "button",
|
|
537
|
+
class: localState.isDirectory ? "" : "ignore",
|
|
538
|
+
onclick: (state) => setLocalState(state, id, {
|
|
539
|
+
isDirectory: !localState.isDirectory
|
|
540
|
+
})
|
|
541
|
+
}, icon_directory), button({
|
|
542
|
+
type: "button",
|
|
543
|
+
class: localState.isFile ? "" : "ignore",
|
|
544
|
+
onclick: (state) => setLocalState(state, id, {
|
|
545
|
+
isFile: !localState.isFile
|
|
546
|
+
})
|
|
547
|
+
}, icon_file)),
|
|
548
|
+
// parentItems
|
|
549
|
+
div({
|
|
550
|
+
class: "parentItems"
|
|
551
|
+
}, ol({}, parentItems.map(item => li({
|
|
552
|
+
onclick: (state) => setValue(state, currentKeys, item)
|
|
553
|
+
}, item.name)))),
|
|
554
|
+
// items
|
|
555
|
+
div({
|
|
556
|
+
class: "items",
|
|
557
|
+
onscroll: action_itemsScroll
|
|
558
|
+
}, ul({}, drawItems.map(item => li({
|
|
559
|
+
class: "item",
|
|
560
|
+
key: item.item.path,
|
|
561
|
+
title: item.item.path
|
|
562
|
+
}, searchResult(item.item, item.depth))))),
|
|
563
|
+
// statusBar
|
|
564
|
+
div({
|
|
565
|
+
class: "statusBar"
|
|
566
|
+
}, message));
|
|
567
|
+
// ---------- ---------- ----------
|
|
568
|
+
// afterRender
|
|
569
|
+
// ---------- ---------- ----------
|
|
570
|
+
return afterRender ? afterRender({ state, localState }, vnode) : vnode;
|
|
324
571
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export type { Keys, Keys_String, Keys_ArrayString, Keys_Number, Keys_ArrayNumber, Keys_ArrayRAFTask, Keys_NavigatorItem, } from "./core/state";
|
|
2
|
-
export type { NavigatorItem, JsonEntry, NavigatorColumn } from "./core/navigator";
|
|
2
|
+
export type { NavigatorItem, JsonEntry, NavigatorColumn, SearchResult } from "./core/navigator";
|
|
3
3
|
export { getValue, setValue, getLocalState, setLocalState, createLocalKey } from "./core/state";
|
|
4
4
|
export { el, concatAction, getClassList, deleteKeys, Route, SelectButton, OptionButton } from "./core/component";
|
|
5
|
-
export { convertJsonToNavigatorItem, getParentItems, NavigatorFinder } from "./core/navigator";
|
|
5
|
+
export { convertJsonToNavigatorItem, getParentItems, NavigatorFinder, NavigatorSearch } from "./core/navigator";
|
|
6
6
|
export type { InternalEffect, RAFEvent } from "./animation/raf";
|
|
7
7
|
export type { CSSProperty } from "./animation/properties";
|
|
8
8
|
export { RAFTask, subscription_RAFManager } from "./animation/raf";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// hyperapp-is / index.ts
|
|
2
2
|
export { getValue, setValue, getLocalState, setLocalState, createLocalKey } from "./core/state";
|
|
3
3
|
export { el, concatAction, getClassList, deleteKeys, Route, SelectButton, OptionButton } from "./core/component";
|
|
4
|
-
export { convertJsonToNavigatorItem, getParentItems, NavigatorFinder } from "./core/navigator";
|
|
4
|
+
export { convertJsonToNavigatorItem, getParentItems, NavigatorFinder, NavigatorSearch } from "./core/navigator";
|
|
5
5
|
export { RAFTask, subscription_RAFManager } from "./animation/raf";
|
|
6
6
|
export { progress_easing } from "./animation/easing";
|
|
7
7
|
export { createUnits, createRAFProperties, effect_RAFProperties } from "./animation/properties";
|