@triniwiz/nativescript-masonkit 1.0.0-beta.120 → 1.0.0-beta.121

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 (142) hide show
  1. package/README.md +67 -27
  2. package/angular/README.md +7 -9
  3. package/button/index.windows.js +1 -1
  4. package/button/index.windows.js.map +1 -1
  5. package/common.d.ts +8 -2
  6. package/common.js +45 -30
  7. package/common.js.map +1 -1
  8. package/css-shorthands.js +14 -2
  9. package/css-shorthands.js.map +1 -1
  10. package/display-density.d.ts +9 -0
  11. package/display-density.js +21 -0
  12. package/display-density.js.map +1 -0
  13. package/foreign-layout.js +1 -1
  14. package/foreign-layout.js.map +1 -1
  15. package/gradient-stops.d.ts +17 -0
  16. package/gradient-stops.js +66 -0
  17. package/gradient-stops.js.map +1 -1
  18. package/index.d.ts +6 -3
  19. package/index.ios.d.ts +3 -0
  20. package/index.ios.js +3 -0
  21. package/index.ios.js.map +1 -1
  22. package/index.windows.d.ts +1 -1
  23. package/index.windows.js +1 -1
  24. package/index.windows.js.map +1 -1
  25. package/{html-windows.js → inner-html.windows.js} +6 -1
  26. package/inner-html.windows.js.map +1 -0
  27. package/input/index.ios.d.ts +2 -0
  28. package/input/index.ios.js +7 -0
  29. package/input/index.ios.js.map +1 -1
  30. package/input/index.windows.js +1 -1
  31. package/input/index.windows.js.map +1 -1
  32. package/li/index.windows.js +1 -1
  33. package/li/index.windows.js.map +1 -1
  34. package/list/index.windows.js +1 -1
  35. package/list/index.windows.js.map +1 -1
  36. package/mask.d.ts +54 -0
  37. package/mask.js +27 -0
  38. package/mask.js.map +1 -0
  39. package/{windows-mask.d.ts → mask.windows.d.ts} +24 -30
  40. package/{windows-mask.js → mask.windows.js} +97 -11
  41. package/mask.windows.js.map +1 -0
  42. package/nativescript.webpack.js +35 -0
  43. package/package.json +1 -1
  44. package/panel-helpers.d.ts +3 -0
  45. package/panel-helpers.js +9 -0
  46. package/panel-helpers.js.map +1 -0
  47. package/{windows-panel-helpers.js → panel-helpers.windows.js} +1 -1
  48. package/{windows-panel-helpers.js.map → panel-helpers.windows.js.map} +1 -1
  49. package/platforms/android/masonkit-release.aar +0 -0
  50. package/platforms/ios/Mason.xcframework/Info.plist +4 -4
  51. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Headers/Mason-Swift.h +11 -2
  52. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Headers/mason_native.h +10 -0
  53. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Mason +0 -0
  54. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
  55. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.abi.json +7069 -15103
  56. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.private.swiftinterface +17 -5
  57. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  58. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.swiftinterface +17 -5
  59. package/platforms/ios/Mason.xcframework/ios-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  60. package/platforms/ios/Mason.xcframework/ios-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +9735 -9456
  61. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Headers/Mason-Swift.h +22 -4
  62. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Headers/mason_native.h +10 -0
  63. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Mason +0 -0
  64. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo +0 -0
  65. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo +0 -0
  66. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.abi.json +7069 -15103
  67. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +17 -5
  68. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  69. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.swiftinterface +17 -5
  70. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.abi.json +7069 -15103
  71. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +17 -5
  72. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  73. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +17 -5
  74. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/_CodeSignature/CodeResources +28 -28
  75. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +2 -2
  76. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +9729 -9450
  77. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/x86_64/Mason.yml +9286 -9010
  78. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Headers/Mason-Swift.h +10 -2
  79. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Headers/mason_native.h +10 -0
  80. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Mason +0 -0
  81. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-xros.swiftsourceinfo +0 -0
  82. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.abi.json +6726 -14794
  83. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.private.swiftinterface +16 -5
  84. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.swiftdoc +0 -0
  85. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.swiftinterface +16 -5
  86. package/platforms/ios/Mason.xcframework/xros-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  87. package/platforms/ios/Mason.xcframework/xros-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +9218 -8945
  88. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Headers/Mason-Swift.h +10 -2
  89. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Headers/mason_native.h +10 -0
  90. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Mason +0 -0
  91. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-xros-simulator.swiftsourceinfo +0 -0
  92. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.abi.json +6726 -14794
  93. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.private.swiftinterface +16 -5
  94. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.swiftdoc +0 -0
  95. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.swiftinterface +16 -5
  96. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/_CodeSignature/CodeResources +16 -16
  97. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  98. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +9217 -8944
  99. package/platforms/windows/arm64/NativeScript.Mason.dll +0 -0
  100. package/platforms/windows/arm64/NativeScript.Mason.winmd +0 -0
  101. package/platforms/windows/x64/NativeScript.Mason.dll +0 -0
  102. package/platforms/windows/x64/NativeScript.Mason.winmd +0 -0
  103. package/postcss-guard.js +64 -0
  104. package/properties.d.ts +6 -2
  105. package/properties.js +78 -13
  106. package/properties.js.map +1 -1
  107. package/scroll/index.windows.js +1 -1
  108. package/scroll/index.windows.js.map +1 -1
  109. package/style.d.ts +40 -11
  110. package/style.js +364 -52
  111. package/style.js.map +1 -1
  112. package/svg-path.windows.d.ts +8 -0
  113. package/svg-path.windows.js +204 -0
  114. package/svg-path.windows.js.map +1 -0
  115. package/text/index.windows.js +1 -1
  116. package/text/index.windows.js.map +1 -1
  117. package/textarea/index.ios.d.ts +2 -0
  118. package/textarea/index.ios.js +7 -0
  119. package/textarea/index.ios.js.map +1 -1
  120. package/tree/index.android.js +14 -3
  121. package/tree/index.android.js.map +1 -1
  122. package/tree/index.ios.js +11 -3
  123. package/tree/index.ios.js.map +1 -1
  124. package/tree/index.windows.js +20 -0
  125. package/tree/index.windows.js.map +1 -1
  126. package/typings/android.d.ts +13 -0
  127. package/typings/objc!Mason.d.ts +6 -0
  128. package/units.d.ts +7 -0
  129. package/units.js +30 -2
  130. package/units.js.map +1 -1
  131. package/utils/index.android.js +28 -27
  132. package/utils/index.android.js.map +1 -1
  133. package/utils/index.ios.d.ts +1 -1
  134. package/view/index.windows.js +1 -1
  135. package/view/index.windows.js.map +1 -1
  136. package/vue/README.md +12 -7
  137. package/web.js +4 -3
  138. package/web.js.map +1 -1
  139. package/html-windows.js.map +0 -1
  140. package/windows-mask.js.map +0 -1
  141. /package/{html-windows.d.ts → inner-html.windows.d.ts} +0 -0
  142. /package/{windows-panel-helpers.d.ts → panel-helpers.windows.d.ts} +0 -0
package/style.js CHANGED
@@ -1,19 +1,21 @@
1
1
  import { layout as coreLayout } from '@nativescript/core/utils';
2
2
  import { cssUnits } from './units';
3
+ import { displayDensity, masonLayout } from './display-density';
3
4
  import { isMasonView_, style_ } from './symbols';
4
5
  import { pickFontFamily } from './fonts';
5
- import { masonEngine } from './windows-panel-helpers';
6
+ import { masonEngine } from './panel-helpers';
6
7
  import { reportCssDiagnostic } from './diagnostics';
7
8
  import { expandColorStops, resolveStopPositions } from './gradient-stops';
8
9
  import { encodeBoxShadows, parseBoxShadows } from './box-shadow';
9
10
  import { encodeCssFilter, parseCssFilter } from './css-filter';
10
11
  import { resolveCssColors } from './css-colors';
11
12
  import { evaluateCssMath, hasCssMathFunction, isCssMathFunction, substituteCssMath } from './css-math';
12
- import { encodeWindowsBackground, encodeWindowsBorderImage, encodeWindowsMask, WINDOWS_MASK_PROPERTIES } from './windows-mask';
13
+ import { encodeWindowsBackground, encodeWindowsBackgroundLayers, encodeWindowsBorderImage, encodeWindowsColorClip, encodeWindowsGradientBackground, hasCustomBackgroundBoxes, needsWindowsBackgroundLayers, encodeWindowsMask, WINDOWS_MASK_PROPERTIES } from './mask';
14
+ import { splitBackground } from './css-shorthands';
13
15
  import { Color, Length as CoreLength, PercentLength as CorePercentLength, Screen, knownFolders } from '@nativescript/core';
14
16
  // The Windows shell lays out in XAML DIPs, so its style buffer holds DIPs. Core's Windows density
15
17
  // is 1 until the window has a XamlRoot, so converting stored early styles unscaled and later ones scaled.
16
- const layout = __WINDOWS__ ? { ...coreLayout, getDisplayDensity: () => 1, toDevicePixels: (value) => value, toDeviceIndependentPixels: (value) => value } : coreLayout;
18
+ const layout = __WINDOWS__ ? { ...coreLayout, getDisplayDensity: () => 1, toDevicePixels: (value) => value, toDeviceIndependentPixels: (value) => value } : { ...coreLayout, ...masonLayout };
17
19
  var StyleKeys;
18
20
  (function (StyleKeys) {
19
21
  // <style-keys:offsets> generated from tools/scripts/style-keys/style-keys.schema, run `npm run gen:style-keys`
@@ -352,6 +354,7 @@ function unitToCssPx(n, unit, emBasis) {
352
354
  case 'vh':
353
355
  case 'vmin':
354
356
  case 'vmax': {
357
+ noteViewportUnit();
355
358
  const { viewportWidth: w, viewportHeight: h } = cssUnits;
356
359
  if (w <= 0 || h <= 0) {
357
360
  reportCssDiagnostic({ kind: 'unsupported-unit', name: 'length', value: `${n}${unit}`, detail: 'viewport size not known yet, resolved to 0' });
@@ -380,6 +383,19 @@ function evaluateLengthMath(value, emBasis) {
380
383
  export function resolveCssMathIn(value, emBasis) {
381
384
  return substituteCssMath(value, (n, unit) => unitToCssPx(n, unit, emBasis));
382
385
  }
386
+ const GRID_RELATIVE_LENGTH = /(^|[\s(,\]])([+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?)(rem|em|pt|vw|vh|vmin|vmax)(?=$|[\s),[])/gi;
387
+ /** A grid track list with relative units and math functions resolved to `px`, which the native parser reads. */
388
+ export function resolveGridTrackUnits(value, emBasis) {
389
+ if (!value) {
390
+ return value;
391
+ }
392
+ let out = hasCssMathFunction(value) ? resolveCssMathIn(value, emBasis) : value;
393
+ out = out.replace(GRID_RELATIVE_LENGTH, (_m, lead, n, unit) => `${lead}${finite(unitToCssPx(parseFloat(n), unit.toLowerCase(), emBasis) ?? 0)}px`);
394
+ if (hasCssMathFunction(out)) {
395
+ reportCssDiagnostic({ kind: 'not-implemented', name: 'grid track list', value, detail: 'a math function mixing % with a length, dropped by the track parser' });
396
+ }
397
+ return out;
398
+ }
383
399
  /**
384
400
  * A math function in a `<length-percentage>` as the buffer's type/value pair,
385
401
  * or undefined when `t` isn't one or doesn't resolve.
@@ -430,6 +446,7 @@ function tokenToDevicePx(token, raw, emBasis) {
430
446
  if (t.endsWith('pt'))
431
447
  return layout.toDevicePixels(n * PX_PER_PT);
432
448
  if (t.endsWith('vmin') || t.endsWith('vmax') || t.endsWith('vw') || t.endsWith('vh')) {
449
+ noteViewportUnit();
433
450
  if (cssUnits.viewportWidth <= 0 || cssUnits.viewportHeight <= 0) {
434
451
  reportCssDiagnostic({ kind: 'unsupported-unit', name: 'length', value: t, detail: 'viewport size not known yet, resolved to 0' });
435
452
  return 0;
@@ -538,6 +555,14 @@ export function cssLengthToDip(value, emBasis) {
538
555
  }
539
556
  return layout.toDeviceIndependentPixels(tokenToDevicePx(t, n, emBasis));
540
557
  }
558
+ const SIZING_KEYWORD = /^(min-content|max-content|fit-content|stretch|content|fit-content\(.+\))$/;
559
+ export function isSizingKeyword(value) {
560
+ return typeof value === 'string' && SIZING_KEYWORD.test(value.trim());
561
+ }
562
+ /** The keyword carried as the unit of a core length object, if any. */
563
+ function sizingKeywordOf(value) {
564
+ return isSizingKeyword(value?.unit) ? value.unit : undefined;
565
+ }
541
566
  function dimensionFromString(value, emBasis) {
542
567
  const t = value.trim();
543
568
  if (t === '' || t === 'auto') {
@@ -870,22 +895,32 @@ export function parseLinearGradientCss(value) {
870
895
  corner = parseGradientCorner(head);
871
896
  start = 1;
872
897
  }
898
+ const { colors, positions, lengths } = parseGradientStops(parts.slice(start));
899
+ if (colors.length < 1)
900
+ return null;
901
+ return { angle, ...(corner && { corner }), offsets: resolveStopPositions(positions), colors, interpolation, positions, ...(lengths && { lengths }) };
902
+ }
903
+ // A length stop needs the gradient line's length, which only the painter knows.
904
+ function parseGradientStops(stops) {
873
905
  const colors = [];
874
906
  const positions = [];
875
- for (const stop of expandColorStops(parts.slice(start))) {
876
- // A length position needs the gradient line's length, unknown here, so that stop is placed as
877
- // if it had none rather than dropped.
878
- const pos = /\s+(-?[\d.]+)(%|[a-z]+)\s*$/i.exec(stop);
907
+ const lengths = [];
908
+ let anyLength = false;
909
+ for (const stop of expandColorStops(stops)) {
910
+ const pos = /\s+(-?[\d.]+)(%|[a-z]+)?\s*$/i.exec(stop);
879
911
  const colorStr = pos ? stop.slice(0, pos.index).trim() : stop;
880
912
  const argb = normalizeColorValue(colorStr);
881
913
  if (argb == null)
882
914
  continue;
883
915
  colors.push(argb >>> 0);
884
- positions.push(pos && pos[2] === '%' ? parseFloat(pos[1]) / 100 : null);
885
- }
886
- if (colors.length < 1)
887
- return null;
888
- return { angle, ...(corner && { corner }), offsets: resolveStopPositions(positions), colors, interpolation };
916
+ const percent = pos?.[2] === '%';
917
+ const length = pos && !percent ? cssLengthToDip(pos[1] + (pos[2] ?? 'px')) : undefined;
918
+ positions.push(percent ? parseFloat(pos[1]) / 100 : null);
919
+ lengths.push(length ?? null);
920
+ if (length != null)
921
+ anyLength = true;
922
+ }
923
+ return { colors, positions, ...(anyLength && { lengths }) };
889
924
  }
890
925
  const RADIAL_GRADIENT_ARGS = /radial-gradient\s*\(([\s\S]*)\)\s*$/i;
891
926
  function positionFraction(token, axis) {
@@ -955,23 +990,17 @@ export function parseRadialGradientCss(value) {
955
990
  if (sizeKeyword)
956
991
  size = sizeKeyword[1].toLowerCase();
957
992
  }
993
+ const shape = head.replace(/\bat\s+.+$/i, '');
994
+ const circleLength = /\bcircle\b/i.test(shape) || /^\s*-?[\d.]+[a-z]*\s*$/i.test(shape) ? /(-?[\d.]+(?:px|r?em|pt|vw|vh)?)(?=\s|$)/i.exec(shape) : null;
995
+ const circleRadius = circleLength ? cssLengthToDip(/[a-z]$/i.test(circleLength[1]) ? circleLength[1] : circleLength[1] + 'px') : undefined;
996
+ const circle = /\bcircle\b/i.test(shape) || circleRadius != null ? ['closest-side', 'farthest-side', 'closest-corner', 'farthest-corner'].indexOf(size) : undefined;
958
997
  const sideX = size.startsWith('closest') ? Math.min(cx, 1 - cx) : Math.max(cx, 1 - cx);
959
998
  const sideY = size.startsWith('closest') ? Math.min(cy, 1 - cy) : Math.max(cy, 1 - cy);
960
999
  const corner = size.endsWith('corner') ? Math.SQRT2 : 1;
961
- const colors = [];
962
- const positions = [];
963
- for (const stop of expandColorStops(parts.slice(start))) {
964
- const pos = /\s+(-?[\d.]+)(%|[a-z]+)\s*$/i.exec(stop);
965
- const colorStr = pos ? stop.slice(0, pos.index).trim() : stop;
966
- const argb = normalizeColorValue(colorStr);
967
- if (argb == null)
968
- continue;
969
- colors.push(argb >>> 0);
970
- positions.push(pos && pos[2] === '%' ? parseFloat(pos[1]) / 100 : null);
971
- }
1000
+ const { colors, positions, lengths } = parseGradientStops(parts.slice(start));
972
1001
  if (colors.length < 1)
973
1002
  return null;
974
- return { cx, cy, rx: Math.max(sideX * corner, 0.001), ry: Math.max(sideY * corner, 0.001), offsets: resolveStopPositions(positions), colors, interpolation };
1003
+ return { cx, cy, rx: Math.max(sideX * corner, 0.001), ry: Math.max(sideY * corner, 0.001), offsets: resolveStopPositions(positions), colors, interpolation, positions, ...(lengths && { lengths }), ...(circle != null && { circle }), ...(circleRadius != null && { circleRadius }) };
975
1004
  }
976
1005
  export function backgroundFit(size) {
977
1006
  const t = (size ?? '').trim().toLowerCase();
@@ -1048,6 +1077,8 @@ function radiusCorners(t) {
1048
1077
  }
1049
1078
  let deviceScaleCache = 0;
1050
1079
  function deviceScale() {
1080
+ if (__ANDROID__)
1081
+ return displayDensity();
1051
1082
  return deviceScaleCache || (deviceScaleCache = Screen.mainScreen.scale);
1052
1083
  }
1053
1084
  function parseWindowsRadius(token, emBasis) {
@@ -1080,6 +1111,41 @@ export function parseBorderRadiusShorthand(value, emBasis) {
1080
1111
  return { tl: vals[0], tr: vals[1], br: vals[2], bl: vals[3] };
1081
1112
  }
1082
1113
  }
1114
+ const CORNER_SHAPE_KEYWORDS = { round: 1, squircle: 2, bevel: 0, scoop: -1, notch: -Infinity, square: Infinity };
1115
+ const SUPERELLIPSE = /^superellipse\(\s*(-?infinity|[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?)\s*\)$/;
1116
+ /** corner-shape as each corner's superellipse parameter K (TL TR BR BL), or null if a token is invalid. An empty value resets to round. */
1117
+ export function parseCornerShape(value) {
1118
+ const tokens = splitTopLevelSpaces(String(value ?? '')
1119
+ .trim()
1120
+ .toLowerCase());
1121
+ if (!tokens.length || (tokens.length === 1 && /^(initial|unset|revert|none)$/.test(tokens[0])))
1122
+ return [1, 1, 1, 1];
1123
+ if (tokens.length > 4)
1124
+ return null;
1125
+ const e = [];
1126
+ for (const token of tokens) {
1127
+ if (token in CORNER_SHAPE_KEYWORDS) {
1128
+ e.push(CORNER_SHAPE_KEYWORDS[token]);
1129
+ continue;
1130
+ }
1131
+ const m = SUPERELLIPSE.exec(token);
1132
+ if (!m)
1133
+ return null;
1134
+ e.push(m[1] === 'infinity' ? Infinity : m[1] === '-infinity' ? -Infinity : Number(m[1]));
1135
+ }
1136
+ switch (e.length) {
1137
+ case 1:
1138
+ return [e[0], e[0], e[0], e[0]];
1139
+ case 2:
1140
+ return [e[0], e[1], e[0], e[1]];
1141
+ case 3:
1142
+ return [e[0], e[1], e[2], e[1]];
1143
+ default:
1144
+ return [e[0], e[1], e[2], e[3]];
1145
+ }
1146
+ }
1147
+ const CORNER_SHAPE_KEYS = [StyleKeys.BORDER_RADIUS_TOP_LEFT_EXPONENT, StyleKeys.BORDER_RADIUS_TOP_RIGHT_EXPONENT, StyleKeys.BORDER_RADIUS_BOTTOM_RIGHT_EXPONENT, StyleKeys.BORDER_RADIUS_BOTTOM_LEFT_EXPONENT];
1148
+ const CORNER_SHAPE_LONGHANDS = { 'corner-shape-top-left': 0, 'corner-shape-top-right': 1, 'corner-shape-bottom-right': 2, 'corner-shape-bottom-left': 3 };
1083
1149
  // Split on top-level whitespace, keeping parenthesised groups (e.g. `rgba(0,0,0,.5)`) intact.
1084
1150
  function splitTopLevelSpaces(value) {
1085
1151
  const out = [];
@@ -1458,6 +1524,56 @@ export function cssColorToRgba(color) {
1458
1524
  }
1459
1525
  return `rgba(${color_.r}, ${color_.g}, ${color_.b}, ${+(color_.a / 255).toFixed(4)})`;
1460
1526
  }
1527
+ // Style writes that resolved a viewport unit, kept so a viewport change can write them again, as
1528
+ // a browser re-resolves vw/vh when the window resizes. Each setter is wrapped once below.
1529
+ const viewportWrites = new WeakMap();
1530
+ const viewportStyles = new Set();
1531
+ const writeTargets = [];
1532
+ const writeNames = [];
1533
+ const writeValues = [];
1534
+ let writeDepth = 0;
1535
+ const VIEWPORT_UNIT_TEXT = /\d(?:vw|vh|vmin|vmax)\b/i;
1536
+ /** Marks a style write in progress, so a viewport unit it resolves is remembered against `target[name] = value`. */
1537
+ export function beginStyleWrite(target, name, value) {
1538
+ viewportWrites.get(target)?.delete(name);
1539
+ writeTargets[writeDepth] = target;
1540
+ writeNames[writeDepth] = name;
1541
+ writeValues[writeDepth] = value;
1542
+ writeDepth++;
1543
+ // Android and iOS parse some CSS text natively, so the text itself marks a viewport unit.
1544
+ if (typeof value === 'string' && VIEWPORT_UNIT_TEXT.test(value))
1545
+ noteViewportUnit();
1546
+ }
1547
+ export function endStyleWrite() {
1548
+ writeDepth--;
1549
+ writeTargets[writeDepth] = writeValues[writeDepth] = undefined;
1550
+ }
1551
+ function noteViewportUnit() {
1552
+ if (!writeDepth)
1553
+ return;
1554
+ const target = writeTargets[writeDepth - 1];
1555
+ let writes = viewportWrites.get(target);
1556
+ if (!writes) {
1557
+ writes = new Map();
1558
+ viewportWrites.set(target, writes);
1559
+ viewportStyles.add(new WeakRef(target));
1560
+ }
1561
+ writes.set(writeNames[writeDepth - 1], writeValues[writeDepth - 1]);
1562
+ }
1563
+ /** Writes every style property that used vw/vh/vmin/vmax again, against the current viewport. */
1564
+ export function refreshViewportUnits() {
1565
+ for (const ref of viewportStyles) {
1566
+ const style = ref.deref();
1567
+ const writes = style && viewportWrites.get(style);
1568
+ if (!style || !writes || !writes.size) {
1569
+ viewportStyles.delete(ref);
1570
+ continue;
1571
+ }
1572
+ const keys = Array.from(writes.keys());
1573
+ for (let i = 0; i < keys.length; i++)
1574
+ style[keys[i]] = writes.get(keys[i]);
1575
+ }
1576
+ }
1461
1577
  export class Style {
1462
1578
  constructor() {
1463
1579
  this._bufferRequested = false;
@@ -1477,6 +1593,7 @@ export class Style {
1477
1593
  this._synced = false;
1478
1594
  this._windowsCss = new Map();
1479
1595
  this._windowsImageBackground = false;
1596
+ this._windowsBackgroundShorthand = false;
1480
1597
  this._windowsMaskSpec = '';
1481
1598
  }
1482
1599
  static fromView(view, nativeView) {
@@ -1692,11 +1809,36 @@ export class Style {
1692
1809
  const layer = splitTopLevelCommas(v)[0]?.trim() ?? '';
1693
1810
  const stopsOf = (g) => g.offsets.map((o, i) => o + ':' + (g.colors[i] >>> 0)).join(',');
1694
1811
  try {
1812
+ const longhands = this.windowsBackgroundLonghands(shorthand, v);
1813
+ if (longhands && (needsWindowsBackgroundLayers(longhands) || (ANY_GRADIENT.test(v) && this.windowsScrolls()))) {
1814
+ const spec = encodeWindowsBackgroundLayers(longhands, this.windowsMaskContext());
1815
+ if (spec) {
1816
+ this._windowsImageBackground = true;
1817
+ NativeScript.Mason.Css.SetBackgroundLayers(this.nativeView, spec);
1818
+ if (longhands.color)
1819
+ this.backgroundColor = longhands.color;
1820
+ return;
1821
+ }
1822
+ }
1695
1823
  const url = /url\(\s*(['"]?)(.*?)\1\s*\)/i.exec(layer);
1696
1824
  if (!url && this._windowsImageBackground) {
1697
1825
  this._windowsImageBackground = false;
1698
1826
  NativeScript.Mason.Css.SetBackgroundLayers(this.nativeView, '');
1699
1827
  }
1828
+ const boxes = this.windowsBackgroundBoxes(shorthand ? layer : '');
1829
+ const setLayers = (spec) => {
1830
+ if (!spec)
1831
+ return false;
1832
+ this._windowsImageBackground = true;
1833
+ NativeScript.Mason.Css.SetBackgroundLayers(this.nativeView, spec);
1834
+ return true;
1835
+ };
1836
+ // Only the layer painter places a background in a box other than the CSS defaults.
1837
+ if (ANY_GRADIENT.test(layer) && (hasCustomBackgroundBoxes(boxes) || /^(repeating-|conic-gradient)/i.test(layer) || this.windowsColorUnder() || /\d(px|r?em|pt|vw|vh)\b|\bcircle\b/i.test(layer))) {
1838
+ const ctx = this.windowsMaskContext();
1839
+ setLayers(encodeWindowsGradientBackground(layer, this._windowsBackgroundSize ?? '', this._windowsBackgroundPosition ?? '', this._windowsCss.get('background-repeat') ?? '', ctx, boxes));
1840
+ return;
1841
+ }
1700
1842
  if (/^radial-gradient/i.test(layer)) {
1701
1843
  const g = parseRadialGradientCss(layer);
1702
1844
  if (g)
@@ -1711,19 +1853,15 @@ export class Style {
1711
1853
  }
1712
1854
  if (url) {
1713
1855
  const rest = layer.slice(url.index + url[0].length).trim();
1714
- const keywords = /\b(no-repeat|repeat-x|repeat-y|repeat|space|round|scroll|fixed|local|border-box|padding-box|content-box)\b/gi;
1856
+ const keywords = /\b(no-repeat|repeat-x|repeat-y|repeat|space|round|scroll|fixed|local|border-box|padding-box|content-box|text)\b/gi;
1715
1857
  const [positionPart, sizePart] = rest.split('/').map((p) => p.replace(keywords, '').trim());
1716
1858
  const size = shorthand && sizePart ? sizePart.split(/\s+/).slice(0, 2).join(' ') : (this._windowsBackgroundSize ?? '');
1717
1859
  const position = shorthand && positionPart ? positionPart : (this._windowsBackgroundPosition ?? '');
1718
1860
  const repeatKeywords = shorthand ? (rest.match(/\b(no-repeat|repeat-x|repeat-y|repeat|space|round)\b/gi) ?? []).join(' ') : '';
1719
1861
  const repeat = repeatKeywords || (this._windowsCss.get('background-repeat') ?? '');
1720
1862
  // Painted natively over background-color (CssMask.h), which an ImageBrush would replace.
1721
- const spec = encodeWindowsBackground(url[2], size, position, repeat, this.windowsMaskContext());
1722
- if (spec) {
1723
- this._windowsImageBackground = true;
1724
- NativeScript.Mason.Css.SetBackgroundLayers(this.nativeView, spec);
1863
+ if (setLayers(encodeWindowsBackground(url[2], size, position, repeat, this.windowsMaskContext(), boxes)))
1725
1864
  return;
1726
- }
1727
1865
  let source = url[2];
1728
1866
  if (source.startsWith('~/'))
1729
1867
  source = source.replace('~/', knownFolders.currentApp().path + '/');
@@ -1734,12 +1872,60 @@ export class Style {
1734
1872
  }
1735
1873
  if (!ANY_GRADIENT.test(layer)) {
1736
1874
  NativeScript.Mason.Css.ClearBackground(this.nativeView);
1737
- if (shorthand && v.length && v.toLowerCase() !== 'none')
1738
- this.backgroundColor = v;
1875
+ const color = v.replace(/\b(border-box|padding-box|content-box|text)\b/gi, '').trim();
1876
+ if (shorthand && color.length && color.toLowerCase() !== 'none')
1877
+ this.backgroundColor = color;
1878
+ if (boxes.clip && hasCustomBackgroundBoxes({ clip: boxes.clip }))
1879
+ setLayers(encodeWindowsColorClip(boxes.clip, this.windowsMaskContext()));
1739
1880
  }
1740
1881
  }
1741
1882
  catch (_) { }
1742
1883
  }
1884
+ windowsScrolls() {
1885
+ if (!this.style_view)
1886
+ return false;
1887
+ const x = getInt8(this.style_view, StyleKeys.OVERFLOW_X);
1888
+ const y = getInt8(this.style_view, StyleKeys.OVERFLOW_Y);
1889
+ return x === 2 || x === 4 || y === 2 || y === 4;
1890
+ }
1891
+ windowsColorUnder() {
1892
+ return !!this.style_view && getUint32(this.style_view, StyleKeys.BACKGROUND_COLOR) >>> 24 > 0;
1893
+ }
1894
+ windowsReapplyGradient() {
1895
+ if (ANY_GRADIENT.test(this._windowsBackground ?? ''))
1896
+ this.applyWindowsBackground(this._windowsBackgroundShorthand);
1897
+ }
1898
+ windowsBackgroundLonghands(shorthand, value) {
1899
+ const css = this._windowsCss;
1900
+ const blend = css.get('background-blend-mode');
1901
+ if (!shorthand) {
1902
+ return { image: value, size: this._windowsBackgroundSize, position: this._windowsBackgroundPosition, repeat: css.get('background-repeat'), origin: css.get('background-origin'), clip: css.get('background-clip'), attachment: css.get('background-attachment'), blend };
1903
+ }
1904
+ let parts;
1905
+ try {
1906
+ parts = splitBackground(value);
1907
+ }
1908
+ catch (_) {
1909
+ return null;
1910
+ }
1911
+ const text = (part) => (typeof part === 'string' ? part : undefined);
1912
+ const [color, image, repeat, position, size, clip, origin, attachment] = parts.map(text);
1913
+ if (!image)
1914
+ return null;
1915
+ return { image, size, position, repeat, origin, clip, attachment, blend, color };
1916
+ }
1917
+ // background-origin and background-clip: the shorthand's box keywords (origin, then clip), else the longhands.
1918
+ // `text` is a clip only; url() and gradient arguments are skipped so a file name can't match it.
1919
+ windowsBackgroundBoxes(shorthandLayer) {
1920
+ const bare = shorthandLayer.replace(/[\w-]+\((?:[^()]|\([^()]*\))*\)/g, ' ');
1921
+ const keywords = bare.match(/\b(border-box|padding-box|content-box|text)\b/gi) ?? [];
1922
+ if (keywords.length) {
1923
+ const boxes = keywords.filter((k) => k.toLowerCase() !== 'text');
1924
+ const text = boxes.length < keywords.length;
1925
+ return { origin: boxes[0], clip: text ? 'text' : (boxes[1] ?? boxes[0]) };
1926
+ }
1927
+ return { origin: this._windowsCss.get('background-origin'), clip: this._windowsCss.get('background-clip') };
1928
+ }
1743
1929
  windowsMaskContext() {
1744
1930
  return {
1745
1931
  length: (token) => cssLengthToDip(token, this.emBasisFor(token)),
@@ -1798,11 +1984,16 @@ export class Style {
1798
1984
  // it lets VisualApply repaint the color.
1799
1985
  if (name === 'background' || name === 'background-image') {
1800
1986
  this._windowsBackground = typeof value === 'string' ? value : String(value ?? '');
1987
+ this._windowsBackgroundShorthand = name === 'background';
1801
1988
  this.applyWindowsBackground(name === 'background');
1802
1989
  return;
1803
1990
  }
1804
- if (name === 'background-repeat') {
1805
- if (/url\(/i.test(this._windowsBackground ?? ''))
1991
+ if (name === 'background-clip' || name === 'background-origin') {
1992
+ this.applyWindowsBackground(false);
1993
+ return;
1994
+ }
1995
+ if (name === 'background-repeat' || name === 'background-attachment' || name === 'background-blend-mode') {
1996
+ if (/url\(|gradient/i.test(this._windowsBackground ?? ''))
1806
1997
  this.applyWindowsBackground(false);
1807
1998
  return;
1808
1999
  }
@@ -1811,7 +2002,7 @@ export class Style {
1811
2002
  this._windowsBackgroundSize = String(value ?? '');
1812
2003
  else
1813
2004
  this._windowsBackgroundPosition = String(value ?? '');
1814
- if (/url\(/i.test(this._windowsBackground ?? ''))
2005
+ if (/url\(|gradient/i.test(this._windowsBackground ?? ''))
1815
2006
  this.applyWindowsBackground(false);
1816
2007
  return;
1817
2008
  }
@@ -1873,6 +2064,20 @@ export class Style {
1873
2064
  this.commitState(StateKeys.BORDER_RADIUS);
1874
2065
  return;
1875
2066
  }
2067
+ if (name === 'corner-shape' || name in CORNER_SHAPE_LONGHANDS) {
2068
+ const text = typeof value === 'string' ? value : '';
2069
+ const e = parseCornerShape(text);
2070
+ if (!e || (name !== 'corner-shape' && splitTopLevelSpaces(text.trim()).length > 1))
2071
+ return;
2072
+ this.prepareMut();
2073
+ if (name === 'corner-shape')
2074
+ for (let i = 0; i < 4; i++)
2075
+ setFloat32(this.style_view, CORNER_SHAPE_KEYS[i], e[i]);
2076
+ else
2077
+ setFloat32(this.style_view, CORNER_SHAPE_KEYS[CORNER_SHAPE_LONGHANDS[name]], e[0]);
2078
+ this.commitState(StateKeys.BORDER_RADIUS);
2079
+ return;
2080
+ }
1876
2081
  if (name === 'border' || name === 'border-top' || name === 'border-right' || name === 'border-bottom' || name === 'border-left') {
1877
2082
  const p = parseBorderShorthand(value, this.emBasisFor(value));
1878
2083
  let style = p.style;
@@ -2125,7 +2330,7 @@ export class Style {
2125
2330
  if (!this.style_view || getInt8(this.style_view, StyleKeys.FONT_SIZE_STATE) !== 1) {
2126
2331
  return this.parentEmBasis();
2127
2332
  }
2128
- const own = getInt32(this.style_view, StyleKeys.FONT_SIZE);
2333
+ const own = getFloat32(this.style_view, StyleKeys.FONT_SIZE);
2129
2334
  if (own <= 0) {
2130
2335
  return this.parentEmBasis();
2131
2336
  }
@@ -2252,7 +2457,7 @@ export class Style {
2252
2457
  return 16;
2253
2458
  }
2254
2459
  const type = getUint8(this.style_view, StyleKeys.FONT_SIZE_TYPE);
2255
- const value = getInt32(this.style_view, StyleKeys.FONT_SIZE);
2460
+ const value = getFloat32(this.style_view, StyleKeys.FONT_SIZE);
2256
2461
  if (type === 1) {
2257
2462
  return `${value / 100}%`;
2258
2463
  }
@@ -2298,7 +2503,7 @@ export class Style {
2298
2503
  else if (isDevicePixelToken(t)) {
2299
2504
  resolved = layout.toDeviceIndependentPixels(n);
2300
2505
  }
2301
- setInt32(this.style_view, StyleKeys.FONT_SIZE, resolved);
2506
+ setFloat32(this.style_view, StyleKeys.FONT_SIZE, resolved);
2302
2507
  setInt8(this.style_view, StyleKeys.FONT_SIZE_STATE, 1);
2303
2508
  setInt8(this.style_view, StyleKeys.FONT_SIZE_TYPE, isPercent ? 1 : 0);
2304
2509
  this.commitState(StateKeys.FONT_SIZE);
@@ -2306,7 +2511,7 @@ export class Style {
2306
2511
  }
2307
2512
  case 'number':
2308
2513
  this.prepareMut();
2309
- setInt32(this.style_view, StyleKeys.FONT_SIZE, value);
2514
+ setFloat32(this.style_view, StyleKeys.FONT_SIZE, value);
2310
2515
  setInt8(this.style_view, StyleKeys.FONT_SIZE_STATE, 1);
2311
2516
  setInt8(this.style_view, StyleKeys.FONT_SIZE_TYPE, 0);
2312
2517
  this.commitState(StateKeys.FONT_SIZE);
@@ -2315,21 +2520,21 @@ export class Style {
2315
2520
  switch (value.unit) {
2316
2521
  case 'dip':
2317
2522
  this.prepareMut();
2318
- setInt32(this.style_view, StyleKeys.FONT_SIZE, finite(value.value));
2523
+ setFloat32(this.style_view, StyleKeys.FONT_SIZE, finite(value.value));
2319
2524
  setInt8(this.style_view, StyleKeys.FONT_SIZE_STATE, 1);
2320
2525
  setInt8(this.style_view, StyleKeys.FONT_SIZE_TYPE, 0);
2321
2526
  this.commitState(StateKeys.FONT_SIZE);
2322
2527
  break;
2323
2528
  case 'px':
2324
2529
  this.prepareMut();
2325
- setInt32(this.style_view, StyleKeys.FONT_SIZE, finite(value.value));
2530
+ setFloat32(this.style_view, StyleKeys.FONT_SIZE, finite(value.value));
2326
2531
  setInt8(this.style_view, StyleKeys.FONT_SIZE_STATE, 1);
2327
2532
  setInt8(this.style_view, StyleKeys.FONT_SIZE_TYPE, 0);
2328
2533
  this.commitState(StateKeys.FONT_SIZE);
2329
2534
  break;
2330
2535
  case '%':
2331
2536
  this.prepareMut();
2332
- setInt32(this.style_view, StyleKeys.FONT_SIZE, value.value * 100);
2537
+ setFloat32(this.style_view, StyleKeys.FONT_SIZE, value.value * 100);
2333
2538
  setInt8(this.style_view, StyleKeys.FONT_SIZE_STATE, 1);
2334
2539
  setInt8(this.style_view, StyleKeys.FONT_SIZE_TYPE, 1);
2335
2540
  this.commitState(StateKeys.FONT_SIZE);
@@ -2492,6 +2697,8 @@ export class Style {
2492
2697
  setInt8(this.style_view, StyleKeys.BACKGROUND_COLOR_STATE, 1);
2493
2698
  setInt8(this.style_view, StyleKeys.BACKGROUND_COLOR_TYPE, 0);
2494
2699
  this.commitState(StateKeys.BACKGROUND_COLOR);
2700
+ if (__WINDOWS__ && !this._windowsImageBackground && normalized >>> 24 > 0)
2701
+ this.windowsReapplyGradient();
2495
2702
  }
2496
2703
  get textWrap() {
2497
2704
  if (!this.style_view) {
@@ -2510,6 +2717,8 @@ export class Style {
2510
2717
  wrap = 1;
2511
2718
  break;
2512
2719
  case 'wrap':
2720
+ case 'pretty':
2721
+ case 'stable':
2513
2722
  wrap = 0;
2514
2723
  break;
2515
2724
  case 'balance':
@@ -2683,7 +2892,7 @@ export class Style {
2683
2892
  get flexWrap() {
2684
2893
  switch (getInt8(this.style_view, StyleKeys.FLEX_WRAP)) {
2685
2894
  case 0:
2686
- return 'no-wrap';
2895
+ return 'nowrap';
2687
2896
  case 1:
2688
2897
  return 'wrap';
2689
2898
  case 2:
@@ -2697,6 +2906,7 @@ export class Style {
2697
2906
  set flexWrap(value) {
2698
2907
  let wrap = -1;
2699
2908
  switch (value) {
2909
+ case 'nowrap':
2700
2910
  case 'no-wrap':
2701
2911
  wrap = 0;
2702
2912
  break;
@@ -2849,8 +3059,18 @@ export class Style {
2849
3059
  setInt8(this.style_view, StyleKeys.WIDTH_TYPE, 2);
2850
3060
  setFloat32(this.style_view, StyleKeys.WIDTH_VALUE, value.value);
2851
3061
  break;
2852
- default:
2853
- return;
3062
+ default: {
3063
+ // A sizing keyword routed through core (see sizingKeywordLength in properties.ts).
3064
+ const keyword = sizingKeywordOf(value);
3065
+ if (!keyword) {
3066
+ return;
3067
+ }
3068
+ this.prepareMut();
3069
+ const dim = dimensionFromString(keyword);
3070
+ setInt8(this.style_view, StyleKeys.WIDTH_TYPE, dim.type);
3071
+ setFloat32(this.style_view, StyleKeys.WIDTH_VALUE, dim.value);
3072
+ break;
3073
+ }
2854
3074
  }
2855
3075
  break;
2856
3076
  default:
@@ -2894,8 +3114,18 @@ export class Style {
2894
3114
  setInt8(this.style_view, StyleKeys.HEIGHT_TYPE, 2);
2895
3115
  setFloat32(this.style_view, StyleKeys.HEIGHT_VALUE, value.value);
2896
3116
  break;
2897
- default:
2898
- return;
3117
+ default: {
3118
+ // A sizing keyword routed through core (see sizingKeywordLength in properties.ts).
3119
+ const keyword = sizingKeywordOf(value);
3120
+ if (!keyword) {
3121
+ return;
3122
+ }
3123
+ this.prepareMut();
3124
+ const dim = dimensionFromString(keyword);
3125
+ setInt8(this.style_view, StyleKeys.HEIGHT_TYPE, dim.type);
3126
+ setFloat32(this.style_view, StyleKeys.HEIGHT_VALUE, dim.value);
3127
+ break;
3128
+ }
2899
3129
  }
2900
3130
  break;
2901
3131
  default:
@@ -4312,6 +4542,7 @@ export class Style {
4312
4542
  }
4313
4543
  // A bare number can't marshal over JNI into the native String setter.
4314
4544
  value = value == null ? '' : String(value);
4545
+ value = resolveGridTrackUnits(value, this.emBasisFor(value));
4315
4546
  if (__ANDROID__) {
4316
4547
  nodeHelper().setGridAutoRows(this.nativeView, value);
4317
4548
  }
@@ -4340,6 +4571,7 @@ export class Style {
4340
4571
  }
4341
4572
  // See gridAutoRows above.
4342
4573
  value = value == null ? '' : String(value);
4574
+ value = resolveGridTrackUnits(value, this.emBasisFor(value));
4343
4575
  if (__ANDROID__) {
4344
4576
  nodeHelper().setGridAutoColumns(this.nativeView, value);
4345
4577
  }
@@ -4363,7 +4595,7 @@ export class Style {
4363
4595
  }
4364
4596
  }
4365
4597
  set gridAutoFlow(value) {
4366
- const v = { row: 0, column: 1, 'row dense': 2, 'column dense': 3 }[value];
4598
+ const v = gridAutoFlowFromString(value);
4367
4599
  if (v !== undefined) {
4368
4600
  this.prepareMut();
4369
4601
  setInt8(this.style_view, StyleKeys.GRID_AUTO_FLOW, v);
@@ -4584,6 +4816,7 @@ export class Style {
4584
4816
  }
4585
4817
  // null clears the template; also guards against a bare number (see gridAutoRows above).
4586
4818
  value = value == null ? '' : String(value);
4819
+ value = resolveGridTrackUnits(value, this.emBasisFor(value));
4587
4820
  if (__ANDROID__) {
4588
4821
  nodeHelper().setGridTemplateRows(this.nativeView, value);
4589
4822
  }
@@ -4624,6 +4857,7 @@ export class Style {
4624
4857
  }
4625
4858
  // null clears the template; also guards against a bare number (see gridAutoRows above).
4626
4859
  value = value == null ? '' : String(value);
4860
+ value = resolveGridTrackUnits(value, this.emBasisFor(value));
4627
4861
  if (__ANDROID__) {
4628
4862
  nodeHelper().setGridTemplateColumns(this.nativeView, value);
4629
4863
  }
@@ -4696,6 +4930,8 @@ export class Style {
4696
4930
  }
4697
4931
  }
4698
4932
  this.commitState(StateKeys.OVERFLOW);
4933
+ if (__WINDOWS__)
4934
+ this.windowsReapplyGradient();
4699
4935
  }
4700
4936
  get overflowX() {
4701
4937
  switch (getInt8(this.style_view, StyleKeys.OVERFLOW_X)) {
@@ -4713,6 +4949,8 @@ export class Style {
4713
4949
  this.prepareMut();
4714
4950
  setInt8(this.style_view, StyleKeys.OVERFLOW_X, v);
4715
4951
  this.commitState(StateKeys.OVERFLOW_X);
4952
+ if (__WINDOWS__)
4953
+ this.windowsReapplyGradient();
4716
4954
  }
4717
4955
  }
4718
4956
  get overflowY() {
@@ -4735,6 +4973,8 @@ export class Style {
4735
4973
  this.prepareMut();
4736
4974
  setInt8(this.style_view, StyleKeys.OVERFLOW_Y, v);
4737
4975
  this.commitState(StateKeys.OVERFLOW_Y);
4976
+ if (__WINDOWS__)
4977
+ this.windowsReapplyGradient();
4738
4978
  }
4739
4979
  }
4740
4980
  get flexGrow() {
@@ -4787,8 +5027,9 @@ export class Style {
4787
5027
  }
4788
5028
  set letterSpacing(value) {
4789
5029
  if (typeof value === 'string') {
5030
+ const t = value.trim();
4790
5031
  this.prepareMut();
4791
- setFloat32(this.style_view, StyleKeys.LETTER_SPACING, tokenToDevicePx(value, parseFloat(value) || 0));
5032
+ setFloat32(this.style_view, StyleKeys.LETTER_SPACING, t === 'normal' ? 0 : finite(tokenToDevicePx(t, parseFloat(t) || 0, this.emBasisFor(t))));
4792
5033
  setUint8(this.style_view, StyleKeys.LETTER_SPACING_STATE, 1);
4793
5034
  this.commitState(StateKeys.LETTER_SPACING);
4794
5035
  }
@@ -4821,12 +5062,18 @@ export class Style {
4821
5062
  set lineHeight(value) {
4822
5063
  if (typeof value === 'string') {
4823
5064
  const t = value.trim();
5065
+ if (t === 'normal') {
5066
+ this.prepareMut();
5067
+ setUint8(this.style_view, StyleKeys.LINE_HEIGHT_STATE, 0);
5068
+ this.commitState(StateKeys.LINE_HEIGHT);
5069
+ return;
5070
+ }
4824
5071
  // A unitless line-height is a multiplier (`line-height: 1.5`), not a
4825
5072
  // length — TYPE 0 means "multiply by the resolved font size".
4826
5073
  const unitless = /^-?[\d.]+$/.test(t);
4827
5074
  this.prepareMut();
4828
5075
  // An absolute line-height is stored in CSS px (iOS points, Android dip), as the number path.
4829
- setFloat32(this.style_view, StyleKeys.LINE_HEIGHT, unitless ? finite(parseFloat(t) || 0) : layout.toDeviceIndependentPixels(tokenToDevicePx(t, parseFloat(t) || 0)));
5076
+ setFloat32(this.style_view, StyleKeys.LINE_HEIGHT, unitless ? finite(parseFloat(t) || 0) : finite(layout.toDeviceIndependentPixels(tokenToDevicePx(t, parseFloat(t) || 0, this.emBasisFor(t)))));
4830
5077
  setUint8(this.style_view, StyleKeys.LINE_HEIGHT_STATE, 1);
4831
5078
  setUint8(this.style_view, StyleKeys.LINE_HEIGHT_TYPE, unitless ? 0 : 1);
4832
5079
  this.commitState(StateKeys.LINE_HEIGHT);
@@ -4902,7 +5149,7 @@ export class Style {
4902
5149
  // clip ?
4903
5150
  return 'start';
4904
5151
  }
4905
- const type = getInt32(this.style_view, StyleKeys.TEXT_ALIGN);
5152
+ const type = getInt8(this.style_view, StyleKeys.TEXT_ALIGN);
4906
5153
  switch (type) {
4907
5154
  case 0:
4908
5155
  // auto
@@ -4952,7 +5199,7 @@ export class Style {
4952
5199
  }
4953
5200
  if (align !== -1) {
4954
5201
  this.prepareMut();
4955
- setInt32(this.style_view, StyleKeys.TEXT_ALIGN, align);
5202
+ setInt8(this.style_view, StyleKeys.TEXT_ALIGN, align);
4956
5203
  setInt8(this.style_view, StyleKeys.TEXT_ALIGN_STATE, 1);
4957
5204
  this.commitState(StateKeys.TEXT_ALIGN);
4958
5205
  }
@@ -6303,6 +6550,21 @@ export class Style {
6303
6550
  setFloat32(this.style_view, StyleKeys.TRANSFORM_ORIGIN_Y_VALUE, parsed.y);
6304
6551
  setUint8(this.style_view, StyleKeys.TRANSFORM_ORIGIN_STATE, 1);
6305
6552
  this.commitState(StateKeys.TRANSFORM_ORIGIN);
6553
+ // Windows applies the origin with the transform, natively it isn't read from the buffer.
6554
+ if (__WINDOWS__)
6555
+ this.view?._applyWindowsTransform?.();
6556
+ }
6557
+ /** transform-origin as fractions of a `width` x `height` box, or null when it isn't set. */
6558
+ transformOriginFraction(width, height) {
6559
+ if (!this.style_view || !getUint8(this.style_view, StyleKeys.TRANSFORM_ORIGIN_STATE))
6560
+ return null;
6561
+ const side = (typeKey, valueKey, size) => {
6562
+ const value = getFloat32(this.style_view, valueKey);
6563
+ if (getUint8(this.style_view, typeKey) === 1)
6564
+ return value / 100;
6565
+ return size > 0 ? layout.toDeviceIndependentPixels(value) / size : 0;
6566
+ };
6567
+ return { x: side(StyleKeys.TRANSFORM_ORIGIN_X_TYPE, StyleKeys.TRANSFORM_ORIGIN_X_VALUE, width), y: side(StyleKeys.TRANSFORM_ORIGIN_Y_TYPE, StyleKeys.TRANSFORM_ORIGIN_Y_VALUE, height) };
6306
6568
  }
6307
6569
  set 'transform-origin'(value) {
6308
6570
  this.transformOrigin = value;
@@ -6852,4 +7114,54 @@ export class Style {
6852
7114
  };
6853
7115
  }
6854
7116
  }
7117
+ {
7118
+ const proto = Style.prototype;
7119
+ const names = Object.getOwnPropertyNames(proto);
7120
+ for (let i = 0; i < names.length; i++) {
7121
+ const name = names[i];
7122
+ const descriptor = Object.getOwnPropertyDescriptor(proto, name);
7123
+ const set = descriptor?.set;
7124
+ if (!set)
7125
+ continue;
7126
+ Object.defineProperty(proto, name, {
7127
+ ...descriptor,
7128
+ set(value) {
7129
+ beginStyleWrite(this, name, value);
7130
+ try {
7131
+ set.call(this, value);
7132
+ }
7133
+ finally {
7134
+ endStyleWrite();
7135
+ }
7136
+ },
7137
+ });
7138
+ }
7139
+ }
7140
+ /** `grid-auto-flow` as its buffer value: `row`/`column` and `dense`, in either order. */
7141
+ export function gridAutoFlowFromString(value) {
7142
+ if (typeof value !== 'string') {
7143
+ return undefined;
7144
+ }
7145
+ const tokens = value.trim().toLowerCase().split(/\s+/);
7146
+ if (tokens.length === 0 || tokens.length > 2 || new Set(tokens).size !== tokens.length) {
7147
+ return undefined;
7148
+ }
7149
+ let column = false;
7150
+ let dense = false;
7151
+ for (const token of tokens) {
7152
+ if (token === 'dense') {
7153
+ dense = true;
7154
+ }
7155
+ else if (token === 'column') {
7156
+ column = true;
7157
+ }
7158
+ else if (token !== 'row') {
7159
+ return undefined;
7160
+ }
7161
+ }
7162
+ if (tokens.length === 2 && !dense) {
7163
+ return undefined;
7164
+ }
7165
+ return (column ? 1 : 0) + (dense ? 2 : 0);
7166
+ }
6855
7167
  //# sourceMappingURL=style.js.map