@triniwiz/nativescript-masonkit 1.0.0-beta.107 → 1.0.0-beta.109

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 (134) hide show
  1. package/box-shadow.d.ts +10 -0
  2. package/box-shadow.js +49 -0
  3. package/box-shadow.js.map +1 -0
  4. package/button/index.windows.js +0 -2
  5. package/button/index.windows.js.map +1 -1
  6. package/common.d.ts +36 -9
  7. package/common.js +674 -202
  8. package/common.js.map +1 -1
  9. package/css-filter.d.ts +17 -0
  10. package/css-filter.js +141 -0
  11. package/css-filter.js.map +1 -0
  12. package/css-transform.d.ts +6 -0
  13. package/css-transform.js +101 -0
  14. package/css-transform.js.map +1 -0
  15. package/html-windows.d.ts +1 -0
  16. package/html-windows.js +163 -0
  17. package/html-windows.js.map +1 -0
  18. package/html.d.ts +8 -0
  19. package/html.js +134 -0
  20. package/html.js.map +1 -0
  21. package/img/index.ios.js +1 -1
  22. package/img/index.ios.js.map +1 -1
  23. package/index.d.ts +6 -4
  24. package/index.windows.d.ts +2 -0
  25. package/index.windows.js +2 -0
  26. package/index.windows.js.map +1 -1
  27. package/input/common.d.ts +16 -0
  28. package/input/common.js +45 -3
  29. package/input/common.js.map +1 -1
  30. package/input/index.android.d.ts +8 -3
  31. package/input/index.android.js +24 -7
  32. package/input/index.android.js.map +1 -1
  33. package/input/index.ios.d.ts +7 -3
  34. package/input/index.ios.js +19 -8
  35. package/input/index.ios.js.map +1 -1
  36. package/input/index.windows.d.ts +14 -2
  37. package/input/index.windows.js +143 -4
  38. package/input/index.windows.js.map +1 -1
  39. package/li/index.ios.js +1 -1
  40. package/li/index.ios.js.map +1 -1
  41. package/li/index.windows.js +4 -2
  42. package/li/index.windows.js.map +1 -1
  43. package/list/index.ios.js +2 -2
  44. package/list/index.ios.js.map +1 -1
  45. package/list/index.windows.d.ts +5 -2
  46. package/list/index.windows.js +26 -4
  47. package/list/index.windows.js.map +1 -1
  48. package/package.json +1 -1
  49. package/platforms/android/masonkit-release.aar +0 -0
  50. package/platforms/ios/Mason.xcframework/Info.plist +6 -6
  51. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Headers/Mason-Swift.h +16 -1
  52. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Mason +0 -0
  53. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
  54. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.abi.json +1086 -234
  55. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.private.swiftinterface +29 -0
  56. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  57. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.swiftinterface +29 -0
  58. package/platforms/ios/Mason.xcframework/ios-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  59. package/platforms/ios/Mason.xcframework/ios-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8873 -8709
  60. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Headers/Mason-Swift.h +32 -2
  61. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Mason +0 -0
  62. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo +0 -0
  63. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo +0 -0
  64. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.abi.json +1086 -234
  65. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +29 -0
  66. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  67. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.swiftinterface +29 -0
  68. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.abi.json +1086 -234
  69. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +29 -0
  70. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  71. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +29 -0
  72. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/_CodeSignature/CodeResources +26 -26
  73. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  74. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8867 -8703
  75. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/x86_64/Mason.yml +8466 -8306
  76. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Headers/Mason-Swift.h +16 -1
  77. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Mason +0 -0
  78. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-xros.swiftsourceinfo +0 -0
  79. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.abi.json +1086 -234
  80. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.private.swiftinterface +29 -0
  81. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.swiftdoc +0 -0
  82. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.swiftinterface +29 -0
  83. package/platforms/ios/Mason.xcframework/xros-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  84. package/platforms/ios/Mason.xcframework/xros-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8365 -8202
  85. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Headers/Mason-Swift.h +16 -1
  86. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Mason +0 -0
  87. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-xros-simulator.swiftsourceinfo +0 -0
  88. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.abi.json +1086 -234
  89. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.private.swiftinterface +29 -0
  90. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.swiftdoc +0 -0
  91. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.swiftinterface +29 -0
  92. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/_CodeSignature/CodeResources +14 -14
  93. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  94. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8364 -8202
  95. package/platforms/windows/arm64/NativeScript.Mason.dll +0 -0
  96. package/platforms/windows/arm64/NativeScript.Mason.winmd +0 -0
  97. package/platforms/windows/x64/NativeScript.Mason.dll +0 -0
  98. package/platforms/windows/x64/NativeScript.Mason.winmd +0 -0
  99. package/properties.js +87 -1
  100. package/properties.js.map +1 -1
  101. package/scroll/index.android.js +3 -1
  102. package/scroll/index.android.js.map +1 -1
  103. package/scroll/index.ios.js +4 -2
  104. package/scroll/index.ios.js.map +1 -1
  105. package/scroll/index.windows.js +4 -2
  106. package/scroll/index.windows.js.map +1 -1
  107. package/style.d.ts +57 -8
  108. package/style.js +542 -262
  109. package/style.js.map +1 -1
  110. package/symbols.d.ts +4 -0
  111. package/symbols.js +6 -2
  112. package/symbols.js.map +1 -1
  113. package/text/index.ios.js +1 -1
  114. package/text/index.ios.js.map +1 -1
  115. package/text/index.windows.d.ts +3 -0
  116. package/text/index.windows.js +39 -10
  117. package/text/index.windows.js.map +1 -1
  118. package/textarea/index.ios.js +1 -1
  119. package/textarea/index.ios.js.map +1 -1
  120. package/textarea/index.windows.d.ts +2 -0
  121. package/textarea/index.windows.js +5 -1
  122. package/textarea/index.windows.js.map +1 -1
  123. package/typings/android.d.ts +3 -0
  124. package/typings/objc!Mason.d.ts +4 -0
  125. package/typings/windows.d.ts +29 -1
  126. package/view/index.windows.js +4 -2
  127. package/view/index.windows.js.map +1 -1
  128. package/vue/src/element-registry.d.ts.map +1 -1
  129. package/vue/src/element-registry.js +4 -1
  130. package/vue/src/element-registry.js.map +1 -1
  131. package/vue/src/v-model.d.ts +27 -0
  132. package/vue/src/v-model.d.ts.map +1 -0
  133. package/vue/src/v-model.js +70 -0
  134. package/vue/src/v-model.js.map +1 -0
package/common.js CHANGED
@@ -1,7 +1,7 @@
1
1
  var _a, _b, _c, _d;
2
2
  /* eslint-disable @typescript-eslint/no-explicit-any */
3
3
  /* eslint-disable @typescript-eslint/ban-ts-comment */
4
- import { CustomLayoutView, Utils, View as NSView, getViewById, Property, widthProperty, heightProperty, marginLeftProperty, marginRightProperty, marginTopProperty, marginBottomProperty, minWidthProperty, minHeightProperty, fontSizeProperty, fontWeightProperty, fontStyleProperty, colorProperty, Color, lineHeightProperty, letterSpacingProperty, textAlignmentProperty, textDecorationProperty, borderLeftWidthProperty, borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, backgroundColorProperty, paddingLeftProperty, paddingRightProperty, paddingTopProperty, paddingBottomProperty, zIndexProperty, PseudoClassHandler } from '@nativescript/core';
4
+ import { CustomLayoutView, Utils, View as NSView, getViewById, Property, widthProperty, heightProperty, marginLeftProperty, marginRightProperty, marginTopProperty, marginBottomProperty, minWidthProperty, minHeightProperty, fontSizeProperty, fontWeightProperty, fontStyleProperty, colorProperty, Color, lineHeightProperty, letterSpacingProperty, textAlignmentProperty, textDecorationProperty, borderLeftWidthProperty, borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, backgroundColorProperty, paddingLeftProperty, paddingRightProperty, paddingTopProperty, paddingBottomProperty, zIndexProperty, directionProperty, PseudoClassHandler, } from '@nativescript/core';
5
5
  import { alignItemsProperty, alignSelfProperty, flexDirectionProperty, flexGrowProperty, flexShrinkProperty, flexWrapProperty, justifyContentProperty } from '@nativescript/core/ui/layouts/flexbox-layout';
6
6
  // The per-corner radius and per-side colour longhands core's `border-radius`
7
7
  // / `border-color` shorthands expand into. They live in the styling module
@@ -9,11 +9,13 @@ import { alignItemsProperty, alignSelfProperty, flexDirectionProperty, flexGrowP
9
9
  import { fontInternalProperty, backgroundInternalProperty, borderTopLeftRadiusProperty, borderTopRightRadiusProperty, borderBottomRightRadiusProperty, borderBottomLeftRadiusProperty, borderTopColorProperty, borderRightColorProperty, borderBottomColorProperty, borderLeftColorProperty } from '@nativescript/core/ui/styling/style-properties';
10
10
  import { _forceStyleUpdate } from './utils';
11
11
  import { borderRadiusCorners, composeBorderRadius, isCssLength, parseCornerRadius, toCamelCase } from './css-shorthands';
12
- import { Style, nodeHelper } from './style';
12
+ import { Style, nodeHelper, cssLengthToDip } from './style';
13
+ import { encodeBoxShadows, parseBoxShadows } from './box-shadow';
14
+ import { parseCssTransform } from './css-transform';
13
15
  import { alignContentProperty, aspectRatioProperty, backgroundProperty, borderProperty, borderLeftProperty, borderTopProperty, borderRightProperty, borderBottomProperty, borderRadiusProperty, bottomProperty, boxSizingProperty, clearProperty, columnGapProperty, cornerShapeProperty, displayProperty, filterProperty, flexBasisProperty, floatProperty, gridAreaProperty, gridAutoColumnsProperty, gridAutoFlowProperty, gridAutoRowsProperty, gridColumnEndProperty, gridColumnProperty, gridColumnStartProperty, gridRowEndProperty, gridRowProperty, gridRowStartProperty, gridTemplateAreasProperty, gridTemplateColumnsProperty, gridTemplateRowsProperty, justifyItemsProperty, justifySelfProperty, leftProperty, marginProperty, maxHeightProperty, maxWidthProperty, overflowXProperty, overflowYProperty, paddingProperty, positionProperty, rightProperty, rowGapProperty, scrollBarWidthProperty, textOverFlowProperty, textProperty, textWrapProperty, topProperty, verticalAlignProperty, boxShadowProperty, transformProperty, borderColorProperty, borderStyleProperty, backgroundImageProperty, listStyleTypeProperty, listStylePositionProperty, installMasonSizeUnits, } from './properties';
14
- import { isMasonView_, isTextChild_, isText_, isPlaceholder_, text_, native_, textNode_, textNodeIndex_, textNodeProxied_, pseudoStyles_, emptyTextNode_, breakRun_, anonymousText_, windowsFontSource_, hostsRuns_, needsAnonymousText_, borderRadiusCorners_, borderSideColors_, eventType_ } from './symbols';
16
+ import { isMasonView_, isTextChild_, isText_, isPlaceholder_, text_, native_, textNode_, textNodeIndex_, textNodeProxied_, pseudoStyles_, emptyTextNode_, breakRun_, anonymousText_, windowsFontSource_, hostsRuns_, needsAnonymousText_, borderRadiusCorners_, borderSideColors_, eventType_, runMember_, runsInline_, runsSettled_, blockified_ } from './symbols';
15
17
  import { Tree } from './tree';
16
- import { masonEngine } from './windows-panel-helpers';
18
+ import { masonEngine, removeNativeChild } from './windows-panel-helpers';
17
19
  import { TextNode } from './text-node';
18
20
  import { compile } from './pseudo';
19
21
  import { frameworkRegistry } from './framework-registry';
@@ -22,72 +24,6 @@ function getViewStyle(view) {
22
24
  const ret = (__ANDROID__ ? view.get() : view.deref());
23
25
  return ret._styleHelper;
24
26
  }
25
- // move to cpp
26
- function parseCssTransformToMatrix(s) {
27
- if (!s || s === 'none')
28
- return null;
29
- let tx = 0, ty = 0, rad = 0, sx = 1, sy = 1;
30
- let found = false;
31
- const re = /(\w+)\(([^)]*)\)/g;
32
- let m;
33
- while ((m = re.exec(s))) {
34
- found = true;
35
- const args = m[2].split(',').map((a) => parseFloat(a.trim()));
36
- switch (m[1]) {
37
- case 'translate':
38
- tx += args[0] || 0;
39
- ty += args[1] || 0;
40
- break;
41
- case 'translateX':
42
- tx += args[0] || 0;
43
- break;
44
- case 'translateY':
45
- ty += args[0] || 0;
46
- break;
47
- case 'rotate':
48
- case 'rotateZ':
49
- rad += ((args[0] || 0) * Math.PI) / 180;
50
- break;
51
- case 'scale':
52
- sx *= args[0] != null ? args[0] : 1;
53
- sy *= args[1] != null ? args[1] : args[0] != null ? args[0] : 1;
54
- break;
55
- case 'scaleX':
56
- sx *= args[0] != null ? args[0] : 1;
57
- break;
58
- case 'scaleY':
59
- sy *= args[0] != null ? args[0] : 1;
60
- break;
61
- }
62
- }
63
- if (!found)
64
- return null;
65
- const cos = Math.cos(rad), sin = Math.sin(rad);
66
- // CSS matrix(a,b,c,d,e,f) of rotate*scale → WinUI Matrix(M11,M12,M21,M22,OffsetX,OffsetY).
67
- return { m11: sx * cos, m12: sx * sin, m21: -sy * sin, m22: sy * cos, tx, ty };
68
- }
69
- // move to cpp
70
- function parseBoxShadow(s) {
71
- if (!s || s === 'none')
72
- return null;
73
- let color = 'rgba(0,0,0,0.2)';
74
- let rest = s;
75
- const m = s.match(/rgba?\([^)]*\)|#[0-9a-fA-F]{3,8}/);
76
- if (m) {
77
- color = m[0];
78
- rest = s.replace(m[0], ' ');
79
- }
80
- const nums = (rest.match(/-?\d*\.?\d+/g) || []).map((n) => parseFloat(n));
81
- const ox = nums[0] || 0, oy = nums[1] || 0, blur = nums[2] || 0;
82
- let argb = 0x33000000;
83
- try {
84
- argb = new Color(color).argb >>> 0;
85
- }
86
- catch (_) {
87
- /* keep default */
88
- }
89
- return { ox, oy, blur, argb };
90
- }
91
27
  function getWeakRefValue(value) {
92
28
  if (!value)
93
29
  return null;
@@ -117,6 +53,10 @@ function masonNativeEventName(eventName) {
117
53
  case 'beforeinput':
118
54
  case 'input':
119
55
  case 'change':
56
+ case 'cancel':
57
+ case 'compositionstart':
58
+ case 'compositionupdate':
59
+ case 'compositionend':
120
60
  case 'focus':
121
61
  case 'blur':
122
62
  case 'keydown':
@@ -129,7 +69,7 @@ function findOwnerForNativeView(owner, nativeView) {
129
69
  if (!owner || !nativeView)
130
70
  return null;
131
71
  const ownNativeView = nativeViewFor(owner);
132
- if (ownNativeView === nativeView)
72
+ if (ownNativeView === nativeView || owner?.[native_] === nativeView)
133
73
  return owner;
134
74
  const children = owner._children ?? owner._viewChildren;
135
75
  if (!children)
@@ -209,6 +149,44 @@ function clearWindowsActive(view) {
209
149
  for (const state of WINDOWS_ACTIVE_STATES)
210
150
  view._removeVisualState(state);
211
151
  }
152
+ function onWindowsHoverEnter(args) {
153
+ args.object._addVisualState('hover');
154
+ }
155
+ function onWindowsHoverLeave(args) {
156
+ args.object._removeVisualState('hover');
157
+ }
158
+ function onWindowsFocus() {
159
+ this._addVisualState('focus');
160
+ }
161
+ function onWindowsBlur() {
162
+ this._removeVisualState('focus');
163
+ }
164
+ const windowsRunCounts = new WeakMap();
165
+ function windowsNativeOf(child) {
166
+ return child?.nativeViewProtected ?? child?._view;
167
+ }
168
+ function windowsBreakRun(child) {
169
+ let run = child[breakRun_];
170
+ if (!run) {
171
+ run = new NativeScript.Mason.TextNode();
172
+ run.SetBreak(true);
173
+ child[breakRun_] = run;
174
+ }
175
+ return run;
176
+ }
177
+ export function windowsMemberKind(child) {
178
+ if (child[textNode_])
179
+ return 'run';
180
+ if (child[isPlaceholder_])
181
+ return 'break';
182
+ if (child[isText_] && !(child instanceof ButtonBase)) {
183
+ const style = child._styleHelper;
184
+ const display = style?.display;
185
+ if ((display === 'inline' || display === 'none') && !style.hasBoxStyle)
186
+ return 'text';
187
+ }
188
+ return 'box';
189
+ }
212
190
  const TEARDOWN_SLICE_MS = 8;
213
191
  // Reading the clock costs more than a teardown on some devices.
214
192
  const TEARDOWNS_PER_CLOCK_READ = 16;
@@ -225,6 +203,10 @@ function markClimbed(root) {
225
203
  function climbedThisTurn(root) {
226
204
  return !!climbedRoots?.has(root) && !!root.isLayoutRequested;
227
205
  }
206
+ let windowsInnerHTML;
207
+ export function setWindowsInnerHTML(build) {
208
+ windowsInnerHTML = build;
209
+ }
228
210
  export class ViewBase extends CustomLayoutView {
229
211
  _tearDownUI(force) {
230
212
  if ((__ANDROID__ || __APPLE__ || __WINDOWS__) && !force && !this.reusable && this._context && this.nativeViewProtected) {
@@ -332,6 +314,8 @@ export class ViewBase extends CustomLayoutView {
332
314
  * lays out, and Mason views listening to layoutChanged). The pass skips subtrees where it's 0.
333
315
  */
334
316
  this._masonLayoutWork = 0;
317
+ this._windowsActiveId = 0;
318
+ this._masonClimbTurn = null;
335
319
  // `width`/`height` are core CssAnimationProperties whose stylesheet accessor
336
320
  // is non-configurable, so units Mason understands but core does not (`vh`,
337
321
  // `rem`, `pt`, …) have to be resolved on this view's own Style object.
@@ -341,6 +325,8 @@ export class ViewBase extends CustomLayoutView {
341
325
  }
342
326
  }
343
327
  get innerHTML() {
328
+ if (__WINDOWS__)
329
+ return this._windowsInnerHTML ?? '';
344
330
  //@ts-ignore
345
331
  const nativeView = this._view;
346
332
  if (__ANDROID__) {
@@ -356,6 +342,11 @@ export class ViewBase extends CustomLayoutView {
356
342
  return '';
357
343
  }
358
344
  set innerHTML(value) {
345
+ if (__WINDOWS__) {
346
+ this._windowsInnerHTML = value ?? '';
347
+ windowsInnerHTML?.(this, value ?? '');
348
+ return;
349
+ }
359
350
  //@ts-ignore
360
351
  const nativeView = this._view;
361
352
  if (__ANDROID__) {
@@ -398,9 +389,18 @@ export class ViewBase extends CustomLayoutView {
398
389
  nativeHit = hitTest.call(nativeView, x, y);
399
390
  }
400
391
  }
392
+ else if (__WINDOWS__ && typeof masonEngine().ElementFromPoint === 'function') {
393
+ nativeHit = masonEngine().ElementFromPoint(nativeView, x, y);
394
+ }
401
395
  if (!nativeHit)
402
396
  return null;
403
- return nativeOwnerFor(nativeHit) ?? findOwnerForNativeView(this, nativeHit);
397
+ const known = nativeOwnerFor(nativeHit);
398
+ if (known)
399
+ return known;
400
+ // Owners are remembered on first hit rather than for every view at init.
401
+ const found = findOwnerForNativeView(this, nativeHit);
402
+ found?._rememberNativeOwner?.(nativeHit);
403
+ return found;
404
404
  }
405
405
  _registerNativeEvent(arg, callback, thisArg) {
406
406
  if (!this[native_]) {
@@ -437,7 +437,21 @@ export class ViewBase extends CustomLayoutView {
437
437
  callback['mason:event:id'] = id;
438
438
  }
439
439
  if (__WINDOWS__) {
440
- if (arg === 'click' || arg === 'tap') {
440
+ if (typeof masonEngine().AddEventListener === 'function') {
441
+ const ref = new WeakRef(this);
442
+ const listener = globalThis.NSWinRT.asDelegate('NativeScript.Mason.EventListener', (event) => {
443
+ const owner = ref.deref();
444
+ if (!owner)
445
+ return;
446
+ const ret = wrapNativeEvent(arg);
447
+ ret[native_] = event;
448
+ ret._target = owner;
449
+ callback.call(thisArg || owner, ret);
450
+ });
451
+ callback['mason:event:id'] = masonEngine().AddEventListener(this._view, arg, listener);
452
+ callback['mason:event:listener'] = listener;
453
+ }
454
+ else if (arg === 'click' || arg === 'tap') {
441
455
  try {
442
456
  const NSWinRT_ = globalThis.NSWinRT;
443
457
  const MUX = globalThis.Microsoft;
@@ -512,7 +526,12 @@ export class ViewBase extends CustomLayoutView {
512
526
  }
513
527
  }
514
528
  if (__WINDOWS__) {
515
- if (id && (arg === 'click' || arg === 'tap')) {
529
+ if (id && callback['mason:event:listener'] && !callback['mason:event:tapped']) {
530
+ masonEngine().RemoveEventListener(this._view, arg, id);
531
+ callback['mason:event:id'] = undefined;
532
+ callback['mason:event:listener'] = undefined;
533
+ }
534
+ else if (id && (arg === 'click' || arg === 'tap')) {
516
535
  try {
517
536
  const view = this._view;
518
537
  const tappedEvent = callback['mason:event:tapped'];
@@ -537,7 +556,6 @@ export class ViewBase extends CustomLayoutView {
537
556
  }
538
557
  initNativeView() {
539
558
  super.initNativeView();
540
- this._rememberNativeOwner();
541
559
  if (this._pendingEventsRegistration.length > 0) {
542
560
  const pending = this._pendingEventsRegistration.splice(0);
543
561
  for (const registration of pending) {
@@ -644,6 +662,17 @@ export class ViewBase extends CustomLayoutView {
644
662
  const styles = compile(this);
645
663
  //@ts-ignore
646
664
  this._applyPseudoClassStyles('hover', this._view, styles);
665
+ if (__WINDOWS__) {
666
+ if (subscribe) {
667
+ this.on('mouseEnter', onWindowsHoverEnter);
668
+ this.on('mouseLeave', onWindowsHoverLeave);
669
+ }
670
+ else {
671
+ this.off('mouseEnter', onWindowsHoverEnter);
672
+ this.off('mouseLeave', onWindowsHoverLeave);
673
+ this._removeVisualState('hover');
674
+ }
675
+ }
647
676
  }
648
677
  _handler(subscribe) {
649
678
  const styles = compile(this);
@@ -659,6 +688,7 @@ export class ViewBase extends CustomLayoutView {
659
688
  this.off('mouseLeave', onWindowsActiveLeave);
660
689
  clearWindowsActive(this);
661
690
  }
691
+ this._windowsListenActive(subscribe);
662
692
  // A button dims while held only when it has no :active style of its own.
663
693
  // @ts-ignore
664
694
  const view = this._view;
@@ -666,6 +696,33 @@ export class ViewBase extends CustomLayoutView {
666
696
  view.DimsWhenPressed = !subscribe;
667
697
  }
668
698
  }
699
+ // Inline elements a Text draws get no pointer events of their own; the Text reports their presses.
700
+ _windowsListenActive(on) {
701
+ const view = this._view;
702
+ if (!view || typeof masonEngine().AddEventListener !== 'function')
703
+ return;
704
+ if (on && !this._windowsActiveId) {
705
+ const ref = new WeakRef(this);
706
+ this._windowsActiveListener = globalThis.NSWinRT.asDelegate('NativeScript.Mason.EventListener', (event) => {
707
+ const owner = ref.deref();
708
+ if (!owner)
709
+ return;
710
+ if (event.Data === '1') {
711
+ for (const state of WINDOWS_ACTIVE_STATES)
712
+ owner._addVisualState(state);
713
+ }
714
+ else {
715
+ clearWindowsActive(owner);
716
+ }
717
+ });
718
+ this._windowsActiveId = masonEngine().AddEventListener(view, 'mason:active', this._windowsActiveListener);
719
+ }
720
+ else if (!on && this._windowsActiveId) {
721
+ masonEngine().RemoveEventListener(view, 'mason:active', this._windowsActiveId);
722
+ this._windowsActiveId = 0;
723
+ this._windowsActiveListener = undefined;
724
+ }
725
+ }
669
726
  _disableHandler(subscribe) {
670
727
  const styles = compile(this);
671
728
  //@ts-ignore
@@ -675,6 +732,17 @@ export class ViewBase extends CustomLayoutView {
675
732
  const styles = compile(this);
676
733
  //@ts-ignore
677
734
  this._applyPseudoClassStyles('focus', this._view, styles);
735
+ if (__WINDOWS__) {
736
+ if (subscribe) {
737
+ this.on('focus', onWindowsFocus, this);
738
+ this.on('blur', onWindowsBlur, this);
739
+ }
740
+ else {
741
+ this.off('focus', onWindowsFocus, this);
742
+ this.off('blur', onWindowsBlur, this);
743
+ this._removeVisualState('focus');
744
+ }
745
+ }
678
746
  }
679
747
  _blurHandler(subscribe) {
680
748
  const styles = compile(this);
@@ -705,8 +773,16 @@ export class ViewBase extends CustomLayoutView {
705
773
  }
706
774
  }
707
775
  eachChild(callback) {
708
- for (const child of this._viewChildren) {
709
- callback(child);
776
+ this._eachViewChild(callback);
777
+ }
778
+ // Live and allocation-free, like core's LayoutBase.eachChildView (walks run per view).
779
+ _eachViewChild(callback) {
780
+ const children = this._children;
781
+ for (let i = 0, length = children.length; i < length; i++) {
782
+ const child = children[i];
783
+ if (child && !child[isPlaceholder_] && child instanceof NSView) {
784
+ callback(child);
785
+ }
710
786
  }
711
787
  }
712
788
  // Core's iOS requestLayout climbs to the Page and re-measures the whole tree in JS.
@@ -817,12 +893,16 @@ export class ViewBase extends CustomLayoutView {
817
893
  // A natively placed view only needs its Mason root re-measured: skip the
818
894
  // per-ancestor hops (each a JS call plus a native setNeedsLayout).
819
895
  if (this._masonPlacedNatively) {
896
+ // CSS asks once per layout property; reuse this turn's root while it is still flagged.
897
+ if (climbedRoots && this._masonClimbTurn === climbedRoots && climbedThisTurn(this._masonClimbRoot))
898
+ return;
820
899
  let root = this.parent;
821
900
  while (root?.parent?.[isMasonView_])
822
901
  root = root.parent;
823
- if (root && climbedThisTurn(root))
824
- return;
825
- root?.requestLayout();
902
+ if (root && !climbedThisTurn(root))
903
+ root.requestLayout();
904
+ this._masonClimbRoot = root;
905
+ this._masonClimbTurn = climbedRoots;
826
906
  return;
827
907
  }
828
908
  // Core climbs on every call, once per changed property; once per turn is enough.
@@ -834,6 +914,7 @@ export class ViewBase extends CustomLayoutView {
834
914
  }
835
915
  _parentChanged(oldParent) {
836
916
  climbedRoots?.delete(this);
917
+ this._masonClimbTurn = null;
837
918
  super._parentChanged(oldParent);
838
919
  }
839
920
  getMeasuredWidth() {
@@ -849,24 +930,37 @@ export class ViewBase extends CustomLayoutView {
849
930
  return super.getMeasuredHeight();
850
931
  }
851
932
  eachChildView(callback) {
852
- for (const view of this._viewChildren) {
853
- callback(view);
854
- }
933
+ this._eachViewChild(callback);
855
934
  }
856
935
  _addChildFromBuilder(name, value) {
857
936
  this.addChild(value);
858
937
  }
859
938
  getChildrenCount() {
860
- return this._viewChildren.length;
939
+ let count = 0;
940
+ this._eachViewChild(() => count++);
941
+ return count;
861
942
  }
862
943
  get _childrenCount() {
863
- return this._viewChildren.length;
944
+ return this.getChildrenCount();
864
945
  }
865
946
  getChildAt(index) {
866
- return this._viewChildren[index];
947
+ let found;
948
+ let i = 0;
949
+ this._eachViewChild((child) => {
950
+ if (i++ === index)
951
+ found = child;
952
+ });
953
+ return found;
867
954
  }
868
955
  getChildIndex(child) {
869
- return this._viewChildren.indexOf(child);
956
+ let index = -1;
957
+ let i = 0;
958
+ this._eachViewChild((c) => {
959
+ if (c === child && index === -1)
960
+ index = i;
961
+ i++;
962
+ });
963
+ return index;
870
964
  }
871
965
  getChildById(id) {
872
966
  return getViewById(this, id);
@@ -881,13 +975,13 @@ export class ViewBase extends CustomLayoutView {
881
975
  //@ts-ignore
882
976
  this._view.mason_append(child._view);
883
977
  }
884
- if (__WINDOWS__) {
885
- this._windowsAttachPlaceholder(child, -1);
886
- }
887
978
  if (this[isText_]) {
888
979
  child[isTextChild_] = true;
889
980
  }
890
981
  this._children.push(child);
982
+ if (__WINDOWS__) {
983
+ this._windowsAttachPlaceholder(child, -1);
984
+ }
891
985
  return;
892
986
  }
893
987
  if (child instanceof NSView) {
@@ -975,9 +1069,9 @@ export class ViewBase extends CustomLayoutView {
975
1069
  group = anonymous;
976
1070
  continue;
977
1071
  }
978
- group = undefined;
979
1072
  if (c[textNode_] || c instanceof TextNode || text_ in c || (c[isPlaceholder_] && c[native_]) || c._isMasonChild) {
980
1073
  index++;
1074
+ group = undefined;
981
1075
  }
982
1076
  }
983
1077
  return index;
@@ -1016,9 +1110,6 @@ export class ViewBase extends CustomLayoutView {
1016
1110
  }
1017
1111
  insertChild(child, atIndex) {
1018
1112
  this._invalidateAttachCursor();
1019
- if (__WINDOWS__) {
1020
- this._windowsSplitAnonymousText(atIndex);
1021
- }
1022
1113
  if (child && child[isPlaceholder_] && child._view) {
1023
1114
  const nativeIndex = this._nativeIndexFor(atIndex);
1024
1115
  this._children.splice(atIndex, 0, child);
@@ -1112,6 +1203,7 @@ export class ViewBase extends CustomLayoutView {
1112
1203
  }
1113
1204
  if (__WINDOWS__) {
1114
1205
  this._windowsDetachPlaceholder(child);
1206
+ this._windowsMergeAt(index);
1115
1207
  }
1116
1208
  child[isTextChild_] = false;
1117
1209
  this.requestLayout?.();
@@ -1132,7 +1224,6 @@ export class ViewBase extends CustomLayoutView {
1132
1224
  // Drop the proxy binding so a later re-adopt re-installs cleanly.
1133
1225
  child[textNodeProxied_] = false;
1134
1226
  child[textNode_] = undefined;
1135
- this._syncTextRunLayout();
1136
1227
  this.requestLayout?.();
1137
1228
  return;
1138
1229
  }
@@ -1141,6 +1232,9 @@ export class ViewBase extends CustomLayoutView {
1141
1232
  if (index > -1) {
1142
1233
  this._children.splice(index, 1);
1143
1234
  this._removeView(child);
1235
+ if (__WINDOWS__) {
1236
+ this._windowsMergeAt(index);
1237
+ }
1144
1238
  }
1145
1239
  }
1146
1240
  // Remove the native node directly when supported (no index drift), falling
@@ -1171,33 +1265,31 @@ export class ViewBase extends CustomLayoutView {
1171
1265
  if (typeof view.RemoveRun === 'function')
1172
1266
  view.RemoveRun(node);
1173
1267
  else
1174
- this._windowsRemoveAnonymousRun(index);
1268
+ this._windowsRemoveMember(this._children[index]);
1175
1269
  }
1176
1270
  }
1177
- // Windows text lays out TextNode runs, not child panels, so a placeholder inside one
1178
- // becomes a break run; any other parent hosts its native panel.
1271
+ // Windows text lays out TextNode runs, not child panels, so a placeholder inside one, or inside a
1272
+ // block's inline run, becomes a break run; any other parent hosts its native panel.
1179
1273
  _windowsAttachPlaceholder(child, index) {
1180
1274
  const view = this._view;
1181
1275
  if (!view)
1182
1276
  return;
1183
1277
  if (this._windowsHostsRuns()) {
1184
- let run = child[breakRun_];
1185
- if (!run) {
1186
- run = new NativeScript.Mason.TextNode();
1187
- run.SetBreak(true);
1188
- child[breakRun_] = run;
1189
- }
1190
- view.SetRun(run, index);
1278
+ view.SetRun(windowsBreakRun(child), index);
1191
1279
  }
1192
- else {
1193
- masonEngine().ReparentChild(view, child._view, index);
1280
+ else if (!this._windowsAttach(child)) {
1281
+ const slot = this._children.indexOf(child);
1282
+ masonEngine().ReparentChild(view, child._view, slot > -1 ? this._nativeIndexFor(slot) : index);
1194
1283
  }
1195
1284
  }
1196
1285
  _windowsDetachPlaceholder(child) {
1197
1286
  const view = this._view;
1198
1287
  if (!view)
1199
1288
  return;
1200
- if (child[breakRun_] && typeof view.RemoveRun === 'function') {
1289
+ if (child[anonymousText_]) {
1290
+ this._windowsRemoveMember(child);
1291
+ }
1292
+ else if (child[breakRun_] && typeof view.RemoveRun === 'function') {
1201
1293
  view.RemoveRun(child[breakRun_]);
1202
1294
  }
1203
1295
  else {
@@ -1217,6 +1309,12 @@ export class ViewBase extends CustomLayoutView {
1217
1309
  }
1218
1310
  if (__WINDOWS__) {
1219
1311
  this._forEachAnonymousText((anonymous) => masonEngine().RemoveChild(this._view, anonymous));
1312
+ for (const c of this._children) {
1313
+ if (!c)
1314
+ continue;
1315
+ c[anonymousText_] = undefined;
1316
+ c[runMember_] = undefined;
1317
+ }
1220
1318
  }
1221
1319
  this._children.splice(0);
1222
1320
  this._invalidateAttachCursor();
@@ -1229,6 +1327,13 @@ export class ViewBase extends CustomLayoutView {
1229
1327
  style.zIndex = value;
1230
1328
  }
1231
1329
  }
1330
+ [directionProperty.setNative](value) {
1331
+ // @ts-ignore
1332
+ super[directionProperty.setNative]?.(value);
1333
+ const style = this._styleHelper;
1334
+ if (style)
1335
+ style.direction = value === 'rtl' || value === 'ltr' ? value : 'inherit';
1336
+ }
1232
1337
  set verticalAlign(value) {
1233
1338
  this.style.verticalAlign = value;
1234
1339
  }
@@ -1439,17 +1544,22 @@ export class ViewBase extends CustomLayoutView {
1439
1544
  const anonymous = this._windowsNeedsAnonymousText();
1440
1545
  switch (operation.type) {
1441
1546
  case 'add':
1442
- if (anonymous)
1443
- entry[anonymousText_] = this._windowsAddAnonymousRun(textNode, this._children.length, false);
1444
- else
1445
- this._nativeAddChild(textNode, this._children.length);
1547
+ if (anonymous) {
1548
+ //@ts-ignore
1549
+ this._children.push({ ...entry, [textNodeIndex_]: this._children.length });
1550
+ this._windowsInsertMember(this._children.length - 1, this._windowsRunsInline());
1551
+ break;
1552
+ }
1553
+ this._nativeAddChild(textNode, this._children.length);
1446
1554
  //@ts-ignore
1447
1555
  this._children.push({ ...entry, [textNodeIndex_]: this._children.length });
1448
1556
  break;
1449
1557
  case 'replace':
1450
- if (anonymous)
1451
- entry[anonymousText_] = this._windowsAddAnonymousRun(textNode, operation.index, true);
1452
- else if (!__WINDOWS__ || this._children[operation.index]?.[textNode_] !== textNode)
1558
+ if (anonymous) {
1559
+ this._windowsReplaceRun(operation.index, entry);
1560
+ break;
1561
+ }
1562
+ if (!__WINDOWS__ || this._children[operation.index]?.[textNode_] !== textNode)
1453
1563
  this._nativeReplaceChild(textNode, operation.index);
1454
1564
  this._setOrPushChild(operation.index, entry);
1455
1565
  break;
@@ -1458,15 +1568,16 @@ export class ViewBase extends CustomLayoutView {
1458
1568
  // lag behind it (elements attach lazily on `loaded`), so map it the
1459
1569
  // same way `insertChild` does or the run lands past the end.
1460
1570
  const index = Math.max(0, Math.min(operation.index ?? this._children.length, this._children.length));
1461
- if (anonymous)
1462
- entry[anonymousText_] = this._windowsAddAnonymousRun(textNode, index, false);
1463
- else
1464
- this._nativeAddChild(textNode, this._nativeIndexFor(index));
1571
+ if (anonymous) {
1572
+ this._spliceOrPushChild(index, entry);
1573
+ this._windowsInsertMember(index, this._windowsRunsInline());
1574
+ break;
1575
+ }
1576
+ this._nativeAddChild(textNode, this._nativeIndexFor(index));
1465
1577
  this._spliceOrPushChild(index, entry);
1466
1578
  break;
1467
1579
  }
1468
1580
  }
1469
- this._syncTextRunLayout();
1470
1581
  }
1471
1582
  // Only Text lays out runs on Windows, so any other container puts consecutive runs in one
1472
1583
  // anonymous Text, as Android's getOrCreateAnonymousTextContainer does.
@@ -1493,71 +1604,399 @@ export class ViewBase extends CustomLayoutView {
1493
1604
  }
1494
1605
  return hosts;
1495
1606
  }
1496
- _windowsAddAnonymousRun(textNode, slot, replace) {
1607
+ // A block container's consecutive inline-level children share one anonymous Text, CSS's anonymous
1608
+ // block box; a flex or grid container groups only consecutive text.
1609
+ _windowsRunsInline() {
1610
+ if (this[runsSettled_] !== true)
1611
+ return false;
1612
+ const display = this._styleHelper?.display;
1613
+ return display === 'block' || display === 'inline-block';
1614
+ }
1615
+ // A container's display arrives with its CSS, after its children attach, so runs are grouped once the turn ends.
1616
+ _windowsScheduleSettle() {
1617
+ if (this[runsSettled_] !== undefined)
1618
+ return;
1619
+ this[runsSettled_] = false;
1620
+ queueMicrotask(() => this._windowsSettleRuns());
1621
+ }
1622
+ _windowsSettleRuns() {
1623
+ this[runsSettled_] = true;
1624
+ const inline = this._windowsRunsInline();
1497
1625
  const children = this._children;
1498
- const old = replace ? children[slot] : undefined;
1499
- const current = old?.[anonymousText_];
1500
- if (current) {
1501
- if (old[textNode_] !== textNode) {
1502
- const at = this._windowsRunsBefore(slot, current);
1503
- current.RemoveRun(old[textNode_]);
1504
- current.SetRun(textNode, at);
1505
- }
1506
- return current;
1507
- }
1508
- const prev = children[slot - 1]?.[anonymousText_];
1509
- if (prev) {
1510
- prev.SetRun(textNode, this._windowsRunsBefore(slot, prev));
1511
- return prev;
1512
- }
1513
- const next = children[replace ? slot + 1 : slot]?.[anonymousText_];
1514
- if (next) {
1515
- next.SetRun(textNode, 0);
1516
- return next;
1517
- }
1518
- const anonymous = this._windowsCreateAnonymousText(this._nativeIndexFor(slot));
1519
- anonymous.SetRun(textNode, 0);
1520
- return anonymous;
1626
+ for (const c of children)
1627
+ if (c?._isMasonChild)
1628
+ this._windowsBlockify(c, inline);
1629
+ const regroup = children.some((c, i) => c && !c[textNode_] && (c[anonymousText_] || c[runMember_] === 'solo' || ((c._isMasonChild || c[isPlaceholder_]) && this._windowsJoinsAt(i, inline))));
1630
+ if (regroup)
1631
+ this._windowsReflow(0, true);
1632
+ this[runsInline_] = inline;
1633
+ }
1634
+ // Undefined for display: none, which stays in an open run.
1635
+ _windowsJoins(c, inline) {
1636
+ if (!c)
1637
+ return false;
1638
+ if (c[textNode_])
1639
+ return true;
1640
+ if (!inline)
1641
+ return false;
1642
+ if (c[isPlaceholder_])
1643
+ return true;
1644
+ if (!c[isMasonView_])
1645
+ return false;
1646
+ const style = c._styleHelper;
1647
+ if (!style)
1648
+ return false;
1649
+ const display = style.display;
1650
+ if (display === 'none')
1651
+ return undefined;
1652
+ if (display !== 'inline' && display !== 'inline-block' && display !== 'inline-flex' && display !== 'inline-grid')
1653
+ return false;
1654
+ const position = style.position;
1655
+ if (position === 'absolute' || position === 'fixed')
1656
+ return false;
1657
+ return style.float === 'none';
1521
1658
  }
1522
- _windowsRunsBefore(slot, anonymous) {
1523
- let n = 0;
1524
- for (let i = slot - 1; i >= 0 && this._children[i]?.[anonymousText_] === anonymous; i--)
1525
- n++;
1526
- return n;
1659
+ _windowsJoinsAt(slot, inline) {
1660
+ const joins = this._windowsJoins(this._children[slot], inline);
1661
+ return joins === undefined ? slot > 0 && this._windowsJoinsAt(slot - 1, inline) : joins;
1527
1662
  }
1528
- _windowsCreateAnonymousText(nativeIndex) {
1663
+ // The anonymous Text or lone element holding the run on each side of `slot`, and whether either is lone.
1664
+ _windowsRunsAround(slot, inline) {
1665
+ const children = this._children;
1666
+ let left;
1667
+ let right;
1668
+ let solo = false;
1669
+ for (let i = slot - 1; i >= 0; i--) {
1670
+ const c = children[i];
1671
+ left = c?.[anonymousText_] ?? (c?.[runMember_] === 'solo' ? c : undefined);
1672
+ if (left) {
1673
+ solo = left === c && !c[anonymousText_];
1674
+ break;
1675
+ }
1676
+ if (!this._windowsJoinsAt(i, inline))
1677
+ break;
1678
+ }
1679
+ for (let i = slot + 1; i < children.length; i++) {
1680
+ const c = children[i];
1681
+ right = c?.[anonymousText_] ?? (c?.[runMember_] === 'solo' ? c : undefined);
1682
+ if (right) {
1683
+ solo = solo || (right === c && !c[anonymousText_]);
1684
+ break;
1685
+ }
1686
+ if (!this._windowsJoinsAt(i, inline))
1687
+ break;
1688
+ }
1689
+ return [left, right, solo];
1690
+ }
1691
+ _windowsAttach(child) {
1692
+ if (!__WINDOWS__ || !this._windowsNeedsAnonymousText())
1693
+ return false;
1694
+ const slot = this._children.indexOf(child);
1695
+ if (slot < 0)
1696
+ return false;
1697
+ const settled = this[runsSettled_] === true;
1698
+ if (!settled)
1699
+ this._windowsScheduleSettle();
1700
+ const inline = this._windowsRunsInline();
1701
+ if (settled)
1702
+ this._windowsBlockify(child, inline);
1703
+ if (this._windowsJoinsAt(slot, inline)) {
1704
+ this._windowsInsertMember(slot, inline, child);
1705
+ if (!child[anonymousText_])
1706
+ return false;
1707
+ child._isMasonChild = true;
1708
+ return true;
1709
+ }
1710
+ const [left, right] = this._windowsRunsAround(slot, inline);
1711
+ if (left && left === right)
1712
+ this._windowsReflow(slot);
1713
+ return false;
1714
+ }
1715
+ // A run of one element needs no anonymous Text: the element is laid out as it is.
1716
+ _windowsInsertMember(slot, inline, attaching) {
1717
+ this._windowsScheduleSettle();
1718
+ const children = this._children;
1719
+ const c = children[slot];
1720
+ const [left, right, solo] = this._windowsRunsAround(slot, inline);
1721
+ if (solo || (left && right && left !== right)) {
1722
+ this._windowsReflow(slot, false, attaching);
1723
+ return;
1724
+ }
1725
+ let anonymous = left ?? right;
1726
+ if (!anonymous) {
1727
+ if (c[isMasonView_] && !c[isPlaceholder_]) {
1728
+ c[runMember_] = 'solo';
1729
+ return;
1730
+ }
1731
+ anonymous = this._windowsCreateAnonymousText();
1732
+ this._windowsPlaceAnonymous(anonymous, slot);
1733
+ }
1734
+ const index = right ? this._windowsMemberIndex(slot, anonymous, inline) : (windowsRunCounts.get(anonymous) ?? 0);
1735
+ this._windowsAddMember(anonymous, c, index);
1736
+ }
1737
+ _windowsMemberIndex(slot, anonymous, inline) {
1738
+ const children = this._children;
1739
+ let index = 0;
1740
+ for (let i = slot - 1; i >= 0; i--) {
1741
+ const owner = children[i]?.[anonymousText_];
1742
+ if (owner === anonymous)
1743
+ index++;
1744
+ else if (owner || !this._windowsJoinsAt(i, inline))
1745
+ break;
1746
+ }
1747
+ return index;
1748
+ }
1749
+ _windowsAddMember(anonymous, c, index) {
1750
+ const kind = windowsMemberKind(c);
1751
+ switch (kind) {
1752
+ case 'run':
1753
+ anonymous.SetRun(c[textNode_], index);
1754
+ break;
1755
+ case 'break':
1756
+ anonymous.SetRun(windowsBreakRun(c), index);
1757
+ break;
1758
+ case 'text':
1759
+ if (c._isMasonChild)
1760
+ masonEngine().RemoveChild(this._view, c._view);
1761
+ anonymous.SetInlineText(c._view, index);
1762
+ break;
1763
+ default:
1764
+ if (c._isMasonChild)
1765
+ masonEngine().RemoveChild(this._view, windowsNativeOf(c));
1766
+ anonymous.SetInlineBox(windowsNativeOf(c), index);
1767
+ break;
1768
+ }
1769
+ c[anonymousText_] = anonymous;
1770
+ c[runMember_] = kind;
1771
+ windowsRunCounts.set(anonymous, (windowsRunCounts.get(anonymous) ?? 0) + 1);
1772
+ }
1773
+ _windowsRemoveMember(c) {
1774
+ const anonymous = c?.[anonymousText_];
1775
+ if (!anonymous)
1776
+ return;
1777
+ switch (c[runMember_]) {
1778
+ case 'run':
1779
+ anonymous.RemoveRun(c[textNode_]);
1780
+ break;
1781
+ case 'break':
1782
+ anonymous.RemoveRun(c[breakRun_]);
1783
+ break;
1784
+ case 'text':
1785
+ anonymous.RemoveInlineText(c._view);
1786
+ break;
1787
+ default:
1788
+ anonymous.RemoveInlineBox(windowsNativeOf(c));
1789
+ break;
1790
+ }
1791
+ c[anonymousText_] = undefined;
1792
+ c[runMember_] = undefined;
1793
+ const count = (windowsRunCounts.get(anonymous) ?? 1) - 1;
1794
+ windowsRunCounts.set(anonymous, count);
1795
+ if (count <= 0)
1796
+ masonEngine().RemoveChild(this._view, anonymous);
1797
+ }
1798
+ _windowsReplaceRun(slot, entry) {
1799
+ const old = this._children[slot];
1800
+ const anonymous = old?.[anonymousText_];
1801
+ if (anonymous && old[runMember_] === 'run') {
1802
+ if (old[textNode_] !== entry[textNode_]) {
1803
+ const index = this._windowsMemberIndex(slot, anonymous, this._windowsRunsInline());
1804
+ anonymous.RemoveRun(old[textNode_]);
1805
+ anonymous.SetRun(entry[textNode_], index);
1806
+ }
1807
+ entry[anonymousText_] = anonymous;
1808
+ entry[runMember_] = 'run';
1809
+ this._setOrPushChild(slot, entry);
1810
+ return;
1811
+ }
1812
+ if (old)
1813
+ this._windowsRemoveMember(old);
1814
+ this._setOrPushChild(slot, entry);
1815
+ this._windowsInsertMember(Math.min(slot, this._children.length - 1), this._windowsRunsInline());
1816
+ }
1817
+ _windowsCreateAnonymousText() {
1529
1818
  const anonymous = new NativeScript.Mason.Text();
1819
+ anonymous.IsAnonymous = true;
1530
1820
  // @ts-ignore
1531
- this._styleHelper?.copyTextStyleTo(anonymous);
1821
+ this._styleHelper?.copyTextStyleTo(anonymous, -1, -1, -1, -1, true);
1532
1822
  const font = this[windowsFontSource_];
1533
1823
  if (font)
1534
1824
  anonymous.SetFontFamily(font);
1535
- masonEngine().ReparentChild(this._view, anonymous, nativeIndex);
1536
1825
  return anonymous;
1537
1826
  }
1538
- _windowsRemoveAnonymousRun(index) {
1827
+ _windowsPlaceAnonymous(anonymous, slot) {
1828
+ masonEngine().ReparentChild(this._view, anonymous, this._nativeIndexFor(slot));
1829
+ }
1830
+ // `attaching` counts as attached; the caller adds it to the panel if it stays a direct child.
1831
+ _windowsReflow(slot, all = false, attaching) {
1539
1832
  const children = this._children;
1540
- const anonymous = children[index]?.[anonymousText_];
1541
- if (!anonymous)
1833
+ const view = this._view;
1834
+ if (!view || children.length === 0)
1542
1835
  return;
1543
- anonymous.RemoveRun(children[index][textNode_]);
1544
- if (children[index - 1]?.[anonymousText_] !== anonymous && children[index + 1]?.[anonymousText_] !== anonymous) {
1545
- masonEngine().RemoveChild(this._view, anonymous);
1836
+ const inline = this._windowsRunsInline();
1837
+ let a = Math.max(0, Math.min(slot, children.length - 1));
1838
+ let b = a;
1839
+ if (all) {
1840
+ a = 0;
1841
+ b = children.length - 1;
1842
+ for (const c of children)
1843
+ if (c?._isMasonChild)
1844
+ this._windowsBlockify(c, inline);
1845
+ }
1846
+ else {
1847
+ const inRegion = (i) => !!children[i]?.[anonymousText_] || this._windowsJoinsAt(i, inline);
1848
+ while (a > 0 && inRegion(a - 1))
1849
+ a--;
1850
+ while (b < children.length - 1 && inRegion(b + 1))
1851
+ b++;
1852
+ }
1853
+ // Every member of an anonymous Text being regrouped is regrouped with it.
1854
+ const pool = [];
1855
+ for (let grew = true; grew;) {
1856
+ grew = false;
1857
+ for (let i = a; i <= b; i++) {
1858
+ const anonymous = children[i]?.[anonymousText_];
1859
+ if (anonymous && pool.indexOf(anonymous) < 0)
1860
+ pool.push(anonymous);
1861
+ }
1862
+ for (let i = 0; i < children.length; i++) {
1863
+ if ((i < a || i > b) && pool.indexOf(children[i]?.[anonymousText_]) > -1) {
1864
+ a = Math.min(a, i);
1865
+ b = Math.max(b, i);
1866
+ grew = true;
1867
+ }
1868
+ }
1869
+ }
1870
+ const members = new Set();
1871
+ for (let i = a; i <= b; i++)
1872
+ if (children[i]?.[anonymousText_])
1873
+ members.add(children[i]);
1874
+ for (const anonymous of pool) {
1875
+ anonymous.ClearRuns();
1876
+ windowsRunCounts.set(anonymous, 0);
1877
+ }
1878
+ for (let i = a; i <= b; i++) {
1879
+ const c = children[i];
1880
+ if (!c)
1881
+ continue;
1882
+ c[anonymousText_] = undefined;
1883
+ c[runMember_] = undefined;
1884
+ }
1885
+ const isElement = (c) => !!c[isMasonView_] && !c[isPlaceholder_];
1886
+ const groups = [];
1887
+ let run = null;
1888
+ for (let i = a; i <= b; i++) {
1889
+ const c = children[i];
1890
+ if (!c)
1891
+ continue;
1892
+ if (this._windowsJoinsAt(i, inline)) {
1893
+ if (isElement(c) && c !== attaching && !c._isMasonChild)
1894
+ continue;
1895
+ if (!run)
1896
+ groups.push((run = []));
1897
+ run.push(i);
1898
+ }
1899
+ else {
1900
+ run = null;
1901
+ groups.push([-1 - i]);
1902
+ }
1546
1903
  }
1904
+ for (const group of groups) {
1905
+ const first = group[0] < 0 ? -1 - group[0] : group[0];
1906
+ const c = children[first];
1907
+ if (group[0] < 0 || (group.length === 1 && isElement(c))) {
1908
+ if (group[0] >= 0)
1909
+ c[runMember_] = 'solo';
1910
+ if (c === attaching || !members.has(c))
1911
+ continue;
1912
+ if (isElement(c) && c._isMasonChild)
1913
+ masonEngine().ReparentChild(view, windowsNativeOf(c), this._nativeIndexFor(first));
1914
+ else if (c[isPlaceholder_] && c._view)
1915
+ masonEngine().ReparentChild(view, c._view, this._nativeIndexFor(first));
1916
+ continue;
1917
+ }
1918
+ const anonymous = pool.shift() ?? this._windowsCreateAnonymousText();
1919
+ this._windowsPlaceAnonymous(anonymous, first);
1920
+ group.forEach((i, k) => this._windowsAddMember(anonymous, children[i], k));
1921
+ }
1922
+ for (const anonymous of pool)
1923
+ masonEngine().RemoveChild(view, anonymous);
1924
+ this[runsInline_] = inline;
1547
1925
  }
1548
- // An element landing between two runs of one anonymous Text splits it, so the runs after it
1549
- // render after it.
1550
- _windowsSplitAnonymousText(slot) {
1551
- const children = this._children;
1552
- const anonymous = children[slot - 1]?.[anonymousText_];
1553
- if (!anonymous || children[slot]?.[anonymousText_] !== anonymous)
1926
+ _windowsMergeAt(slot) {
1927
+ if (!this._windowsNeedsAnonymousText() || this._children.length === 0)
1554
1928
  return;
1555
- const tail = this._windowsCreateAnonymousText(this._nativeIndexFor(slot));
1556
- for (let i = slot, k = 0; children[i]?.[anonymousText_] === anonymous; i++, k++) {
1557
- anonymous.RemoveRun(children[i][textNode_]);
1558
- tail.SetRun(children[i][textNode_], k);
1559
- children[i][anonymousText_] = tail;
1929
+ const inline = this._windowsRunsInline();
1930
+ const [left] = this._windowsRunsAround(slot, inline);
1931
+ const [, right] = this._windowsRunsAround(slot - 1, inline);
1932
+ if (left && right && left !== right)
1933
+ this._windowsReflow(Math.max(0, slot - 1));
1934
+ }
1935
+ _windowsFlowTypeChanged() {
1936
+ if (this[runsSettled_] === true && this._windowsNeedsAnonymousText() && this._windowsRunsInline() !== this[runsInline_]) {
1937
+ this._windowsSettleRuns();
1560
1938
  }
1939
+ this.parent?._windowsChildFlowChanged?.(this);
1940
+ }
1941
+ _windowsChildFlowChanged(child) {
1942
+ if (!child?._isMasonChild)
1943
+ return;
1944
+ if (!this._windowsHostsRuns() && this[runsSettled_] !== true)
1945
+ return;
1946
+ if (this._windowsHostsRuns()) {
1947
+ if (child[runMember_] && child[runMember_] !== windowsMemberKind(child))
1948
+ this._windowsRehost?.(child);
1949
+ return;
1950
+ }
1951
+ if (!this._windowsNeedsAnonymousText())
1952
+ return;
1953
+ const inline = this._windowsRunsInline();
1954
+ if (child[blockified_] && child._styleHelper?.display !== 'block')
1955
+ child[blockified_] = false;
1956
+ this._windowsBlockify(child, inline);
1957
+ const member = child[runMember_];
1958
+ let joins = this._windowsJoins(child, inline);
1959
+ let slot = -1;
1960
+ if (joins === undefined) {
1961
+ slot = this._children.indexOf(child);
1962
+ joins = slot > 0 && this._windowsJoinsAt(slot - 1, inline);
1963
+ }
1964
+ if (member === 'solo') {
1965
+ if (!joins)
1966
+ child[runMember_] = undefined;
1967
+ return;
1968
+ }
1969
+ if (joins === !!member && (!member || member === windowsMemberKind(child)))
1970
+ return;
1971
+ if (slot < 0)
1972
+ slot = this._children.indexOf(child);
1973
+ if (slot > -1)
1974
+ this._windowsReflow(slot);
1975
+ }
1976
+ // CSS blockifies flex and grid items.
1977
+ _windowsBlockify(child, inline) {
1978
+ if (!child?.[isText_] || child instanceof ButtonBase)
1979
+ return;
1980
+ const style = child._styleHelper;
1981
+ if (!style)
1982
+ return;
1983
+ if (!inline && !child[blockified_] && style.display === 'inline') {
1984
+ child[blockified_] = true;
1985
+ style.display = 'block';
1986
+ }
1987
+ else if (inline && child[blockified_]) {
1988
+ child[blockified_] = false;
1989
+ if (style.display === 'block')
1990
+ style.display = 'inline';
1991
+ }
1992
+ }
1993
+ _windowsDetachChild(child) {
1994
+ if (child?.[anonymousText_])
1995
+ this._windowsRemoveMember(child);
1996
+ else
1997
+ removeNativeChild(this._view, child);
1998
+ if (child)
1999
+ child[runMember_] = undefined;
1561
2000
  }
1562
2001
  _forEachAnonymousText(fn) {
1563
2002
  let last;
@@ -1568,11 +2007,11 @@ export class ViewBase extends CustomLayoutView {
1568
2007
  last = anonymous;
1569
2008
  }
1570
2009
  }
1571
- _windowsSyncAnonymousText() {
2010
+ _windowsSyncAnonymousText(d0, d1, d2, d3) {
1572
2011
  // @ts-ignore
1573
2012
  const style = this._styleHelper;
1574
2013
  if (style)
1575
- this._forEachAnonymousText((anonymous) => style.copyTextStyleTo(anonymous));
2014
+ this._forEachAnonymousText((anonymous) => style.copyTextStyleTo(anonymous, d0, d1, d2, d3));
1576
2015
  }
1577
2016
  [fontInternalProperty.setNative](value) {
1578
2017
  if (!__WINDOWS__)
@@ -1581,20 +2020,6 @@ export class ViewBase extends CustomLayoutView {
1581
2020
  this[windowsFontSource_] = source;
1582
2021
  this._forEachAnonymousText((anonymous) => anonymous.SetFontFamily(source));
1583
2022
  }
1584
- _syncTextRunLayout() {
1585
- if (!__WINDOWS__ || !this._windowsHostsRuns())
1586
- return;
1587
- // @ts-ignore
1588
- const sh = this._styleHelper;
1589
- if (!sh || sh.display === 'block')
1590
- return;
1591
- try {
1592
- sh.display = 'block';
1593
- }
1594
- catch (_) {
1595
- // empty
1596
- }
1597
- }
1598
2023
  // -- Text setter: framework adapter driven --
1599
2024
  [textProperty.setNative](value) {
1600
2025
  const adapter = frameworkRegistry.find(this);
@@ -1984,6 +2409,12 @@ export class ViewBase extends CustomLayoutView {
1984
2409
  // @ts-ignore
1985
2410
  this.nativeView.style.applyListStyleType(String(value));
1986
2411
  }
2412
+ else if (__WINDOWS__) {
2413
+ const style = this._styleHelper;
2414
+ const type = String(value).trim().toLowerCase();
2415
+ if (style && (type === 'none' || type === 'disc' || type === 'circle' || type === 'square' || type === 'decimal'))
2416
+ style.listStyleType = type;
2417
+ }
1987
2418
  }
1988
2419
  // @ts-ignore
1989
2420
  [listStylePositionProperty.setNative](value) {
@@ -1995,6 +2426,12 @@ export class ViewBase extends CustomLayoutView {
1995
2426
  // @ts-ignore
1996
2427
  this.nativeView.style.applyListStylePosition(String(value));
1997
2428
  }
2429
+ else if (__WINDOWS__) {
2430
+ const style = this._styleHelper;
2431
+ const position = String(value).trim().toLowerCase();
2432
+ if (style && (position === 'inside' || position === 'outside'))
2433
+ style.listStylePosition = position;
2434
+ }
1998
2435
  }
1999
2436
  get boxSizing() {
2000
2437
  return this.style.boxSizing;
@@ -2655,17 +3092,16 @@ export class ViewBase extends CustomLayoutView {
2655
3092
  return this.style.inset;
2656
3093
  }
2657
3094
  set textOverFlow(value) {
2658
- this.style.textOverFlow = value;
3095
+ this.style.textOverflow = value;
2659
3096
  }
2660
3097
  get textOverFlow() {
2661
- return this.style.textOverFlow;
3098
+ return this.style.textOverflow;
2662
3099
  }
2663
3100
  [textOverFlowProperty.setNative](value) {
2664
3101
  // @ts-ignore
2665
3102
  const style = this._styleHelper;
2666
3103
  if (style) {
2667
- // @ts-ignore
2668
- style.textOverFlow = value;
3104
+ style.textOverflow = value;
2669
3105
  }
2670
3106
  }
2671
3107
  [clearProperty.setNative](value) {
@@ -2698,15 +3134,21 @@ export class ViewBase extends CustomLayoutView {
2698
3134
  // @ts-ignore
2699
3135
  style.boxShadow = value;
2700
3136
  if (__WINDOWS__) {
2701
- // box-shadow isn't a Mason buffer prop — render it as a Composition DropShadow on the element
2702
- // (masked to its rounded-rect shape, re-applied on resize). The corner radius is read natively.
2703
3137
  const nv = this.nativeViewProtected ?? this._view;
2704
3138
  try {
2705
- const sh = parseBoxShadow(typeof value === 'string' ? value : '');
2706
- if (!sh)
2707
- NativeScript.Mason.Css.ClearShadow(nv);
2708
- else
2709
- NativeScript.Mason.Css.ApplyShadow(nv, sh.ox, sh.oy, sh.blur, sh.argb, 0);
3139
+ const shadows = parseBoxShadows(typeof value === 'string' ? value : '', (token) => cssLengthToDip(token, style.emBasis()));
3140
+ const current = style.color >>> 0 || 0xff000000;
3141
+ const spec = encodeBoxShadows(shadows, (color) => {
3142
+ if (!color || color.toLowerCase() === 'currentcolor')
3143
+ return current;
3144
+ try {
3145
+ return new Color(color).argb >>> 0;
3146
+ }
3147
+ catch (_) {
3148
+ return current;
3149
+ }
3150
+ });
3151
+ NativeScript.Mason.Css.SetBoxShadow(nv, spec);
2710
3152
  }
2711
3153
  catch (_) { }
2712
3154
  }
@@ -2724,11 +3166,14 @@ export class ViewBase extends CustomLayoutView {
2724
3166
  // doesn't drive transforms on). Parse the CSS string to a matrix and set RenderTransform.
2725
3167
  const nv = this.nativeViewProtected ?? this._view;
2726
3168
  try {
2727
- const mtx = parseCssTransformToMatrix(typeof value === 'string' ? value : '');
2728
- if (!mtx)
3169
+ const size = { width: nv?.ActualWidth ?? 0, height: nv?.ActualHeight ?? 0 };
3170
+ const m = parseCssTransform(typeof value === 'string' ? value : '', (token) => cssLengthToDip(token, style.emBasis()), size);
3171
+ if (!m)
2729
3172
  NativeScript.Mason.Css.ClearTransform(nv);
2730
- else
2731
- NativeScript.Mason.Css.ApplyTransform(nv, mtx.m11, mtx.m12, mtx.m21, mtx.m22, mtx.tx, mtx.ty);
3173
+ else {
3174
+ NativeScript.Mason.Css.ApplyTransform(nv, m[0], m[1], m[2], m[3], m[4], m[5]);
3175
+ nv.RenderTransformOrigin = { X: this.originX ?? 0.5, Y: this.originY ?? 0.5 };
3176
+ }
2732
3177
  }
2733
3178
  catch (_) { }
2734
3179
  }
@@ -2770,7 +3215,7 @@ __decorate([
2770
3215
  textProperty.register(ViewBase);
2771
3216
  // Core's Windows Font resolves app/fonts files to an ms-appx URI (and generics to system fonts);
2772
3217
  // the bare family name only finds installed fonts.
2773
- function windowsFontSource(font) {
3218
+ export function windowsFontSource(font) {
2774
3219
  try {
2775
3220
  const source = font?.getWindowsFontDescriptor?.()?.fontFamilyNative?.Source;
2776
3221
  if (source)
@@ -2978,7 +3423,16 @@ export class Event {
2978
3423
  }
2979
3424
  set button(_) { }
2980
3425
  get target() {
2981
- return this['_target'];
3426
+ // The element the event started at, which differs from currentTarget once it bubbles.
3427
+ const nativeEvent = this[native_];
3428
+ const nativeTarget = __ANDROID__ ? nativeEvent?.getTarget?.() : __APPLE__ ? nativeEvent?.target : __WINDOWS__ ? nativeEvent?.Target : null;
3429
+ const current = this['_target'];
3430
+ if (nativeTarget && nativeTarget !== nativeViewFor(current)) {
3431
+ const found = nativeOwnerFor(nativeTarget) ?? findOwnerForNativeView(current, nativeTarget);
3432
+ if (found)
3433
+ return found;
3434
+ }
3435
+ return current;
2982
3436
  }
2983
3437
  set target(_) { }
2984
3438
  get object() {
@@ -3027,6 +3481,15 @@ export class InputEvent extends Event {
3027
3481
  return this[native_]?.data;
3028
3482
  }
3029
3483
  if (__WINDOWS__) {
3484
+ const files = this[native_]?.Files;
3485
+ if (files) {
3486
+ const ret = [];
3487
+ const size = files.Size;
3488
+ for (let i = 0; i < size; i++) {
3489
+ ret.push(files.GetAt(i));
3490
+ }
3491
+ return ret;
3492
+ }
3030
3493
  return this[native_]?.Data ?? null;
3031
3494
  }
3032
3495
  return false;
@@ -3044,6 +3507,11 @@ export class InputEvent extends Event {
3044
3507
  return false;
3045
3508
  }
3046
3509
  }
3510
+ export class CompositionEvent extends Event {
3511
+ get data() {
3512
+ return this[native_]?.Data ?? '';
3513
+ }
3514
+ }
3047
3515
  /** DOM KeyboardEvent: dispatched on Windows. */
3048
3516
  export class KeyboardEvent extends Event {
3049
3517
  get key() {
@@ -3072,6 +3540,10 @@ function wrapNativeEvent(type) {
3072
3540
  return new InputEvent();
3073
3541
  case 'keydown':
3074
3542
  return new KeyboardEvent();
3543
+ case 'compositionstart':
3544
+ case 'compositionupdate':
3545
+ case 'compositionend':
3546
+ return new CompositionEvent();
3075
3547
  default:
3076
3548
  return new Event();
3077
3549
  }