@triniwiz/nativescript-masonkit 1.0.0-beta.86 → 1.0.0-beta.88

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.
Files changed (105) hide show
  1. package/DOCS.md +16 -4
  2. package/angular/README.md +204 -0
  3. package/angular/fesm2022/triniwiz-nativescript-masonkit-angular.mjs +496 -0
  4. package/angular/fesm2022/triniwiz-nativescript-masonkit-angular.mjs.map +1 -0
  5. package/angular/package.json +19 -0
  6. package/angular/types/triniwiz-nativescript-masonkit-angular.d.ts +181 -0
  7. package/button/index.android.d.ts +2 -1
  8. package/button/index.ios.d.ts +2 -1
  9. package/button/index.windows.d.ts +2 -1
  10. package/common.d.ts +102 -1
  11. package/common.js +116 -6
  12. package/common.js.map +1 -1
  13. package/img/index.android.d.ts +2 -1
  14. package/img/index.ios.d.ts +2 -1
  15. package/img/index.windows.d.ts +2 -1
  16. package/index.d.ts +21 -10
  17. package/input/index.android.d.ts +5 -1
  18. package/input/index.ios.d.ts +7 -1
  19. package/input/index.windows.d.ts +6 -1
  20. package/package.json +3 -1
  21. package/platforms/android/masonkit-release.aar +0 -0
  22. package/platforms/ios/Mason.xcframework/Info.plist +2 -36
  23. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Headers/Mason-Swift.h +26 -0
  24. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Headers/mason_native.h +27 -2
  25. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Mason +0 -0
  26. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
  27. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.abi.json +2630 -979
  28. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.private.swiftinterface +37 -1
  29. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  30. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.swiftinterface +37 -1
  31. package/platforms/ios/Mason.xcframework/ios-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  32. package/platforms/ios/Mason.xcframework/ios-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8457 -8378
  33. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Headers/Mason-Swift.h +52 -0
  34. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Headers/mason_native.h +27 -2
  35. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Mason +0 -0
  36. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo +0 -0
  37. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo +0 -0
  38. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.abi.json +2630 -979
  39. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +37 -1
  40. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  41. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.swiftinterface +37 -1
  42. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.abi.json +2630 -979
  43. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +37 -1
  44. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  45. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +37 -1
  46. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/_CodeSignature/CodeResources +28 -28
  47. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  48. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8452 -8373
  49. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/x86_64/Mason.yml +8090 -8017
  50. package/platforms/windows/arm64/NativeScript.Mason.dll +0 -0
  51. package/platforms/windows/arm64/NativeScript.Mason.winmd +0 -0
  52. package/platforms/windows/x64/NativeScript.Mason.dll +0 -0
  53. package/platforms/windows/x64/NativeScript.Mason.winmd +0 -0
  54. package/properties.d.ts +4 -0
  55. package/properties.js +58 -15
  56. package/properties.js.map +1 -1
  57. package/style.d.ts +39 -37
  58. package/style.js +429 -110
  59. package/style.js.map +1 -1
  60. package/text/index.android.d.ts +3 -1
  61. package/text/index.ios.d.ts +3 -1
  62. package/text/index.windows.d.ts +2 -1
  63. package/textarea/index.android.d.ts +6 -2
  64. package/textarea/index.ios.d.ts +6 -2
  65. package/textarea/index.windows.d.ts +6 -2
  66. package/utils/index.android.d.ts +15 -6
  67. package/utils/index.android.js +83 -2
  68. package/utils/index.android.js.map +1 -1
  69. package/utils/index.ios.d.ts +15 -6
  70. package/utils/index.ios.js +83 -2
  71. package/utils/index.ios.js.map +1 -1
  72. package/utils/index.windows.d.ts +11 -2
  73. package/utils/index.windows.js +9 -0
  74. package/utils/index.windows.js.map +1 -1
  75. package/view/index.ios.js +14 -1
  76. package/view/index.ios.js.map +1 -1
  77. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Headers/Mason-Swift.h +0 -1982
  78. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Headers/Mason.h +0 -25
  79. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Headers/mason_native.h +0 -499
  80. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Info.plist +0 -0
  81. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Mason +0 -0
  82. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-xros.swiftsourceinfo +0 -0
  83. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.abi.json +0 -98937
  84. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.private.swiftinterface +0 -3475
  85. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.swiftdoc +0 -0
  86. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.swiftinterface +0 -3475
  87. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/module.modulemap +0 -10
  88. package/platforms/ios/Mason.xcframework/xros-arm64/dSYMs/Mason.framework.dSYM/Contents/Info.plist +0 -20
  89. package/platforms/ios/Mason.xcframework/xros-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  90. package/platforms/ios/Mason.xcframework/xros-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +0 -2134
  91. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Headers/Mason-Swift.h +0 -1982
  92. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Headers/Mason.h +0 -25
  93. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Headers/mason_native.h +0 -499
  94. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Info.plist +0 -0
  95. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Mason +0 -0
  96. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-xros-simulator.swiftsourceinfo +0 -0
  97. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.abi.json +0 -98937
  98. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.private.swiftinterface +0 -3475
  99. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.swiftdoc +0 -0
  100. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.swiftinterface +0 -3475
  101. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/module.modulemap +0 -10
  102. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/_CodeSignature/CodeResources +0 -212
  103. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/dSYMs/Mason.framework.dSYM/Contents/Info.plist +0 -20
  104. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  105. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +0 -2134
package/style.js CHANGED
@@ -256,7 +256,7 @@ function windowsSetGrid(nativeView, field, value) {
256
256
  }
257
257
  catch (_) { }
258
258
  }
259
- function parseLengthPercentageAuto(type, value) {
259
+ function parseDimension(type, value) {
260
260
  switch (type) {
261
261
  case 0:
262
262
  return 'auto';
@@ -264,8 +264,79 @@ function parseLengthPercentageAuto(type, value) {
264
264
  return { value, unit: 'px' };
265
265
  case 2:
266
266
  return { value, unit: '%' };
267
+ case 3:
268
+ return 'min-content';
269
+ case 4:
270
+ return 'max-content';
271
+ case 5:
272
+ return 'fit-content';
273
+ case 6:
274
+ return `fit-content(${value}px)`;
275
+ case 7:
276
+ return `fit-content(${value}%)`;
277
+ case 8:
278
+ return 'stretch';
279
+ case 9:
280
+ return 'content';
267
281
  }
268
282
  }
283
+ function parseLengthPercentageAuto(type, value) {
284
+ return parseDimension(type, value);
285
+ }
286
+ function dimensionFromString(value) {
287
+ const t = value.trim();
288
+ if (t === '' || t === 'auto') {
289
+ return { type: 0, value: 0 };
290
+ }
291
+ switch (t) {
292
+ case 'min-content':
293
+ return { type: 3, value: 0 };
294
+ case 'max-content':
295
+ return { type: 4, value: 0 };
296
+ case 'fit-content':
297
+ return { type: 5, value: 0 };
298
+ case 'stretch':
299
+ return { type: 8, value: 0 };
300
+ case 'content':
301
+ return { type: 9, value: 0 };
302
+ }
303
+ if (t.startsWith('fit-content(') && t.endsWith(')')) {
304
+ const limit = t.slice('fit-content('.length, -1).trim();
305
+ if (limit.endsWith('%')) {
306
+ // taffy percentages are a [0.0, 1.0] fraction, not [0.0, 100.0]
307
+ return { type: 7, value: (parseFloat(limit) || 0) / 100 };
308
+ }
309
+ const n = parseFloat(limit) || 0;
310
+ return { type: 6, value: limit.endsWith('px') ? n : layout.toDevicePixels(n) };
311
+ }
312
+ if (t.endsWith('%')) {
313
+ // percentages are stored as a [0.0, 1.0] fraction, not percentage points
314
+ return { type: 2, value: (parseFloat(t) || 0) / 100 };
315
+ }
316
+ const n = parseFloat(t) || 0;
317
+ return { type: 1, value: t.endsWith('px') ? n : layout.toDevicePixels(n) };
318
+ }
319
+ // Shared parser for LengthPercentageAuto props (min/max width/height, margin, inset)
320
+ function lengthPercentageAutoFromString(value) {
321
+ const t = value.trim();
322
+ if (t === '' || t === 'auto') {
323
+ return { type: 0, value: 0 };
324
+ }
325
+ if (t.endsWith('%')) {
326
+ return { type: 2, value: (parseFloat(t) || 0) / 100 };
327
+ }
328
+ const n = parseFloat(t) || 0;
329
+ return { type: 1, value: t.endsWith('px') ? n : layout.toDevicePixels(n) };
330
+ }
331
+ // Same as lengthPercentageAutoFromString but for padding (no "auto", type 0/1 swapped)
332
+ function lengthPercentageFromString(value) {
333
+ const t = value.trim();
334
+ if (t.endsWith('%')) {
335
+ return { type: 1, value: (parseFloat(t) || 0) / 100 };
336
+ }
337
+ const n = parseFloat(t) || 0;
338
+ return { type: 0, value: t.endsWith('px') ? n : layout.toDevicePixels(n) };
339
+ }
269
340
  function parseLengthPercentage(type, value) {
270
341
  switch (type) {
271
342
  case 0:
@@ -403,6 +474,25 @@ const splitBigIntToInt64Parts = (value) => {
403
474
  }
404
475
  return [lowSigned.toString(), HIGH.toString()];
405
476
  };
477
+ // Android-only fast path for syncStyle(): splits the 128-bit dirty mask into
478
+ // four signed 32-bit words instead of two 64-bit decimal strings. Plain JS
479
+ // `number` <-> Java `int` marshalling is a completely standard, unambiguous
480
+ // {N} bridge path; encoding as decimal strings instead forced the receiving
481
+ // side (Element.syncStyle(String,String)) through Long.parseUnsignedLong with
482
+ // a BigInteger fallback on every single style write. Recombined bit-exactly
483
+ // on the Kotlin side via (high32 << 32) | (low32 & 0xffffffff) - see
484
+ // Element.syncStyleParts.
485
+ const splitBigIntToInt32Parts = (value) => {
486
+ const MASK64 = (1n << 64n) - 1n;
487
+ const MASK32 = 0xffffffffn;
488
+ const LOW = value & MASK64;
489
+ const HIGH = (value >> 64n) & MASK64;
490
+ const lowLow32 = Number(BigInt.asIntN(32, LOW & MASK32));
491
+ const lowHigh32 = Number(BigInt.asIntN(32, (LOW >> 32n) & MASK32));
492
+ const highLow32 = Number(BigInt.asIntN(32, HIGH & MASK32));
493
+ const highHigh32 = Number(BigInt.asIntN(32, (HIGH >> 32n) & MASK32));
494
+ return [lowLow32, lowHigh32, highLow32, highHigh32];
495
+ };
406
496
  const getInt16 = (view, offset) => {
407
497
  return view.getInt16(offset, true);
408
498
  };
@@ -575,6 +665,85 @@ function parseBorderRadiusShorthand(value) {
575
665
  return { tl: vals[0], tr: vals[1], br: vals[2], bl: vals[3] };
576
666
  }
577
667
  }
668
+ // Split on top-level whitespace, keeping parenthesised groups (e.g. `rgba(0,0,0,.5)`) intact.
669
+ function splitTopLevelSpaces(value) {
670
+ const out = [];
671
+ let depth = 0;
672
+ let cur = '';
673
+ for (let i = 0; i < value.length; i++) {
674
+ const ch = value[i];
675
+ if (ch === '(')
676
+ depth++;
677
+ else if (ch === ')')
678
+ depth = Math.max(0, depth - 1);
679
+ if (depth === 0 && /\s/.test(ch)) {
680
+ if (cur.length) {
681
+ out.push(cur);
682
+ cur = '';
683
+ }
684
+ }
685
+ else {
686
+ cur += ch;
687
+ }
688
+ }
689
+ if (cur.length)
690
+ out.push(cur);
691
+ return out;
692
+ }
693
+ // Parse a `border` / `border-<side>` shorthand (`<width> <style> <color>`, any order) into px width,
694
+ // border-style enum and argb color; each is null when absent.
695
+ function parseBorderShorthand(value) {
696
+ let width = null;
697
+ let style = null;
698
+ let color = null;
699
+ for (const tok of splitTopLevelSpaces(String(value ?? '').trim())) {
700
+ const s = borderStyleToEnum(tok);
701
+ if (s !== -1) {
702
+ style = s;
703
+ continue;
704
+ }
705
+ const lower = tok.toLowerCase();
706
+ if (lower === 'thin') {
707
+ width = 1;
708
+ continue;
709
+ }
710
+ if (lower === 'medium') {
711
+ width = 3;
712
+ continue;
713
+ }
714
+ if (lower === 'thick') {
715
+ width = 5;
716
+ continue;
717
+ }
718
+ if (/^-?\d*\.?\d+(px|dip|dp|rem|em|pt)?$/i.test(tok)) {
719
+ const n = parseFloat(tok);
720
+ if (!isNaN(n)) {
721
+ width = n;
722
+ continue;
723
+ }
724
+ }
725
+ const c = normalizeColorValue(tok);
726
+ if (c != null)
727
+ color = c;
728
+ }
729
+ return { width, style, color };
730
+ }
731
+ // Parse a 1-4 token `border-color` shorthand into per-side argb (CSS order top/right/bottom/left).
732
+ function parseSidesColorShorthand(value) {
733
+ const cols = splitTopLevelSpaces(String(value ?? '').trim()).map((t) => normalizeColorValue(t));
734
+ switch (cols.length) {
735
+ case 0:
736
+ return { t: null, r: null, b: null, l: null };
737
+ case 1:
738
+ return { t: cols[0], r: cols[0], b: cols[0], l: cols[0] };
739
+ case 2:
740
+ return { t: cols[0], r: cols[1], b: cols[0], l: cols[1] };
741
+ case 3:
742
+ return { t: cols[0], r: cols[1], b: cols[2], l: cols[1] };
743
+ default:
744
+ return { t: cols[0], r: cols[1], b: cols[2], l: cols[3] };
745
+ }
746
+ }
578
747
  const i8Buffer = new Int8Array(4);
579
748
  const f32Buffer = new Uint8Array(Float32Array.BYTES_PER_ELEMENT * 4);
580
749
  const f32View = new Float32Array(f32Buffer.buffer);
@@ -611,19 +780,20 @@ function borderStyleToEnum(value) {
611
780
  function borderStyleFromEnum(value) {
612
781
  return BORDER_STYLE_VALUES[value] ?? 'none';
613
782
  }
783
+ // hoisted so it's not rebuilt on every parseObjectPosition call
784
+ const OBJECT_POSITION_KEYWORDS = {
785
+ left: { type: 1, val: 0 },
786
+ center: { type: 1, val: 50 },
787
+ right: { type: 1, val: 100 },
788
+ top: { type: 1, val: 0 },
789
+ bottom: { type: 1, val: 100 },
790
+ };
614
791
  function parseObjectPosition(value) {
615
- const keywords = {
616
- left: { type: 1, val: 0 },
617
- center: { type: 1, val: 50 },
618
- right: { type: 1, val: 100 },
619
- top: { type: 1, val: 0 },
620
- bottom: { type: 1, val: 100 },
621
- };
622
792
  const parts = value.trim().split(/\s+/);
623
793
  if (parts.length === 0)
624
794
  return null;
625
795
  function parseComponent(s) {
626
- const kw = keywords[s];
796
+ const kw = OBJECT_POSITION_KEYWORDS[s];
627
797
  if (kw)
628
798
  return kw;
629
799
  if (s.endsWith('%'))
@@ -666,11 +836,12 @@ function fontStretchToValue(value) {
666
836
  }
667
837
  return -1;
668
838
  }
839
+ // built once instead of scanning FONT_STRETCH_KEYWORDS on every getter read
840
+ const FONT_STRETCH_REVERSE = new Map(Object.entries(FONT_STRETCH_KEYWORDS).map(([kw, val]) => [val, kw]));
669
841
  function fontStretchFromValue(v) {
670
- for (const [kw, val] of Object.entries(FONT_STRETCH_KEYWORDS)) {
671
- if (val === v)
672
- return kw;
673
- }
842
+ const kw = FONT_STRETCH_REVERSE.get(v);
843
+ if (kw !== undefined)
844
+ return kw;
674
845
  return `${v / 100}%`;
675
846
  }
676
847
  export class Style {
@@ -914,25 +1085,79 @@ export class Style {
914
1085
  setUint8(this.style_view, StyleKeys.BORDER_RADIUS_BOTTOM_LEFT_X_TYPE, 0);
915
1086
  setUint8(this.style_view, StyleKeys.BORDER_RADIUS_BOTTOM_LEFT_Y_TYPE, 0);
916
1087
  this.commitState(StateKeys.BORDER_RADIUS);
1088
+ return;
1089
+ }
1090
+ if (name === 'border' || name === 'border-top' || name === 'border-right' || name === 'border-bottom' || name === 'border-left') {
1091
+ const p = parseBorderShorthand(value);
1092
+ let style = p.style;
1093
+ if (style == null && (p.width != null || p.color != null))
1094
+ style = 4; // solid
1095
+ const sides = name === 'border' ? ['left', 'right', 'top', 'bottom'] : name === 'border-left' ? ['left'] : name === 'border-right' ? ['right'] : name === 'border-top' ? ['top'] : ['bottom'];
1096
+ for (const s of sides)
1097
+ this.writeBorderSide(s, p.width, style, p.color);
1098
+ this.commitState(StateKeys.BORDER);
1099
+ this.commitState(StateKeys.BORDER_STYLE);
1100
+ this.commitState(StateKeys.BORDER_COLOR);
1101
+ return;
1102
+ }
1103
+ if (name === 'border-color') {
1104
+ const c = parseSidesColorShorthand(value);
1105
+ this.writeBorderSide('top', null, null, c.t);
1106
+ this.writeBorderSide('right', null, null, c.r);
1107
+ this.writeBorderSide('bottom', null, null, c.b);
1108
+ this.writeBorderSide('left', null, null, c.l);
1109
+ this.commitState(StateKeys.BORDER_COLOR);
1110
+ return;
917
1111
  }
918
1112
  }
1113
+ // Write one side's border width/style/color into the style buffer; null components are skipped.
1114
+ writeBorderSide(side, width, style, color) {
1115
+ if (!this.style_view)
1116
+ return;
1117
+ const W = side === 'left' ? StyleKeys.BORDER_LEFT_VALUE : side === 'right' ? StyleKeys.BORDER_RIGHT_VALUE : side === 'top' ? StyleKeys.BORDER_TOP_VALUE : StyleKeys.BORDER_BOTTOM_VALUE;
1118
+ const T = side === 'left' ? StyleKeys.BORDER_LEFT_TYPE : side === 'right' ? StyleKeys.BORDER_RIGHT_TYPE : side === 'top' ? StyleKeys.BORDER_TOP_TYPE : StyleKeys.BORDER_BOTTOM_TYPE;
1119
+ const S = side === 'left' ? StyleKeys.BORDER_LEFT_STYLE : side === 'right' ? StyleKeys.BORDER_RIGHT_STYLE : side === 'top' ? StyleKeys.BORDER_TOP_STYLE : StyleKeys.BORDER_BOTTOM_STYLE;
1120
+ const C = side === 'left' ? StyleKeys.BORDER_LEFT_COLOR : side === 'right' ? StyleKeys.BORDER_RIGHT_COLOR : side === 'top' ? StyleKeys.BORDER_TOP_COLOR : StyleKeys.BORDER_BOTTOM_COLOR;
1121
+ this.prepareMut();
1122
+ if (width != null) {
1123
+ setInt8(this.style_view, T, 0);
1124
+ setFloat32(this.style_view, W, width);
1125
+ }
1126
+ if (style != null)
1127
+ setInt8(this.style_view, S, style);
1128
+ if (color != null)
1129
+ setUint32(this.style_view, C, color >>> 0);
1130
+ }
1131
+ setBorderColor(value) {
1132
+ if (!__WINDOWS__ || !this.style_view)
1133
+ return;
1134
+ const c = parseSidesColorShorthand(String(value ?? ''));
1135
+ this.writeBorderSide('top', null, null, c.t);
1136
+ this.writeBorderSide('right', null, null, c.r);
1137
+ this.writeBorderSide('bottom', null, null, c.b);
1138
+ this.writeBorderSide('left', null, null, c.l);
1139
+ this.commitState(StateKeys.BORDER_COLOR);
1140
+ }
919
1141
  resetState() {
920
1142
  this.isDirty = -1n;
921
1143
  }
922
1144
  syncStyle() {
923
- const [low, high] = splitBigIntToInt64Parts(this.isDirty);
924
1145
  if (__ANDROID__) {
1146
+ const [lowLow, lowHigh, highLow, highHigh] = splitBigIntToInt32Parts(this.isDirty);
925
1147
  //@ts-ignore
926
1148
  const view = this.view?.android ?? this.view._view;
927
- view.syncStyle(low, high);
1149
+ // @ts-ignore - syncStyleParts is a newer native method; typings regenerate from the AAR separately.
1150
+ view.syncStyleParts(lowLow, lowHigh, highLow, highHigh);
928
1151
  }
929
1152
  else if (__APPLE__) {
1153
+ const [low, high] = splitBigIntToInt64Parts(this.isDirty);
930
1154
  //@ts-ignore
931
1155
  const view = this.view?.ios ?? this.view._view;
932
1156
  // @ts-ignore
933
1157
  view.mason_syncStyle(low, high);
934
1158
  }
935
1159
  else if (__WINDOWS__) {
1160
+ const [low, high] = splitBigIntToInt64Parts(this.isDirty);
936
1161
  // @ts-ignore
937
1162
  const view = this.view?.windows ?? this.view._view;
938
1163
  view.SyncStyle(low, high);
@@ -1340,7 +1565,8 @@ export class Style {
1340
1565
  else {
1341
1566
  this.isDirty = this.isDirty | StateKeys.DISPLAY_MODE.bits;
1342
1567
  }
1343
- this.commitState(StateKeys.DISPLAY.and(StateKeys.DISPLAY_MODE));
1568
+ // DISPLAY/DISPLAY_MODE are disjoint bits; use .or(), not .and()
1569
+ this.commitState(StateKeys.DISPLAY.or(StateKeys.DISPLAY_MODE));
1344
1570
  }
1345
1571
  }
1346
1572
  get position() {
@@ -1409,6 +1635,10 @@ export class Style {
1409
1635
  return 'wrap';
1410
1636
  case 2:
1411
1637
  return 'wrap-reverse';
1638
+ case 3:
1639
+ return 'balance';
1640
+ case 4:
1641
+ return 'balance-reverse';
1412
1642
  }
1413
1643
  }
1414
1644
  set flexWrap(value) {
@@ -1423,6 +1653,12 @@ export class Style {
1423
1653
  case 'wrap-reverse':
1424
1654
  wrap = 2;
1425
1655
  break;
1656
+ case 'balance':
1657
+ wrap = 3;
1658
+ break;
1659
+ case 'balance-reverse':
1660
+ wrap = 4;
1661
+ break;
1426
1662
  }
1427
1663
  if (wrap != -1) {
1428
1664
  this.prepareMut();
@@ -1441,10 +1677,13 @@ export class Style {
1441
1677
  }
1442
1678
  set minWidth(value) {
1443
1679
  switch (typeof value) {
1444
- case 'string':
1680
+ case 'string': {
1445
1681
  this.prepareMut();
1446
- setInt8(this.style_view, StyleKeys.MIN_WIDTH_TYPE, 0);
1682
+ const dim = lengthPercentageAutoFromString(value);
1683
+ setInt8(this.style_view, StyleKeys.MIN_WIDTH_TYPE, dim.type);
1684
+ setFloat32(this.style_view, StyleKeys.MIN_WIDTH_VALUE, dim.value);
1447
1685
  break;
1686
+ }
1448
1687
  case 'number':
1449
1688
  this.prepareMut();
1450
1689
  setInt8(this.style_view, StyleKeys.MIN_WIDTH_TYPE, 1);
@@ -1479,10 +1718,13 @@ export class Style {
1479
1718
  }
1480
1719
  set minHeight(value) {
1481
1720
  switch (typeof value) {
1482
- case 'string':
1721
+ case 'string': {
1483
1722
  this.prepareMut();
1484
- setInt8(this.style_view, StyleKeys.MIN_HEIGHT_TYPE, 0);
1723
+ const dim = lengthPercentageAutoFromString(value);
1724
+ setInt8(this.style_view, StyleKeys.MIN_HEIGHT_TYPE, dim.type);
1725
+ setFloat32(this.style_view, StyleKeys.MIN_HEIGHT_VALUE, dim.value);
1485
1726
  break;
1727
+ }
1486
1728
  case 'number':
1487
1729
  this.prepareMut();
1488
1730
  setInt8(this.style_view, StyleKeys.MIN_HEIGHT_TYPE, 1);
@@ -1513,29 +1755,15 @@ export class Style {
1513
1755
  get width() {
1514
1756
  const type = getInt8(this.style_view, StyleKeys.WIDTH_TYPE);
1515
1757
  const value = getFloat32(this.style_view, StyleKeys.WIDTH_VALUE);
1516
- return parseLengthPercentageAuto(type, value);
1758
+ return parseDimension(type, value);
1517
1759
  }
1518
1760
  set width(value) {
1519
1761
  switch (typeof value) {
1520
1762
  case 'string': {
1521
- // Parse the string instead of forcing `auto`. Reactively-applied sizes arrive as strings
1522
- // ("48", "48px", "50%") — the old stub dropped them to auto (0), so dynamically-added boxes
1523
- // rendered 0x0. unitless/dip → device pixels; px → as-is; % → percent.
1524
1763
  this.prepareMut();
1525
- const t = value.trim();
1526
- if (t === '' || t === 'auto') {
1527
- setInt8(this.style_view, StyleKeys.WIDTH_TYPE, 0);
1528
- setFloat32(this.style_view, StyleKeys.WIDTH_VALUE, 0);
1529
- }
1530
- else if (t.endsWith('%')) {
1531
- setInt8(this.style_view, StyleKeys.WIDTH_TYPE, 2);
1532
- setFloat32(this.style_view, StyleKeys.WIDTH_VALUE, parseFloat(t) || 0);
1533
- }
1534
- else {
1535
- const n = parseFloat(t) || 0;
1536
- setInt8(this.style_view, StyleKeys.WIDTH_TYPE, 1);
1537
- setFloat32(this.style_view, StyleKeys.WIDTH_VALUE, t.endsWith('px') ? n : layout.toDevicePixels(n));
1538
- }
1764
+ const dim = dimensionFromString(value);
1765
+ setInt8(this.style_view, StyleKeys.WIDTH_TYPE, dim.type);
1766
+ setFloat32(this.style_view, StyleKeys.WIDTH_VALUE, dim.value);
1539
1767
  break;
1540
1768
  }
1541
1769
  case 'number':
@@ -1568,27 +1796,15 @@ export class Style {
1568
1796
  get height() {
1569
1797
  const type = getInt8(this.style_view, StyleKeys.HEIGHT_TYPE);
1570
1798
  const value = getFloat32(this.style_view, StyleKeys.HEIGHT_VALUE);
1571
- return parseLengthPercentageAuto(type, value);
1799
+ return parseDimension(type, value);
1572
1800
  }
1573
1801
  set height(value) {
1574
1802
  switch (typeof value) {
1575
1803
  case 'string': {
1576
- // Parse the string (see width setter) — the old stub forced auto/0, breaking string sizes.
1577
1804
  this.prepareMut();
1578
- const t = value.trim();
1579
- if (t === '' || t === 'auto') {
1580
- setInt8(this.style_view, StyleKeys.HEIGHT_TYPE, 0);
1581
- setFloat32(this.style_view, StyleKeys.HEIGHT_VALUE, 0);
1582
- }
1583
- else if (t.endsWith('%')) {
1584
- setInt8(this.style_view, StyleKeys.HEIGHT_TYPE, 2);
1585
- setFloat32(this.style_view, StyleKeys.HEIGHT_VALUE, parseFloat(t) || 0);
1586
- }
1587
- else {
1588
- const n = parseFloat(t) || 0;
1589
- setInt8(this.style_view, StyleKeys.HEIGHT_TYPE, 1);
1590
- setFloat32(this.style_view, StyleKeys.HEIGHT_VALUE, t.endsWith('px') ? n : layout.toDevicePixels(n));
1591
- }
1805
+ const dim = dimensionFromString(value);
1806
+ setInt8(this.style_view, StyleKeys.HEIGHT_TYPE, dim.type);
1807
+ setFloat32(this.style_view, StyleKeys.HEIGHT_VALUE, dim.value);
1592
1808
  break;
1593
1809
  }
1594
1810
  case 'number':
@@ -1625,10 +1841,13 @@ export class Style {
1625
1841
  }
1626
1842
  set maxWidth(value) {
1627
1843
  switch (typeof value) {
1628
- case 'string':
1844
+ case 'string': {
1629
1845
  this.prepareMut();
1630
- setInt8(this.style_view, StyleKeys.MAX_WIDTH_TYPE, 0);
1846
+ const dim = lengthPercentageAutoFromString(value);
1847
+ setInt8(this.style_view, StyleKeys.MAX_WIDTH_TYPE, dim.type);
1848
+ setFloat32(this.style_view, StyleKeys.MAX_WIDTH_VALUE, dim.value);
1631
1849
  break;
1850
+ }
1632
1851
  case 'number':
1633
1852
  this.prepareMut();
1634
1853
  setInt8(this.style_view, StyleKeys.MAX_WIDTH_TYPE, 1);
@@ -1663,10 +1882,13 @@ export class Style {
1663
1882
  }
1664
1883
  set maxHeight(value) {
1665
1884
  switch (typeof value) {
1666
- case 'string':
1885
+ case 'string': {
1667
1886
  this.prepareMut();
1668
- setInt8(this.style_view, StyleKeys.MAX_HEIGHT_TYPE, 0);
1887
+ const dim = lengthPercentageAutoFromString(value);
1888
+ setInt8(this.style_view, StyleKeys.MAX_HEIGHT_TYPE, dim.type);
1889
+ setFloat32(this.style_view, StyleKeys.MAX_HEIGHT_VALUE, dim.value);
1669
1890
  break;
1891
+ }
1670
1892
  case 'number':
1671
1893
  this.prepareMut();
1672
1894
  setInt8(this.style_view, StyleKeys.MAX_HEIGHT_TYPE, 1);
@@ -1834,10 +2056,12 @@ export class Style {
1834
2056
  var type;
1835
2057
  var insetValue;
1836
2058
  switch (typeof value) {
1837
- case 'string':
1838
- type = 0;
1839
- insetValue = 0;
2059
+ case 'string': {
2060
+ const dim = lengthPercentageAutoFromString(value);
2061
+ type = dim.type;
2062
+ insetValue = dim.value;
1840
2063
  break;
2064
+ }
1841
2065
  case 'number':
1842
2066
  type = 1;
1843
2067
  insetValue = layout.toDevicePixels(value);
@@ -1874,13 +2098,14 @@ export class Style {
1874
2098
  return parseLengthPercentageAuto(type, value);
1875
2099
  }
1876
2100
  set left(value) {
1877
- if (value === 'auto') {
1878
- this.prepareMut();
1879
- setInt8(this.style_view, StyleKeys.INSET_LEFT_TYPE, 0);
1880
- setFloat32(this.style_view, StyleKeys.INSET_LEFT_VALUE, 0);
1881
- return;
1882
- }
1883
2101
  switch (typeof value) {
2102
+ case 'string': {
2103
+ this.prepareMut();
2104
+ const dim = lengthPercentageAutoFromString(value);
2105
+ setInt8(this.style_view, StyleKeys.INSET_LEFT_TYPE, dim.type);
2106
+ setFloat32(this.style_view, StyleKeys.INSET_LEFT_VALUE, dim.value);
2107
+ break;
2108
+ }
1884
2109
  case 'number':
1885
2110
  this.prepareMut();
1886
2111
  setInt8(this.style_view, StyleKeys.INSET_LEFT_TYPE, 1);
@@ -1914,13 +2139,14 @@ export class Style {
1914
2139
  return parseLengthPercentageAuto(type, value);
1915
2140
  }
1916
2141
  set right(value) {
1917
- if (value === 'auto') {
1918
- this.prepareMut();
1919
- setInt8(this.style_view, StyleKeys.INSET_RIGHT_TYPE, 0);
1920
- setFloat32(this.style_view, StyleKeys.INSET_RIGHT_VALUE, 0);
1921
- return;
1922
- }
1923
2142
  switch (typeof value) {
2143
+ case 'string': {
2144
+ this.prepareMut();
2145
+ const dim = lengthPercentageAutoFromString(value);
2146
+ setInt8(this.style_view, StyleKeys.INSET_RIGHT_TYPE, dim.type);
2147
+ setFloat32(this.style_view, StyleKeys.INSET_RIGHT_VALUE, dim.value);
2148
+ break;
2149
+ }
1924
2150
  case 'number':
1925
2151
  this.prepareMut();
1926
2152
  setInt8(this.style_view, StyleKeys.INSET_RIGHT_TYPE, 1);
@@ -1954,13 +2180,14 @@ export class Style {
1954
2180
  return parseLengthPercentageAuto(type, value);
1955
2181
  }
1956
2182
  set top(value) {
1957
- if (value === 'auto') {
1958
- this.prepareMut();
1959
- setInt8(this.style_view, StyleKeys.INSET_TOP_TYPE, 0);
1960
- setFloat32(this.style_view, StyleKeys.INSET_TOP_VALUE, 0);
1961
- return;
1962
- }
1963
2183
  switch (typeof value) {
2184
+ case 'string': {
2185
+ this.prepareMut();
2186
+ const dim = lengthPercentageAutoFromString(value);
2187
+ setInt8(this.style_view, StyleKeys.INSET_TOP_TYPE, dim.type);
2188
+ setFloat32(this.style_view, StyleKeys.INSET_TOP_VALUE, dim.value);
2189
+ break;
2190
+ }
1964
2191
  case 'number':
1965
2192
  this.prepareMut();
1966
2193
  setInt8(this.style_view, StyleKeys.INSET_TOP_TYPE, 1);
@@ -1994,13 +2221,14 @@ export class Style {
1994
2221
  return parseLengthPercentageAuto(type, value);
1995
2222
  }
1996
2223
  set bottom(value) {
1997
- if (value === 'auto') {
1998
- this.prepareMut();
1999
- setInt8(this.style_view, StyleKeys.INSET_BOTTOM_TYPE, 0);
2000
- setFloat32(this.style_view, StyleKeys.INSET_BOTTOM_VALUE, 0);
2001
- return;
2002
- }
2003
2224
  switch (typeof value) {
2225
+ case 'string': {
2226
+ this.prepareMut();
2227
+ const dim = lengthPercentageAutoFromString(value);
2228
+ setInt8(this.style_view, StyleKeys.INSET_BOTTOM_TYPE, dim.type);
2229
+ setFloat32(this.style_view, StyleKeys.INSET_BOTTOM_VALUE, dim.value);
2230
+ break;
2231
+ }
2004
2232
  case 'number':
2005
2233
  this.prepareMut();
2006
2234
  setInt8(this.style_view, StyleKeys.INSET_BOTTOM_TYPE, 1);
@@ -2032,10 +2260,12 @@ export class Style {
2032
2260
  var type;
2033
2261
  var marginValue;
2034
2262
  switch (typeof value) {
2035
- case 'string':
2036
- type = 0;
2037
- marginValue = 0;
2263
+ case 'string': {
2264
+ const dim = lengthPercentageAutoFromString(value);
2265
+ type = dim.type;
2266
+ marginValue = dim.value;
2038
2267
  break;
2268
+ }
2039
2269
  case 'number':
2040
2270
  type = 1;
2041
2271
  marginValue = layout.toDevicePixels(value);
@@ -2073,10 +2303,13 @@ export class Style {
2073
2303
  }
2074
2304
  set marginLeft(value) {
2075
2305
  switch (typeof value) {
2076
- case 'string':
2306
+ case 'string': {
2077
2307
  this.prepareMut();
2078
- setInt8(this.style_view, StyleKeys.MARGIN_LEFT_TYPE, 0);
2308
+ const dim = lengthPercentageAutoFromString(value);
2309
+ setInt8(this.style_view, StyleKeys.MARGIN_LEFT_TYPE, dim.type);
2310
+ setFloat32(this.style_view, StyleKeys.MARGIN_LEFT_VALUE, dim.value);
2079
2311
  break;
2312
+ }
2080
2313
  case 'number':
2081
2314
  this.prepareMut();
2082
2315
  setInt8(this.style_view, StyleKeys.MARGIN_LEFT_TYPE, 1);
@@ -2111,10 +2344,13 @@ export class Style {
2111
2344
  }
2112
2345
  set marginRight(value) {
2113
2346
  switch (typeof value) {
2114
- case 'string':
2347
+ case 'string': {
2115
2348
  this.prepareMut();
2116
- setInt8(this.style_view, StyleKeys.MARGIN_RIGHT_TYPE, 0);
2349
+ const dim = lengthPercentageAutoFromString(value);
2350
+ setInt8(this.style_view, StyleKeys.MARGIN_RIGHT_TYPE, dim.type);
2351
+ setFloat32(this.style_view, StyleKeys.MARGIN_RIGHT_VALUE, dim.value);
2117
2352
  break;
2353
+ }
2118
2354
  case 'number':
2119
2355
  this.prepareMut();
2120
2356
  setInt8(this.style_view, StyleKeys.MARGIN_RIGHT_TYPE, 1);
@@ -2149,10 +2385,13 @@ export class Style {
2149
2385
  }
2150
2386
  set marginTop(value) {
2151
2387
  switch (typeof value) {
2152
- case 'string':
2388
+ case 'string': {
2153
2389
  this.prepareMut();
2154
- setInt8(this.style_view, StyleKeys.MARGIN_TOP_TYPE, 0);
2390
+ const dim = lengthPercentageAutoFromString(value);
2391
+ setInt8(this.style_view, StyleKeys.MARGIN_TOP_TYPE, dim.type);
2392
+ setFloat32(this.style_view, StyleKeys.MARGIN_TOP_VALUE, dim.value);
2155
2393
  break;
2394
+ }
2156
2395
  case 'number':
2157
2396
  this.prepareMut();
2158
2397
  setInt8(this.style_view, StyleKeys.MARGIN_TOP_TYPE, 1);
@@ -2187,10 +2426,13 @@ export class Style {
2187
2426
  }
2188
2427
  set marginBottom(value) {
2189
2428
  switch (typeof value) {
2190
- case 'string':
2429
+ case 'string': {
2191
2430
  this.prepareMut();
2192
- setInt8(this.style_view, StyleKeys.MARGIN_BOTTOM_TYPE, 0);
2431
+ const dim = lengthPercentageAutoFromString(value);
2432
+ setInt8(this.style_view, StyleKeys.MARGIN_BOTTOM_TYPE, dim.type);
2433
+ setFloat32(this.style_view, StyleKeys.MARGIN_BOTTOM_VALUE, dim.value);
2193
2434
  break;
2435
+ }
2194
2436
  case 'number':
2195
2437
  this.prepareMut();
2196
2438
  setInt8(this.style_view, StyleKeys.MARGIN_BOTTOM_TYPE, 1);
@@ -2231,6 +2473,13 @@ export class Style {
2231
2473
  }
2232
2474
  set paddingLeft(value) {
2233
2475
  switch (typeof value) {
2476
+ case 'string': {
2477
+ this.prepareMut();
2478
+ const dim = lengthPercentageFromString(value);
2479
+ setInt8(this.style_view, StyleKeys.PADDING_LEFT_TYPE, dim.type);
2480
+ setFloat32(this.style_view, StyleKeys.PADDING_LEFT_VALUE, dim.value);
2481
+ break;
2482
+ }
2234
2483
  case 'number':
2235
2484
  this.prepareMut();
2236
2485
  setInt8(this.style_view, StyleKeys.PADDING_LEFT_TYPE, 0);
@@ -2265,6 +2514,13 @@ export class Style {
2265
2514
  }
2266
2515
  set paddingRight(value) {
2267
2516
  switch (typeof value) {
2517
+ case 'string': {
2518
+ this.prepareMut();
2519
+ const dim = lengthPercentageFromString(value);
2520
+ setInt8(this.style_view, StyleKeys.PADDING_RIGHT_TYPE, dim.type);
2521
+ setFloat32(this.style_view, StyleKeys.PADDING_RIGHT_VALUE, dim.value);
2522
+ break;
2523
+ }
2268
2524
  case 'number':
2269
2525
  this.prepareMut();
2270
2526
  setInt8(this.style_view, StyleKeys.PADDING_RIGHT_TYPE, 0);
@@ -2299,6 +2555,13 @@ export class Style {
2299
2555
  }
2300
2556
  set paddingTop(value) {
2301
2557
  switch (typeof value) {
2558
+ case 'string': {
2559
+ this.prepareMut();
2560
+ const dim = lengthPercentageFromString(value);
2561
+ setInt8(this.style_view, StyleKeys.PADDING_TOP_TYPE, dim.type);
2562
+ setFloat32(this.style_view, StyleKeys.PADDING_TOP_VALUE, dim.value);
2563
+ break;
2564
+ }
2302
2565
  case 'number':
2303
2566
  this.prepareMut();
2304
2567
  setInt8(this.style_view, StyleKeys.PADDING_TOP_TYPE, 0);
@@ -2333,6 +2596,13 @@ export class Style {
2333
2596
  }
2334
2597
  set paddingBottom(value) {
2335
2598
  switch (typeof value) {
2599
+ case 'string': {
2600
+ this.prepareMut();
2601
+ const dim = lengthPercentageFromString(value);
2602
+ setInt8(this.style_view, StyleKeys.PADDING_BOTTOM_TYPE, dim.type);
2603
+ setFloat32(this.style_view, StyleKeys.PADDING_BOTTOM_VALUE, dim.value);
2604
+ break;
2605
+ }
2336
2606
  case 'number':
2337
2607
  this.prepareMut();
2338
2608
  setInt8(this.style_view, StyleKeys.PADDING_BOTTOM_TYPE, 0);
@@ -2464,6 +2734,8 @@ export class Style {
2464
2734
  return getFloat32(this.style_view, StyleKeys.ASPECT_RATIO);
2465
2735
  }
2466
2736
  set aspectRatio(value) {
2737
+ if (getFloat32(this.style_view, StyleKeys.ASPECT_RATIO) === value)
2738
+ return;
2467
2739
  this.prepareMut();
2468
2740
  setFloat32(this.style_view, StyleKeys.ASPECT_RATIO, value);
2469
2741
  this.commitState(StateKeys.ASPECT_RATIO);
@@ -2471,14 +2743,17 @@ export class Style {
2471
2743
  get flexBasis() {
2472
2744
  const type = getInt8(this.style_view, StyleKeys.FLEX_BASIS_TYPE);
2473
2745
  const value = getFloat32(this.style_view, StyleKeys.FLEX_BASIS_VALUE);
2474
- return parseLengthPercentageAuto(type, value);
2746
+ return parseDimension(type, value);
2475
2747
  }
2476
2748
  set flexBasis(value) {
2477
2749
  switch (typeof value) {
2478
- case 'string':
2750
+ case 'string': {
2479
2751
  this.prepareMut();
2480
- setInt8(this.style_view, StyleKeys.FLEX_BASIS_TYPE, 0);
2752
+ const dim = dimensionFromString(value);
2753
+ setInt8(this.style_view, StyleKeys.FLEX_BASIS_TYPE, dim.type);
2754
+ setFloat32(this.style_view, StyleKeys.FLEX_BASIS_VALUE, dim.value);
2481
2755
  break;
2756
+ }
2482
2757
  case 'number':
2483
2758
  this.prepareMut();
2484
2759
  setInt8(this.style_view, StyleKeys.FLEX_BASIS_TYPE, 1);
@@ -2632,8 +2907,13 @@ export class Style {
2632
2907
  return 'start';
2633
2908
  case 3 /* AlignContent.Stretch */:
2634
2909
  return 'stretch';
2910
+ case 7 /* AlignContent.FlexStart */:
2911
+ return 'flex-start';
2912
+ case 8 /* AlignContent.FlexEnd */:
2913
+ return 'flex-end';
2635
2914
  }
2636
2915
  }
2916
+ // 'flex-start'/'flex-end' were missing from this switch entirely
2637
2917
  set alignContent(value) {
2638
2918
  let align = -1;
2639
2919
  switch (value) {
@@ -2661,6 +2941,12 @@ export class Style {
2661
2941
  case 'stretch':
2662
2942
  align = 3 /* AlignContent.Stretch */;
2663
2943
  break;
2944
+ case 'flex-start':
2945
+ align = 7 /* AlignContent.FlexStart */;
2946
+ break;
2947
+ case 'flex-end':
2948
+ align = 8 /* AlignContent.FlexEnd */;
2949
+ break;
2664
2950
  }
2665
2951
  if (align !== -1) {
2666
2952
  this.prepareMut();
@@ -2827,6 +3113,12 @@ export class Style {
2827
3113
  case 'stretch':
2828
3114
  v = 3 /* JustifyContent.Stretch */;
2829
3115
  break;
3116
+ case 'flex-start':
3117
+ v = 7 /* JustifyContent.FlexStart */;
3118
+ break;
3119
+ case 'flex-end':
3120
+ v = 8 /* JustifyContent.FlexEnd */;
3121
+ break;
2830
3122
  }
2831
3123
  if (v !== -1) {
2832
3124
  this.prepareMut();
@@ -2850,6 +3142,8 @@ export class Style {
2850
3142
  if (!this.nativeView) {
2851
3143
  return;
2852
3144
  }
3145
+ // A bare number can't marshal over JNI into the native String setter.
3146
+ value = value == null ? '' : String(value);
2853
3147
  if (__ANDROID__) {
2854
3148
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridAutoRows(this.nativeView, value);
2855
3149
  }
@@ -2876,6 +3170,8 @@ export class Style {
2876
3170
  if (!this.nativeView) {
2877
3171
  return;
2878
3172
  }
3173
+ // See gridAutoRows above.
3174
+ value = value == null ? '' : String(value);
2879
3175
  if (__ANDROID__) {
2880
3176
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridAutoColumns(this.nativeView, value);
2881
3177
  }
@@ -2922,6 +3218,8 @@ export class Style {
2922
3218
  if (!this.nativeView) {
2923
3219
  return;
2924
3220
  }
3221
+ // See gridAutoRows above.
3222
+ value = value == null ? '' : String(value);
2925
3223
  if (__ANDROID__) {
2926
3224
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridColumn(this.nativeView, value);
2927
3225
  }
@@ -2960,6 +3258,8 @@ export class Style {
2960
3258
  if (!this.nativeView) {
2961
3259
  return;
2962
3260
  }
3261
+ // See gridAutoRows above.
3262
+ value = value == null ? '' : String(value);
2963
3263
  if (__ANDROID__) {
2964
3264
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridColumnStart(this.nativeView, value);
2965
3265
  }
@@ -2986,6 +3286,8 @@ export class Style {
2986
3286
  if (!this.nativeView) {
2987
3287
  return;
2988
3288
  }
3289
+ // See gridAutoRows above.
3290
+ value = value == null ? '' : String(value);
2989
3291
  if (__ANDROID__) {
2990
3292
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridColumnEnd(this.nativeView, value);
2991
3293
  }
@@ -3000,6 +3302,8 @@ export class Style {
3000
3302
  if (!this.nativeView) {
3001
3303
  return;
3002
3304
  }
3305
+ // See gridAutoRows above.
3306
+ value = value == null ? '' : String(value);
3003
3307
  if (__ANDROID__) {
3004
3308
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridRow(this.nativeView, value);
3005
3309
  }
@@ -3038,6 +3342,8 @@ export class Style {
3038
3342
  if (!this.nativeView) {
3039
3343
  return;
3040
3344
  }
3345
+ // See gridAutoRows above.
3346
+ value = value == null ? '' : String(value);
3041
3347
  if (__ANDROID__) {
3042
3348
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridRowStart(this.nativeView, value);
3043
3349
  }
@@ -3064,6 +3370,8 @@ export class Style {
3064
3370
  if (!this.nativeView) {
3065
3371
  return;
3066
3372
  }
3373
+ // See gridAutoRows above.
3374
+ value = value == null ? '' : String(value);
3067
3375
  if (__ANDROID__) {
3068
3376
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridRowEnd(this.nativeView, value);
3069
3377
  }
@@ -3078,6 +3386,8 @@ export class Style {
3078
3386
  if (!this.nativeView) {
3079
3387
  return;
3080
3388
  }
3389
+ // See gridAutoRows above.
3390
+ value = value == null ? '' : String(value);
3081
3391
  if (__ANDROID__) {
3082
3392
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridArea(this.nativeView, value);
3083
3393
  }
@@ -3104,9 +3414,8 @@ export class Style {
3104
3414
  if (!this.nativeView) {
3105
3415
  return;
3106
3416
  }
3107
- // Reset (e.g. a media query toggling grid-rows off) passes null; the native
3108
- // setters are non-null, so coerce to '' which clears the template.
3109
- value = value ?? '';
3417
+ // null clears the template; also guards against a bare number (see gridAutoRows above).
3418
+ value = value == null ? '' : String(value);
3110
3419
  if (__ANDROID__) {
3111
3420
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridTemplateRows(this.nativeView, value);
3112
3421
  }
@@ -3145,9 +3454,8 @@ export class Style {
3145
3454
  if (!this.nativeView) {
3146
3455
  return;
3147
3456
  }
3148
- // Reset (e.g. a media query toggling grid-cols off) passes null; the native
3149
- // setters are non-null, so coerce to '' which clears the template.
3150
- value = value ?? '';
3457
+ // null clears the template; also guards against a bare number (see gridAutoRows above).
3458
+ value = value == null ? '' : String(value);
3151
3459
  if (__ANDROID__) {
3152
3460
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridTemplateColumns(this.nativeView, value);
3153
3461
  }
@@ -3174,8 +3482,8 @@ export class Style {
3174
3482
  if (!this.nativeView) {
3175
3483
  return;
3176
3484
  }
3177
- // Reset passes null; the native setters are non-null, coerce to '' (clears it).
3178
- value = value ?? '';
3485
+ // null clears it; also guards against a bare number (see gridAutoRows above).
3486
+ value = value == null ? '' : String(value);
3179
3487
  if (__ANDROID__) {
3180
3488
  org.nativescript.mason.masonkit.NodeHelper.getShared().setGridTemplateAreas(this.nativeView, value);
3181
3489
  }
@@ -3265,6 +3573,9 @@ export class Style {
3265
3573
  return getFloat32(this.style_view, StyleKeys.FLEX_GROW);
3266
3574
  }
3267
3575
  set flexGrow(value) {
3576
+ // skip invalidation on a no-op re-apply of the same value
3577
+ if (getFloat32(this.style_view, StyleKeys.FLEX_GROW) === value)
3578
+ return;
3268
3579
  this.prepareMut();
3269
3580
  setFloat32(this.style_view, StyleKeys.FLEX_GROW, value);
3270
3581
  this.commitState(StateKeys.FLEX_GROW);
@@ -3273,6 +3584,8 @@ export class Style {
3273
3584
  return getFloat32(this.style_view, StyleKeys.FLEX_SHRINK);
3274
3585
  }
3275
3586
  set flexShrink(value) {
3587
+ if (getFloat32(this.style_view, StyleKeys.FLEX_SHRINK) === value)
3588
+ return;
3276
3589
  this.prepareMut();
3277
3590
  setFloat32(this.style_view, StyleKeys.FLEX_SHRINK, value);
3278
3591
  this.commitState(StateKeys.FLEX_SHRINK);
@@ -3637,7 +3950,9 @@ export class Style {
3637
3950
  return '';
3638
3951
  }
3639
3952
  set paddingCss(value) {
3640
- const strValue = typeof value === 'number' ? `${value}px` : value;
3953
+ // a bare number is dip, matching other numeric setters; Android's
3954
+ // native parser treats "px" as unscaled device pixels, "dip" as scaled
3955
+ const strValue = typeof value === 'number' ? `${value}dip` : value;
3641
3956
  this.setPseudoCssStringValue('padding', strValue, () => org.nativescript.mason.masonkit.NodeHelper.getShared().setPaddingCss(this.nativeView, strValue), () => (this.nativeView.style.paddingCss = strValue));
3642
3957
  }
3643
3958
  get marginCss() {
@@ -3652,7 +3967,8 @@ export class Style {
3652
3967
  return '';
3653
3968
  }
3654
3969
  set marginCss(value) {
3655
- const strValue = typeof value === 'number' ? `${value}px` : value;
3970
+ // See the comment on `paddingCss` above — same dip-vs-px mislabeling fix.
3971
+ const strValue = typeof value === 'number' ? `${value}dip` : value;
3656
3972
  this.setPseudoCssStringValue('margin', strValue, () => org.nativescript.mason.masonkit.NodeHelper.getShared().setMarginCss(this.nativeView, strValue), () => (this.nativeView.style.marginCss = strValue));
3657
3973
  }
3658
3974
  get insetCss() {
@@ -3667,7 +3983,8 @@ export class Style {
3667
3983
  return '';
3668
3984
  }
3669
3985
  set insetCss(value) {
3670
- const strValue = typeof value === 'number' ? `${value}px` : value;
3986
+ // See the comment on `paddingCss` above — same dip-vs-px mislabeling fix.
3987
+ const strValue = typeof value === 'number' ? `${value}dip` : value;
3671
3988
  this.setPseudoCssStringValue('inset', strValue, () => org.nativescript.mason.masonkit.NodeHelper.getShared().setInsetCss(this.nativeView, strValue), () => (this.nativeView.style.insetCss = strValue));
3672
3989
  }
3673
3990
  get borderLeft() {
@@ -3912,6 +4229,8 @@ export class Style {
3912
4229
  return getInt32(this.style_view, StyleKeys.Z_INDEX);
3913
4230
  }
3914
4231
  set zIndex(value) {
4232
+ if (getInt32(this.style_view, StyleKeys.Z_INDEX) === value)
4233
+ return;
3915
4234
  this.prepareMut();
3916
4235
  setInt32(this.style_view, StyleKeys.Z_INDEX, value);
3917
4236
  this.commitState(StateKeys.Z_INDEX);