jsbox-cview 1.4.4 → 1.5.1
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.
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Base } from "./base";
|
|
2
|
+
import { cvid } from "../utils/cvid";
|
|
3
|
+
|
|
4
|
+
type MenuItem = {
|
|
5
|
+
title: string;
|
|
6
|
+
symbol: string;
|
|
7
|
+
handler: () => void;
|
|
8
|
+
destructive?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const RegisteredOCClassName: Set<string> = new Set()
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 动态上下文菜单视图,此视图是为了弥补JSBox中无法动态调整上下文菜单的缺陷而设计的。
|
|
15
|
+
*
|
|
16
|
+
* 此视图除了一般UIView的props, layout, events, views四个参数外,还有必须的特殊参数:
|
|
17
|
+
* 1. classname?: string OC类名,如果不指定则会自动生成一个唯一的类名。
|
|
18
|
+
* 如果有不同的DynamicContextMenuView实例使用相同的OC类,那么无法确定弹出的contextMenu是绑定了哪个实例。换言之,实例A弹出的Menu可能是绑定的实例B。
|
|
19
|
+
* 如果这样做,必须使用下面generateContextMenu的sender参数来定位。
|
|
20
|
+
* 2. generateContextMenu: (sender: UIView) => { title: string; items: MenuItem[]; } 生成上下文菜单的回调函数。
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
export class DynamicContextMenuView extends Base<UIView, UiTypes.RuntimeOptions> {
|
|
24
|
+
private generateContextMenu: (sender: UIView) => { title: string; items: MenuItem[]; };
|
|
25
|
+
private _ocClassName: string;
|
|
26
|
+
_defineView: () => UiTypes.RuntimeOptions;
|
|
27
|
+
|
|
28
|
+
constructor({ classname, generateContextMenu, props, layout, events, views }: {
|
|
29
|
+
classname?: string;
|
|
30
|
+
generateContextMenu: (sender: UIView) => { title: string; items: MenuItem[]; };
|
|
31
|
+
props: UiTypes.BaseViewProps;
|
|
32
|
+
layout?: (make: MASConstraintMaker, view: UIView) => void;
|
|
33
|
+
events?: UiTypes.BaseViewEvents;
|
|
34
|
+
views?: UiTypes.AllViewOptions[];
|
|
35
|
+
}) {
|
|
36
|
+
super();
|
|
37
|
+
this._ocClassName = classname || `DynamicContextMenuView_${cvid.newId}`;
|
|
38
|
+
this.generateContextMenu = generateContextMenu;
|
|
39
|
+
const runtimeView = this.createRuntimeView();
|
|
40
|
+
this._defineView = () => {
|
|
41
|
+
return {
|
|
42
|
+
type: "runtime",
|
|
43
|
+
props: {
|
|
44
|
+
...props,
|
|
45
|
+
id: this.id,
|
|
46
|
+
view: runtimeView
|
|
47
|
+
},
|
|
48
|
+
layout,
|
|
49
|
+
events,
|
|
50
|
+
views
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private defineOCClass() {
|
|
56
|
+
if (RegisteredOCClassName.has(this._ocClassName)) return;
|
|
57
|
+
RegisteredOCClassName.add(this._ocClassName);
|
|
58
|
+
$define({
|
|
59
|
+
type: this._ocClassName + " : UIView <UIContextMenuInteractionDelegate>",
|
|
60
|
+
events: {
|
|
61
|
+
"contextMenuInteraction:configurationForMenuAtLocation:": (interacton: any, point: JBPoint) => {
|
|
62
|
+
const view = interacton.$view().jsValue()
|
|
63
|
+
const menu = this.generateContextMenu(view);
|
|
64
|
+
return this.createContextMenuConfiguration(menu);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private createContextMenuConfiguration({ title, items }: { title: string, items: MenuItem[] }) {
|
|
71
|
+
return $objc("UIContextMenuConfiguration").$configurationWithIdentifier_previewProvider_actionProvider(
|
|
72
|
+
null,
|
|
73
|
+
null,
|
|
74
|
+
$block("UIMenu *, NSArray *", () => {
|
|
75
|
+
const actions = items.map(item => {
|
|
76
|
+
const action = $objc("UIAction").$actionWithTitle_image_identifier_handler(
|
|
77
|
+
item.title,
|
|
78
|
+
item.symbol,
|
|
79
|
+
null,
|
|
80
|
+
$block("void, UIAction *", () => item.handler())
|
|
81
|
+
);
|
|
82
|
+
if (item.destructive) action.$setAttributes(1 << 1);
|
|
83
|
+
return action;
|
|
84
|
+
})
|
|
85
|
+
return $objc("UIMenu").$menuWithTitle_children(title, actions);
|
|
86
|
+
})
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private createRuntimeView() {
|
|
91
|
+
this.defineOCClass();
|
|
92
|
+
const view = $objc(this._ocClassName).invoke("alloc.init");
|
|
93
|
+
const interaction = $objc("UIContextMenuInteraction")
|
|
94
|
+
.invoke("alloc")
|
|
95
|
+
.invoke("initWithDelegate", view);
|
|
96
|
+
view.$addInteraction(interaction);
|
|
97
|
+
return view;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DynamicContextMenuView = void 0;
|
|
4
|
+
const base_1 = require("./base");
|
|
5
|
+
const cvid_1 = require("../utils/cvid");
|
|
6
|
+
const RegisteredOCClassName = new Set();
|
|
7
|
+
/**
|
|
8
|
+
* 动态上下文菜单视图,此视图是为了弥补JSBox中无法动态调整上下文菜单的缺陷而设计的。
|
|
9
|
+
*
|
|
10
|
+
* 此视图除了一般UIView的props, layout, events, views四个参数外,还有必须的特殊参数:
|
|
11
|
+
* 1. classname?: string OC类名,如果不指定则会自动生成一个唯一的类名。
|
|
12
|
+
* 如果有不同的DynamicContextMenuView实例使用相同的OC类,那么无法确定弹出的contextMenu是绑定了哪个实例。换言之,实例A弹出的Menu可能是绑定的实例B。
|
|
13
|
+
* 如果这样做,必须使用下面generateContextMenu的sender参数来定位。
|
|
14
|
+
* 2. generateContextMenu: (sender: UIView) => { title: string; items: MenuItem[]; } 生成上下文菜单的回调函数。
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
class DynamicContextMenuView extends base_1.Base {
|
|
18
|
+
constructor({ classname, generateContextMenu, props, layout, events, views }) {
|
|
19
|
+
super();
|
|
20
|
+
this._ocClassName = classname || `DynamicContextMenuView_${cvid_1.cvid.newId}`;
|
|
21
|
+
this.generateContextMenu = generateContextMenu;
|
|
22
|
+
const runtimeView = this.createRuntimeView();
|
|
23
|
+
this._defineView = () => {
|
|
24
|
+
return {
|
|
25
|
+
type: "runtime",
|
|
26
|
+
props: Object.assign(Object.assign({}, props), { id: this.id, view: runtimeView }),
|
|
27
|
+
layout,
|
|
28
|
+
events,
|
|
29
|
+
views
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
defineOCClass() {
|
|
34
|
+
if (RegisteredOCClassName.has(this._ocClassName))
|
|
35
|
+
return;
|
|
36
|
+
RegisteredOCClassName.add(this._ocClassName);
|
|
37
|
+
$define({
|
|
38
|
+
type: this._ocClassName + " : UIView <UIContextMenuInteractionDelegate>",
|
|
39
|
+
events: {
|
|
40
|
+
"contextMenuInteraction:configurationForMenuAtLocation:": (interacton, point) => {
|
|
41
|
+
const view = interacton.$view().jsValue();
|
|
42
|
+
const menu = this.generateContextMenu(view);
|
|
43
|
+
return this.createContextMenuConfiguration(menu);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
createContextMenuConfiguration({ title, items }) {
|
|
49
|
+
return $objc("UIContextMenuConfiguration").$configurationWithIdentifier_previewProvider_actionProvider(null, null, $block("UIMenu *, NSArray *", () => {
|
|
50
|
+
const actions = items.map(item => {
|
|
51
|
+
const action = $objc("UIAction").$actionWithTitle_image_identifier_handler(item.title, item.symbol, null, $block("void, UIAction *", () => item.handler()));
|
|
52
|
+
if (item.destructive)
|
|
53
|
+
action.$setAttributes(1 << 1);
|
|
54
|
+
return action;
|
|
55
|
+
});
|
|
56
|
+
return $objc("UIMenu").$menuWithTitle_children(title, actions);
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
createRuntimeView() {
|
|
60
|
+
this.defineOCClass();
|
|
61
|
+
const view = $objc(this._ocClassName).invoke("alloc.init");
|
|
62
|
+
const interaction = $objc("UIContextMenuInteraction")
|
|
63
|
+
.invoke("alloc")
|
|
64
|
+
.invoke("initWithDelegate", view);
|
|
65
|
+
view.$addInteraction(interaction);
|
|
66
|
+
return view;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.DynamicContextMenuView = DynamicContextMenuView;
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./components/base"), exports);
|
|
18
18
|
__exportStar(require("./components/custom-navigation-bar"), exports);
|
|
19
|
+
__exportStar(require("./components/dynamic-contextmenu-view"), exports);
|
|
19
20
|
__exportStar(require("./components/dynamic-itemsize-matrix"), exports);
|
|
20
21
|
__exportStar(require("./components/dynamic-preference-listview"), exports);
|
|
21
22
|
__exportStar(require("./components/dynamic-rowheight-list"), exports);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const dynamic_contextmenu_view_1 = require("../components/dynamic-contextmenu-view");
|
|
4
|
+
let menuIndex = 0;
|
|
5
|
+
const menuList = [
|
|
6
|
+
{
|
|
7
|
+
title: "菜单1",
|
|
8
|
+
items: [
|
|
9
|
+
{
|
|
10
|
+
title: "变成菜单1",
|
|
11
|
+
symbol: "plus",
|
|
12
|
+
handler: () => {
|
|
13
|
+
menuIndex = 0;
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
title: "变成菜单2",
|
|
18
|
+
symbol: "plus",
|
|
19
|
+
destructive: true,
|
|
20
|
+
handler: () => {
|
|
21
|
+
menuIndex = 1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
title: "菜单2",
|
|
28
|
+
items: [
|
|
29
|
+
{
|
|
30
|
+
title: "变成菜单1",
|
|
31
|
+
symbol: "plus",
|
|
32
|
+
handler: () => {
|
|
33
|
+
menuIndex = 0;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
title: "变成菜单2",
|
|
38
|
+
symbol: "plus",
|
|
39
|
+
handler: () => {
|
|
40
|
+
menuIndex = 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
const view = new dynamic_contextmenu_view_1.DynamicContextMenuView({
|
|
47
|
+
generateContextMenu: (sender) => {
|
|
48
|
+
return menuList[menuIndex];
|
|
49
|
+
},
|
|
50
|
+
props: {},
|
|
51
|
+
layout: (make, view) => {
|
|
52
|
+
make.center.equalTo(view.super);
|
|
53
|
+
make.size.equalTo($size(100, 100));
|
|
54
|
+
},
|
|
55
|
+
views: [{
|
|
56
|
+
type: "label",
|
|
57
|
+
props: {
|
|
58
|
+
text: "长按我",
|
|
59
|
+
textColor: $color("black"),
|
|
60
|
+
align: $align.center
|
|
61
|
+
},
|
|
62
|
+
layout: $layout.center
|
|
63
|
+
}]
|
|
64
|
+
});
|
|
65
|
+
$ui.render({
|
|
66
|
+
views: [view.definition]
|
|
67
|
+
});
|
package/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './components/base';
|
|
2
2
|
export * from './components/custom-navigation-bar';
|
|
3
|
+
export * from './components/dynamic-contextmenu-view';
|
|
3
4
|
export * from './components/dynamic-itemsize-matrix';
|
|
4
5
|
export * from './components/dynamic-preference-listview';
|
|
5
6
|
export * from './components/dynamic-rowheight-list';
|
package/package.json
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { DynamicContextMenuView } from "../components/dynamic-contextmenu-view";
|
|
2
|
+
|
|
3
|
+
let menuIndex = 0;
|
|
4
|
+
const menuList = [
|
|
5
|
+
{
|
|
6
|
+
title: "菜单1",
|
|
7
|
+
items: [
|
|
8
|
+
{
|
|
9
|
+
title: "变成菜单1",
|
|
10
|
+
symbol: "plus",
|
|
11
|
+
handler: () => {
|
|
12
|
+
menuIndex = 0;
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
title: "变成菜单2",
|
|
17
|
+
symbol: "plus",
|
|
18
|
+
destructive: true,
|
|
19
|
+
handler: () => {
|
|
20
|
+
menuIndex = 1;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
title: "菜单2",
|
|
27
|
+
items: [
|
|
28
|
+
{
|
|
29
|
+
title: "变成菜单1",
|
|
30
|
+
symbol: "plus",
|
|
31
|
+
handler: () => {
|
|
32
|
+
menuIndex = 0;
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
title: "变成菜单2",
|
|
37
|
+
symbol: "plus",
|
|
38
|
+
handler: () => {
|
|
39
|
+
menuIndex = 1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
const view = new DynamicContextMenuView({
|
|
47
|
+
generateContextMenu: (sender) => {
|
|
48
|
+
return menuList[menuIndex]
|
|
49
|
+
},
|
|
50
|
+
props: {},
|
|
51
|
+
layout: (make, view) => {
|
|
52
|
+
make.center.equalTo(view.super);
|
|
53
|
+
make.size.equalTo($size(100, 100));
|
|
54
|
+
},
|
|
55
|
+
views: [{
|
|
56
|
+
type: "label",
|
|
57
|
+
props: {
|
|
58
|
+
text: "长按我",
|
|
59
|
+
textColor: $color("black"),
|
|
60
|
+
align: $align.center
|
|
61
|
+
},
|
|
62
|
+
layout: $layout.center
|
|
63
|
+
}]
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
$ui.render({
|
|
67
|
+
views: [view.definition]
|
|
68
|
+
})
|