@rnmapbox/maps 10.0.0-beta.44 → 10.0.0-beta.45
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/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/RCTMGLPackage.java +0 -2
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/annotation/RCTMGLMarkerView.kt +162 -51
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/annotation/RCTMGLMarkerViewManager.kt +10 -0
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/annotation/RCTMGLPointAnnotation.kt +6 -6
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/camera/CameraStop.kt +5 -1
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/images/RCTMGLImages.kt +22 -2
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/mapview/RCTMGLMapView.kt +17 -19
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/styles/RCTMGLStyle.kt +1 -1
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/utils/DownloadMapImageTask.kt +2 -1
- package/docs/MapboxGL.md +1 -1
- package/docs/MarkerView.md +17 -10
- package/docs/PointAnnotation.md +1 -1
- package/docs/SymbolLayer.md +1 -1
- package/docs/docs.json +116 -102
- package/index.d.ts +1 -0
- package/ios/RCTMGL-v10/RCTLog.swift +5 -5
- package/ios/RCTMGL-v10/RCTMGLMapViewManager.swift +2 -2
- package/ios/RCTMGL-v10/RCTMGLMarkerView.swift +186 -105
- package/ios/RCTMGL-v10/RCTMGLMarkerViewManager.m +2 -1
- package/ios/RCTMGL-v10/RCTMGLShapeSourceManager.swift +1 -1
- package/ios/RCTMGL-v10/RCTMGLUtils.swift +1 -1
- package/ios/RCTMGL-v10/RCTMGLVectorLayer.swift +1 -1
- package/javascript/components/AbstractLayer.tsx +6 -3
- package/javascript/components/MarkerView.tsx +81 -77
- package/javascript/components/PointAnnotation.tsx +1 -1
- package/javascript/components/SymbolLayer.tsx +2 -2
- package/javascript/utils/index.d.ts +3 -3
- package/package.json +1 -1
- package/scripts/autogenHelpers/DocJSONBuilder.js +17 -1
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/annotation/RCTMGLMarkerViewWrapper.kt +0 -8
- package/android/rctmgl/src/main/java-v10/com/mapbox/rctmgl/components/annotation/RCTMGLMarkerViewWrapperManager.kt +0 -21
- package/ios/RCTMGL-v10/RCTMGLMarkerViewWrapper.swift +0 -24
- package/ios/RCTMGL-v10/RCTMGLMarkerViewWrapperManager.m +0 -8
- package/ios/RCTMGL-v10/RCTMGLMarkerViewWrapperManager.swift +0 -14
|
@@ -23,7 +23,7 @@ extension RCTMGLShapeSourceManager {
|
|
|
23
23
|
let view = viewRegistry![reactTag]
|
|
24
24
|
|
|
25
25
|
guard let shapeSource = view! as? RCTMGLShapeSource else {
|
|
26
|
-
|
|
26
|
+
RCTMGLLogError("Invalid react tag, could not find RCTMGLShapeSource");
|
|
27
27
|
rejecter(name, "Unknown find reactTag: \(reactTag)", nil)
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
@@ -35,7 +35,7 @@ class RCTMGLUtils {
|
|
|
35
35
|
RCTMGLImageQueue.sharedInstance.addImage(objects[imageName], scale: scale, bridge:bridge) {
|
|
36
36
|
(error,image) in
|
|
37
37
|
if image == nil {
|
|
38
|
-
|
|
38
|
+
RCTMGLLogWarn("Failed to fetch image: \(imageName) error:\(error)")
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
41
|
DispatchQueue.main.async {
|
|
@@ -15,7 +15,7 @@ class RCTMGLVectorLayer: RCTMGLLayer {
|
|
|
15
15
|
((MGLVectorStyleLayer *) self.styleLayer).predicate = predicate;
|
|
16
16
|
}
|
|
17
17
|
@catch (NSException* exception) {
|
|
18
|
-
|
|
18
|
+
RCTMGLLogError(@"Invalid predicate: %@ on layer %@ - %@ reason: %@", predicate, self, exception.name, exception.reason);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -4,7 +4,7 @@ import { NativeMethods, processColor } from 'react-native';
|
|
|
4
4
|
|
|
5
5
|
import { getFilter } from '../utils/filterUtils';
|
|
6
6
|
import { transformStyle } from '../utils/StyleValue';
|
|
7
|
-
import { AllLayerStyleProps } from '../utils/MapboxStyles';
|
|
7
|
+
import { AllLayerStyleProps, Expression } from '../utils/MapboxStyles';
|
|
8
8
|
|
|
9
9
|
type PropsBase = {
|
|
10
10
|
id: string;
|
|
@@ -14,7 +14,7 @@ type PropsBase = {
|
|
|
14
14
|
aboveLayerID?: string;
|
|
15
15
|
belowLayerID?: string;
|
|
16
16
|
layerIndex?: number;
|
|
17
|
-
filter?:
|
|
17
|
+
filter?: Expression;
|
|
18
18
|
style: AllLayerStyleProps;
|
|
19
19
|
};
|
|
20
20
|
|
|
@@ -62,7 +62,10 @@ class AbstractLayer<
|
|
|
62
62
|
if (this.nativeLayer) {
|
|
63
63
|
let propsToPass = props;
|
|
64
64
|
if (props.style) {
|
|
65
|
-
propsToPass = {
|
|
65
|
+
propsToPass = {
|
|
66
|
+
...props,
|
|
67
|
+
reactStyle: this.getStyle(props.style as AllLayerStyleProps),
|
|
68
|
+
};
|
|
66
69
|
}
|
|
67
70
|
this.nativeLayer?.setNativeProps(propsToPass);
|
|
68
71
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Platform,
|
|
4
4
|
NativeModules,
|
|
5
5
|
requireNativeComponent,
|
|
6
6
|
HostComponent,
|
|
7
7
|
type ViewProps,
|
|
8
|
+
View,
|
|
8
9
|
} from 'react-native';
|
|
9
10
|
|
|
10
11
|
import { toJSONString } from '../utils';
|
|
@@ -16,46 +17,55 @@ const Mapbox = NativeModules.MGLModule;
|
|
|
16
17
|
|
|
17
18
|
export const NATIVE_MODULE_NAME = 'RCTMGLMarkerView';
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
* MarkerView allows you to place a interactive react native marker to the map.
|
|
21
|
-
*
|
|
22
|
-
* If you have static view consider using PointAnnotation or SymbolLayer they'll offer much better performance
|
|
23
|
-
* .
|
|
24
|
-
* This is based on [MakerView plugin](https://docs.mapbox.com/android/plugins/overview/markerview/) on Android
|
|
25
|
-
* and PointAnnotation on iOS.
|
|
26
|
-
*/
|
|
27
|
-
class MarkerView extends React.PureComponent<{
|
|
20
|
+
type Props = ViewProps & {
|
|
28
21
|
/**
|
|
29
22
|
* The center point (specified as a map coordinate) of the marker.
|
|
30
|
-
* See also #anchor.
|
|
31
23
|
*/
|
|
32
24
|
coordinate: [number, number];
|
|
33
25
|
|
|
34
26
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* where (0, 0) is the top-left corner of the image, and (1, 1) is the bottom-right corner.
|
|
38
|
-
* Note this is only for custom annotations not the default pin view.
|
|
39
|
-
* Defaults to the center of the view.
|
|
27
|
+
* Any coordinate between (0, 0) and (1, 1), where (0, 0) is the top-left corner of
|
|
28
|
+
* the view, and (1, 1) is the bottom-right corner. Defaults to the center at (0.5, 0.5).
|
|
40
29
|
*/
|
|
41
30
|
anchor: {
|
|
42
|
-
/**
|
|
43
|
-
* `x` of anchor
|
|
44
|
-
*/
|
|
45
31
|
x: number;
|
|
46
|
-
/**
|
|
47
|
-
* `y` of anchor
|
|
48
|
-
*/
|
|
49
32
|
y: number;
|
|
50
33
|
};
|
|
51
34
|
|
|
52
35
|
/**
|
|
53
|
-
*
|
|
36
|
+
* @v10
|
|
37
|
+
*
|
|
38
|
+
* Whether or not nearby markers on the map should all be displayed. If false, adjacent
|
|
39
|
+
* markers will 'collapse' and only one will be shown. Defaults to false.
|
|
40
|
+
*/
|
|
41
|
+
allowOverlap: boolean;
|
|
42
|
+
|
|
43
|
+
isSelected: boolean;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* One or more valid React Native views.
|
|
54
47
|
*/
|
|
55
48
|
children: React.ReactElement;
|
|
56
|
-
}
|
|
57
|
-
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* MarkerView represents an interactive React Native marker on the map.
|
|
53
|
+
*
|
|
54
|
+
* If you have static views, consider using PointAnnotation or SymbolLayer to display
|
|
55
|
+
* an image, as they'll offer much better performance. Mapbox suggests using this
|
|
56
|
+
* component for a maximum of around 100 views displayed at one time.
|
|
57
|
+
*
|
|
58
|
+
* This is implemented with view annotations on [Android](https://docs.mapbox.com/android/maps/guides/annotations/view-annotations/)
|
|
59
|
+
* and [iOS](https://docs.mapbox.com/ios/maps/guides/annotations/view-annotations).
|
|
60
|
+
*
|
|
61
|
+
* This component has no dedicated `onPress` method. Instead, you should handle gestures
|
|
62
|
+
* with the React views passed in as `children`.
|
|
63
|
+
*/
|
|
64
|
+
class MarkerView extends React.PureComponent<Props> {
|
|
65
|
+
static defaultProps: Partial<Props> = {
|
|
58
66
|
anchor: { x: 0.5, y: 0.5 },
|
|
67
|
+
allowOverlap: false,
|
|
68
|
+
isSelected: false,
|
|
59
69
|
};
|
|
60
70
|
|
|
61
71
|
static lastId = 0;
|
|
@@ -69,69 +79,63 @@ class MarkerView extends React.PureComponent<{
|
|
|
69
79
|
return this.__idForPointAnnotation;
|
|
70
80
|
}
|
|
71
81
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return <PointAnnotation id={this._idForPointAnnotation()} {...props} />;
|
|
82
|
+
_getCoordinate(coordinate: [number, number]): string | undefined {
|
|
83
|
+
if (!coordinate) {
|
|
84
|
+
return undefined;
|
|
76
85
|
}
|
|
86
|
+
return toJSONString(makePoint(coordinate));
|
|
87
|
+
}
|
|
77
88
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
render() {
|
|
90
|
+
if (
|
|
91
|
+
this.props.anchor.x < 0 ||
|
|
92
|
+
this.props.anchor.y < 0 ||
|
|
93
|
+
this.props.anchor.x > 1 ||
|
|
94
|
+
this.props.anchor.y > 1
|
|
95
|
+
) {
|
|
96
|
+
console.warn(
|
|
97
|
+
`[MarkerView] Anchor with value (${this.props.anchor.x}, ${this.props.anchor.y}) should not be outside the range [(0, 0), (1, 1)]`,
|
|
98
|
+
);
|
|
83
99
|
}
|
|
84
100
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const actProps = {
|
|
89
|
-
anchor,
|
|
90
|
-
coordinate: _getCoordinate(props.coordinate),
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const wrapChildern =
|
|
94
|
-
RCTMGLMarkerViewWrapper === undefined
|
|
95
|
-
? (child: ReactNode | ReactNode[]) => child
|
|
96
|
-
: (child: ReactNode | ReactNode[]) => (
|
|
97
|
-
<RCTMGLMarkerViewWrapper
|
|
98
|
-
style={{
|
|
99
|
-
alignSelf: 'flex-start',
|
|
100
|
-
position: 'absolute',
|
|
101
|
-
}}
|
|
102
|
-
>
|
|
103
|
-
{child}
|
|
104
|
-
</RCTMGLMarkerViewWrapper>
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
if (RCTMGLMarkerView === undefined) {
|
|
108
|
-
throw new Error(
|
|
109
|
-
'internal error RCTMGLMarkerView should not be null on v10 or non ios',
|
|
101
|
+
if (Platform.OS === 'ios' && !Mapbox.MapboxV10) {
|
|
102
|
+
return (
|
|
103
|
+
<PointAnnotation id={this._idForPointAnnotation()} {...this.props} />
|
|
110
104
|
);
|
|
111
105
|
}
|
|
106
|
+
|
|
107
|
+
const { anchor = { x: 0.5, y: 0.5 } } = this.props;
|
|
108
|
+
|
|
112
109
|
return (
|
|
113
|
-
<RCTMGLMarkerView
|
|
114
|
-
{
|
|
110
|
+
<RCTMGLMarkerView
|
|
111
|
+
style={[
|
|
112
|
+
{
|
|
113
|
+
flex: 0,
|
|
114
|
+
alignSelf: 'flex-start',
|
|
115
|
+
},
|
|
116
|
+
this.props.style,
|
|
117
|
+
]}
|
|
118
|
+
coordinate={this._getCoordinate(this.props.coordinate)}
|
|
119
|
+
anchor={anchor}
|
|
120
|
+
allowOverlap={this.props.allowOverlap}
|
|
121
|
+
isSelected={this.props.isSelected}
|
|
122
|
+
>
|
|
123
|
+
<View style={{ flex: 0, alignSelf: 'flex-start' }}>
|
|
124
|
+
{this.props.children}
|
|
125
|
+
</View>
|
|
115
126
|
</RCTMGLMarkerView>
|
|
116
127
|
);
|
|
117
128
|
}
|
|
118
129
|
}
|
|
119
130
|
|
|
120
|
-
|
|
121
|
-
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
? requireNativeComponent(NATIVE_MODULE_NAME)
|
|
130
|
-
: undefined;
|
|
131
|
-
|
|
132
|
-
const RCTMGLMarkerViewWrapper: HostComponent<ViewProps> | undefined =
|
|
133
|
-
Mapbox.MapboxV10
|
|
134
|
-
? requireNativeComponent('RCTMGLMarkerViewWrapper')
|
|
135
|
-
: undefined;
|
|
131
|
+
type NativeProps = ViewProps & {
|
|
132
|
+
coordinate: string | undefined;
|
|
133
|
+
anchor: { x: number; y: number };
|
|
134
|
+
allowOverlap: boolean;
|
|
135
|
+
isSelected: boolean;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const RCTMGLMarkerView: HostComponent<NativeProps> =
|
|
139
|
+
requireNativeComponent(NATIVE_MODULE_NAME);
|
|
136
140
|
|
|
137
141
|
export default MarkerView;
|
|
@@ -116,7 +116,7 @@ type PointAnnotationProps = {
|
|
|
116
116
|
* they'll offer much better performance.
|
|
117
117
|
*
|
|
118
118
|
* If you need interactive views please use MarkerView,
|
|
119
|
-
* as with PointAnnotation
|
|
119
|
+
* as with PointAnnotation child views are rendered onto a bitmap
|
|
120
120
|
*/
|
|
121
121
|
class PointAnnotation extends NativeBridgeComponent(
|
|
122
122
|
React.PureComponent<PointAnnotationProps>,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { View, NativeModules, requireNativeComponent } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import { type SymbolLayerStyleProps } from '../utils/MapboxStyles';
|
|
4
|
+
import { Expression, type SymbolLayerStyleProps } from '../utils/MapboxStyles';
|
|
5
5
|
import { type StyleValue } from '../utils/StyleValue';
|
|
6
6
|
|
|
7
7
|
import AbstractLayer from './AbstractLayer';
|
|
@@ -46,7 +46,7 @@ export type Props = {
|
|
|
46
46
|
/**
|
|
47
47
|
* Filter only the features in the source layer that satisfy a condition that you define
|
|
48
48
|
*/
|
|
49
|
-
filter?:
|
|
49
|
+
filter?: Expression;
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* The minimum zoom level at which the layer gets parsed and appears.
|
|
@@ -7,9 +7,9 @@ export type NativeArg =
|
|
|
7
7
|
| NativeArg[];
|
|
8
8
|
|
|
9
9
|
export function isAndroid(): boolean;
|
|
10
|
-
export function isBoolean(
|
|
11
|
-
export function isNumber(
|
|
12
|
-
export function isString(
|
|
10
|
+
export function isBoolean(argument: unknown): argument is boolean;
|
|
11
|
+
export function isNumber(argument: unknown): argument is number;
|
|
12
|
+
export function isString(argument: unknown): argument is string;
|
|
13
13
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
14
14
|
export function isFunction(argument: unknown): argument is Function;
|
|
15
15
|
|
package/package.json
CHANGED
|
@@ -48,6 +48,7 @@ class DocJSONBuilder {
|
|
|
48
48
|
return {
|
|
49
49
|
match: fileExtensionsRegex,
|
|
50
50
|
shortName: true,
|
|
51
|
+
sort: true,
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
54
|
|
|
@@ -422,6 +423,18 @@ class DocJSONBuilder {
|
|
|
422
423
|
});
|
|
423
424
|
}
|
|
424
425
|
|
|
426
|
+
sortObject(not_sorted) {
|
|
427
|
+
return Object.keys(not_sorted)
|
|
428
|
+
.sort()
|
|
429
|
+
.reduce(
|
|
430
|
+
(acc, key) => ({
|
|
431
|
+
...acc,
|
|
432
|
+
[key]: not_sorted[key],
|
|
433
|
+
}),
|
|
434
|
+
{},
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
425
438
|
async generate() {
|
|
426
439
|
this.generateModulesTask({}, MODULES_PATH);
|
|
427
440
|
|
|
@@ -433,7 +446,10 @@ class DocJSONBuilder {
|
|
|
433
446
|
];
|
|
434
447
|
|
|
435
448
|
return Promise.all(tasks).then(() => {
|
|
436
|
-
fs.writeFileSync(
|
|
449
|
+
fs.writeFileSync(
|
|
450
|
+
OUTPUT_PATH,
|
|
451
|
+
JSON.stringify(this.sortObject(results), null, 2),
|
|
452
|
+
);
|
|
437
453
|
return true;
|
|
438
454
|
});
|
|
439
455
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
package com.mapbox.rctmgl.components.annotation
|
|
2
|
-
import android.content.Context
|
|
3
|
-
import android.util.Log
|
|
4
|
-
import android.view.View
|
|
5
|
-
import com.facebook.react.views.view.ReactViewGroup
|
|
6
|
-
|
|
7
|
-
class RCTMGLMarkerViewWrapper(context: Context?, private val mManager: RCTMGLMarkerViewWrapperManager) : ReactViewGroup(context) {
|
|
8
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
package com.mapbox.rctmgl.components.annotation
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
-
import com.facebook.react.uimanager.ThemedReactContext
|
|
5
|
-
import com.facebook.react.uimanager.ViewGroupManager
|
|
6
|
-
|
|
7
|
-
class RCTMGLMarkerViewWrapperManager(reactApplicationContext: ReactApplicationContext?) :
|
|
8
|
-
ViewGroupManager<RCTMGLMarkerViewWrapper>() {
|
|
9
|
-
|
|
10
|
-
override fun getName(): String {
|
|
11
|
-
return REACT_CLASS
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
override fun createViewInstance(reactContext: ThemedReactContext): RCTMGLMarkerViewWrapper {
|
|
15
|
-
return RCTMGLMarkerViewWrapper(reactContext, this)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
companion object {
|
|
19
|
-
const val REACT_CLASS = "RCTMGLMarkerViewWrapper"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import MapboxMaps
|
|
2
|
-
|
|
3
|
-
class RCTMGLMarkerViewWrapper : UIView {
|
|
4
|
-
var anchorX : CGFloat? = nil
|
|
5
|
-
var anchorY : CGFloat? = nil
|
|
6
|
-
|
|
7
|
-
override func reactSetFrame(_ frame: CGRect) {
|
|
8
|
-
let oldFrame = self.frame
|
|
9
|
-
let newSize = frame.size
|
|
10
|
-
let oldSize = oldFrame.size
|
|
11
|
-
|
|
12
|
-
if let anchorX = anchorX, let anchorY = anchorY {
|
|
13
|
-
let oldCenter = CGPoint(x: oldFrame.origin.x + oldSize.width * anchorX,
|
|
14
|
-
y: oldFrame.origin.y + oldSize.height * anchorY)
|
|
15
|
-
|
|
16
|
-
let newFrame = CGRect(origin: CGPoint(x: oldCenter.x-anchorX * newSize.width,y: oldCenter.y-anchorY * newSize.height), size: newSize)
|
|
17
|
-
self.frame = newFrame
|
|
18
|
-
} else {
|
|
19
|
-
super.reactSetFrame(frame)
|
|
20
|
-
let newFrame = CGRect(origin: oldFrame.origin, size: newSize)
|
|
21
|
-
self.frame = newFrame
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import MapboxMaps
|
|
3
|
-
|
|
4
|
-
@objc(RCTMGLMarkerViewWrapperManager)
|
|
5
|
-
class RCTMGLMarkerViewWrapperManager : RCTViewManager {
|
|
6
|
-
@objc
|
|
7
|
-
override static func requiresMainQueueSetup() -> Bool {
|
|
8
|
-
return true
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
override func view() -> UIView! {
|
|
12
|
-
return RCTMGLMarkerViewWrapper()
|
|
13
|
-
}
|
|
14
|
-
}
|