From d107640682952e61bec2618fa011c7256dde9e35 Mon Sep 17 00:00:00 2001 From: fl0h0 Date: Sun, 7 Dec 2025 18:14:37 +0100 Subject: [PATCH 1/2] feat: Add line border properties to LineLayer - Introduced `lineBorderWidth`, `lineBorderWidthTransition`, `lineBorderColor`, and `lineBorderColorTransition` properties to enhance line styling capabilities. - Updated Android and iOS implementations to support new properties. - Enhanced documentation to include descriptions and usage examples for the new line border attributes. This update allows for more customizable line styles in the mapping interface. --- .../components/styles/RNMBXStyleFactory.kt | 60 ++++++++++++++ docs/LineLayer.md | 83 +++++++++++++++++++ docs/docs.json | 49 +++++++++++ ios/RNMBX/RNMBXStyle.swift | 36 ++++++++ src/utils/MapboxStyles.ts | 18 ++++ src/utils/styleMap.ts | 4 + style-spec/v8.json | 2 - 7 files changed, 250 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleFactory.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleFactory.kt index a8456b688..d8856869a 100644 --- a/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleFactory.kt +++ b/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleFactory.kt @@ -175,6 +175,14 @@ object RNMBXStyleFactory { setLineGradient(layer, styleValue) "lineTrimOffset" -> setLineTrimOffset(layer, styleValue) + "lineBorderWidth" -> + setLineBorderWidth(layer, styleValue) + "lineBorderWidthTransition" -> + setLineBorderWidthTransition(layer, styleValue) + "lineBorderColor" -> + setLineBorderColor(layer, styleValue) + "lineBorderColorTransition" -> + setLineBorderColorTransition(layer, styleValue) "lineZOffset" -> setLineZOffset(layer, styleValue) "lineElevationReference" -> @@ -1619,6 +1627,58 @@ object RNMBXStyleFactory { } } + fun setLineBorderWidth(layer: LineLayer, styleValue: RNMBXStyleValue ) { + if (styleValue.isExpression()) { + val expression = styleValue.getExpression() + if (expression != null) { + layer.lineBorderWidth(expression) + } else { + Logger.e("RNMBXLine", "Expression for lineBorderWidth is null") + } + } else { + val value = styleValue.getDouble(VALUE_KEY) + if (value != null) { + layer.lineBorderWidth(value) + } else { + Logger.e("RNMBXLine", "value for lineBorderWidth is null") + } + } + } + + + fun setLineBorderWidthTransition(layer: LineLayer, styleValue: RNMBXStyleValue) { + val transition = styleValue.transition + if (transition != null) { + layer.lineBorderWidthTransition(transition); + } + } + + fun setLineBorderColor(layer: LineLayer, styleValue: RNMBXStyleValue ) { + if (styleValue.isExpression()) { + val expression = styleValue.getExpression() + if (expression != null) { + layer.lineBorderColor(expression) + } else { + Logger.e("RNMBXLine", "Expression for lineBorderColor is null") + } + } else { + val value = styleValue.getInt(VALUE_KEY) + if (value != null) { + layer.lineBorderColor(value) + } else { + Logger.e("RNMBXLine", "value for lineBorderColor is null") + } + } + } + + + fun setLineBorderColorTransition(layer: LineLayer, styleValue: RNMBXStyleValue) { + val transition = styleValue.transition + if (transition != null) { + layer.lineBorderColorTransition(transition); + } + } + fun setLineZOffset(layer: LineLayer, styleValue: RNMBXStyleValue ) { if (styleValue.isExpression()) { val expression = styleValue.getExpression() diff --git a/docs/LineLayer.md b/docs/LineLayer.md index 690aa8ef9..579bf4b0c 100644 --- a/docs/LineLayer.md +++ b/docs/LineLayer.md @@ -161,6 +161,8 @@ Customizable style attributes * lineTrimFadeRange
* lineTrimColor
* lineEmissiveStrength
+* lineBorderWidth
+* lineBorderColor
* lineOcclusionOpacity
___ @@ -949,6 +951,87 @@ The transition affecting any changes to this layer’s lineEmissiveStrength prop `{duration: 300, delay: 0}` +___ + +### lineBorderWidth +Name: `lineBorderWidth` + +Mapbox spec: [line-border-width](https://docs.mapbox.com/style-spec/reference/layers/#paint-line-line-border-width) + +#### Description +The width of the line border. A value of zero means no border. + +#### Type +`number` +#### Default Value +`0` + +#### Minimum +`0` + + +#### Expression + +Parameters: `zoom, feature, feature-state` +___ + +### lineBorderWidthTransition +Name: `lineBorderWidthTransition` + +#### Description + +The transition affecting any changes to this layer’s lineBorderWidth property. + +#### Type + +`{ duration, delay }` + +#### Units +`milliseconds` + +#### Default Value +`{duration: 300, delay: 0}` + + +___ + +### lineBorderColor +Name: `lineBorderColor` + +Mapbox spec: [line-border-color](https://docs.mapbox.com/style-spec/reference/layers/#paint-line-line-border-color) + +#### Description +The color of the line border. If lineBorderWidth is greater than zero and the alpha value of this color is 0 (default), the color for the border will be selected automatically based on the line color. + +#### Type +`color` +#### Default Value +`rgba(0, 0, 0, 0)` + + +#### Expression + +Parameters: `zoom, feature, feature-state` +___ + +### lineBorderColorTransition +Name: `lineBorderColorTransition` + +#### Description + +The transition affecting any changes to this layer’s lineBorderColor property. + +#### Type + +`{ duration, delay }` + +#### Units +`milliseconds` + +#### Default Value +`{duration: 300, delay: 0}` + + ___ ### lineOcclusionOpacity diff --git a/docs/docs.json b/docs/docs.json index 73a056760..ed50887da 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -4105,6 +4105,55 @@ "namespace": "paint" } }, + { + "name": "lineBorderWidth", + "type": "number", + "values": [], + "minimum": 0, + "default": 0, + "description": "The width of the line border. A value of zero means no border.", + "requires": [], + "disabledBy": [], + "allowedFunctionTypes": [], + "expression": { + "interpolated": true, + "parameters": [ + "zoom", + "feature", + "feature-state" + ] + }, + "transition": true, + "mbx": { + "fullName": "paint-line-line-border-width", + "name": "line-border-width", + "namespace": "paint" + } + }, + { + "name": "lineBorderColor", + "type": "color", + "values": [], + "default": "rgba(0, 0, 0, 0)", + "description": "The color of the line border. If lineBorderWidth is greater than zero and the alpha value of this color is 0 (default), the color for the border will be selected automatically based on the line color.", + "requires": [], + "disabledBy": [], + "allowedFunctionTypes": [], + "expression": { + "interpolated": true, + "parameters": [ + "zoom", + "feature", + "feature-state" + ] + }, + "transition": true, + "mbx": { + "fullName": "paint-line-line-border-color", + "name": "line-border-color", + "namespace": "paint" + } + }, { "name": "lineOcclusionOpacity", "type": "number", diff --git a/ios/RNMBX/RNMBXStyle.swift b/ios/RNMBX/RNMBXStyle.swift index be9eaddc3..7fe4582e6 100644 --- a/ios/RNMBX/RNMBXStyle.swift +++ b/ios/RNMBX/RNMBXStyle.swift @@ -154,6 +154,14 @@ func lineLayer(layer: inout LineLayer, reactStyle:Dictionary, oldRe self.setLineGradient(&layer, styleValue:styleValue); } else if (prop == "lineTrimOffset") { self.setLineTrimOffset(&layer, styleValue:styleValue); + } else if (prop == "lineBorderWidth") { + self.setLineBorderWidth(&layer, styleValue:styleValue); + } else if (prop == "lineBorderWidthTransition") { + self.setLineBorderWidthTransition(&layer, styleValue:styleValue); + } else if (prop == "lineBorderColor") { + self.setLineBorderColor(&layer, styleValue:styleValue); + } else if (prop == "lineBorderColorTransition") { + self.setLineBorderColorTransition(&layer, styleValue:styleValue); } else if (prop == "lineZOffset") { self.setLineZOffset(&layer, styleValue:styleValue); } else if (prop == "lineElevationReference") { @@ -1379,6 +1387,34 @@ func setLineTrimOffset(_ layer: inout LineLayer, styleValue: RNMBXStyleValue) } +func setLineBorderWidth(_ layer: inout LineLayer, styleValue: RNMBXStyleValue) +{ + + + layer.lineBorderWidth = styleValue.mglStyleValueNumber(); + + +} + +func setLineBorderWidthTransition(_ layer: inout LineLayer, styleValue: RNMBXStyleValue) +{ + layer.lineBorderWidthTransition = styleValue.getTransition(); +} + +func setLineBorderColor(_ layer: inout LineLayer, styleValue: RNMBXStyleValue) +{ + + + layer.lineBorderColor = styleValue.mglStyleValueColor(); + + +} + +func setLineBorderColorTransition(_ layer: inout LineLayer, styleValue: RNMBXStyleValue) +{ + layer.lineBorderColorTransition = styleValue.getTransition(); +} + func setLineZOffset(_ layer: inout LineLayer, styleValue: RNMBXStyleValue) { #if RNMBX_11 diff --git a/src/utils/MapboxStyles.ts b/src/utils/MapboxStyles.ts index 3bba720a7..a0177e248 100644 --- a/src/utils/MapboxStyles.ts +++ b/src/utils/MapboxStyles.ts @@ -720,6 +720,24 @@ export interface LineLayerStyleProps { * The line part between [trimStart, trimEnd] will be painted using `lineTrimColor,` which is transparent by default to produce a route vanishing effect. The line trimOff offset is based on the whole line range [0.0, 1.0]. */ lineTrimOffset?: number[]; + /** + * The width of the line border. A value of zero means no border. + */ + lineBorderWidth?: Value; + + /** + * The transition affecting any changes to this layer’s lineBorderWidth property. + */ + lineBorderWidthTransition?: Transition; + /** + * The color of the line border. If lineBorderWidth is greater than zero and the alpha value of this color is 0 (default), the color for the border will be selected automatically based on the line color. + */ + lineBorderColor?: Value; + + /** + * The transition affecting any changes to this layer’s lineBorderColor property. + */ + lineBorderColorTransition?: Transition; /** * Vertical offset from ground, in meters. Defaults to 0. This is an experimental property with some known issues: * Not supported for globe projection at the moment diff --git a/src/utils/styleMap.ts b/src/utils/styleMap.ts index 24f04f051..a5233ffae 100644 --- a/src/utils/styleMap.ts +++ b/src/utils/styleMap.ts @@ -66,6 +66,10 @@ const styleMap = { linePattern: StyleTypes.Image, lineGradient: StyleTypes.Color, lineTrimOffset: StyleTypes.Constant, + lineBorderWidth: StyleTypes.Constant, + lineBorderWidthTransition: StyleTypes.Transition, + lineBorderColor: StyleTypes.Color, + lineBorderColorTransition: StyleTypes.Transition, lineZOffset: StyleTypes.Constant, lineElevationReference: StyleTypes.Enum, lineCrossSlope: StyleTypes.Constant, diff --git a/style-spec/v8.json b/style-spec/v8.json index 59bb995ec..a80c3d934 100644 --- a/style-spec/v8.json +++ b/style-spec/v8.json @@ -8723,7 +8723,6 @@ }, "line-border-width": { "type": "number", - "private": true, "doc": "The width of the line border. A value of zero means no border.", "default": 0.0, "minimum": 0.0, @@ -8752,7 +8751,6 @@ }, "line-border-color": { "type": "color", - "private": true, "doc": "The color of the line border. If line-border-width is greater than zero and the alpha value of this color is 0 (default), the color for the border will be selected automatically based on the line color.", "default": "rgba(0, 0, 0, 0)", "use-theme": true, From 2c5bef175846f3deb33da9ed23df750b140e9695 Mon Sep 17 00:00:00 2001 From: fl0h0 Date: Sun, 7 Dec 2025 23:48:28 +0100 Subject: [PATCH 2/2] Move private handling to generate script --- scripts/autogenHelpers/generateCodeWithEjs.mjs | 8 +++++++- style-spec/v8.json | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/autogenHelpers/generateCodeWithEjs.mjs b/scripts/autogenHelpers/generateCodeWithEjs.mjs index 2238b88b0..60aa9773f 100644 --- a/scripts/autogenHelpers/generateCodeWithEjs.mjs +++ b/scripts/autogenHelpers/generateCodeWithEjs.mjs @@ -331,6 +331,12 @@ const UnsupportedProperties = [ 'raster-particle-elevation', // should be supported in v11 11.7.0 but it's not yet implemented in SDK ]; +// Properties marked as private in the style-spec but supported by native SDKs +const AllowedPrivateProperties = [ + 'line-border-width', + 'line-border-color', +]; + /** * * @param {string[]|undefined} only @@ -340,7 +346,7 @@ function isAttrSupported(name, attr, only) { return false; } const support = getAttributeSupport(attr['sdk-support']); - if (attr.private === true) { + if (attr.private === true && !AllowedPrivateProperties.includes(name)) { return false; } if (only != null) { diff --git a/style-spec/v8.json b/style-spec/v8.json index a80c3d934..59bb995ec 100644 --- a/style-spec/v8.json +++ b/style-spec/v8.json @@ -8723,6 +8723,7 @@ }, "line-border-width": { "type": "number", + "private": true, "doc": "The width of the line border. A value of zero means no border.", "default": 0.0, "minimum": 0.0, @@ -8751,6 +8752,7 @@ }, "line-border-color": { "type": "color", + "private": true, "doc": "The color of the line border. If line-border-width is greater than zero and the alpha value of this color is 0 (default), the color for the border will be selected automatically based on the line color.", "default": "rgba(0, 0, 0, 0)", "use-theme": true,