@triniwiz/nativescript-masonkit 1.0.0-beta.108 → 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 (120) 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 +31 -7
  7. package/common.js +625 -184
  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/index.d.ts +6 -4
  22. package/index.windows.d.ts +2 -0
  23. package/index.windows.js +2 -0
  24. package/index.windows.js.map +1 -1
  25. package/input/common.d.ts +16 -0
  26. package/input/common.js +45 -3
  27. package/input/common.js.map +1 -1
  28. package/input/index.android.d.ts +8 -3
  29. package/input/index.android.js +24 -7
  30. package/input/index.android.js.map +1 -1
  31. package/input/index.ios.d.ts +7 -3
  32. package/input/index.ios.js +18 -7
  33. package/input/index.ios.js.map +1 -1
  34. package/input/index.windows.d.ts +14 -2
  35. package/input/index.windows.js +143 -4
  36. package/input/index.windows.js.map +1 -1
  37. package/li/index.windows.js +4 -2
  38. package/li/index.windows.js.map +1 -1
  39. package/list/index.windows.d.ts +5 -2
  40. package/list/index.windows.js +26 -4
  41. package/list/index.windows.js.map +1 -1
  42. package/package.json +1 -1
  43. package/platforms/android/masonkit-release.aar +0 -0
  44. package/platforms/ios/Mason.xcframework/Info.plist +11 -11
  45. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Headers/Mason-Swift.h +14 -1
  46. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Mason +0 -0
  47. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
  48. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.abi.json +5091 -13148
  49. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.private.swiftinterface +28 -0
  50. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  51. package/platforms/ios/Mason.xcframework/ios-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios.swiftinterface +28 -0
  52. package/platforms/ios/Mason.xcframework/ios-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  53. package/platforms/ios/Mason.xcframework/ios-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8874 -8713
  54. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Headers/Mason-Swift.h +28 -2
  55. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Mason +0 -0
  56. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo +0 -0
  57. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo +0 -0
  58. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.abi.json +5091 -13148
  59. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +28 -0
  60. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  61. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-ios-simulator.swiftinterface +28 -0
  62. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.abi.json +5091 -13148
  63. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +28 -0
  64. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  65. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/Modules/Mason.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +28 -0
  66. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/Mason.framework/_CodeSignature/CodeResources +26 -26
  67. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  68. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8868 -8708
  69. package/platforms/ios/Mason.xcframework/ios-arm64_x86_64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/x86_64/Mason.yml +8467 -8310
  70. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Headers/Mason-Swift.h +14 -1
  71. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Mason +0 -0
  72. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-xros.swiftsourceinfo +0 -0
  73. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.abi.json +5091 -13148
  74. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.private.swiftinterface +28 -0
  75. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.swiftdoc +0 -0
  76. package/platforms/ios/Mason.xcframework/xros-arm64/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros.swiftinterface +28 -0
  77. package/platforms/ios/Mason.xcframework/xros-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  78. package/platforms/ios/Mason.xcframework/xros-arm64/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8366 -8204
  79. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Headers/Mason-Swift.h +14 -1
  80. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Mason +0 -0
  81. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/Project/arm64-apple-xros-simulator.swiftsourceinfo +0 -0
  82. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.abi.json +5091 -13148
  83. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.private.swiftinterface +28 -0
  84. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.swiftdoc +0 -0
  85. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/Modules/Mason.swiftmodule/arm64-apple-xros-simulator.swiftinterface +28 -0
  86. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/Mason.framework/_CodeSignature/CodeResources +14 -14
  87. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/DWARF/Mason +0 -0
  88. package/platforms/ios/Mason.xcframework/xros-arm64-simulator/dSYMs/Mason.framework.dSYM/Contents/Resources/Relocations/aarch64/Mason.yml +8365 -8204
  89. package/platforms/windows/arm64/NativeScript.Mason.dll +0 -0
  90. package/platforms/windows/arm64/NativeScript.Mason.winmd +0 -0
  91. package/platforms/windows/x64/NativeScript.Mason.dll +0 -0
  92. package/platforms/windows/x64/NativeScript.Mason.winmd +0 -0
  93. package/properties.js +1 -1
  94. package/properties.js.map +1 -1
  95. package/scroll/index.windows.js +4 -2
  96. package/scroll/index.windows.js.map +1 -1
  97. package/style.d.ts +28 -2
  98. package/style.js +291 -69
  99. package/style.js.map +1 -1
  100. package/symbols.d.ts +4 -0
  101. package/symbols.js +6 -2
  102. package/symbols.js.map +1 -1
  103. package/text/index.windows.d.ts +3 -0
  104. package/text/index.windows.js +39 -10
  105. package/text/index.windows.js.map +1 -1
  106. package/textarea/index.windows.d.ts +2 -0
  107. package/textarea/index.windows.js +5 -1
  108. package/textarea/index.windows.js.map +1 -1
  109. package/typings/android.d.ts +3 -0
  110. package/typings/objc!Mason.d.ts +4 -0
  111. package/typings/windows.d.ts +29 -1
  112. package/view/index.windows.js +4 -2
  113. package/view/index.windows.js.map +1 -1
  114. package/vue/src/element-registry.d.ts.map +1 -1
  115. package/vue/src/element-registry.js +4 -1
  116. package/vue/src/element-registry.js.map +1 -1
  117. package/vue/src/v-model.d.ts +27 -0
  118. package/vue/src/v-model.d.ts.map +1 -0
  119. package/vue/src/v-model.js +70 -0
  120. 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,7 @@ 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;
335
318
  this._masonClimbTurn = null;
336
319
  // `width`/`height` are core CssAnimationProperties whose stylesheet accessor
337
320
  // is non-configurable, so units Mason understands but core does not (`vh`,
@@ -342,6 +325,8 @@ export class ViewBase extends CustomLayoutView {
342
325
  }
343
326
  }
344
327
  get innerHTML() {
328
+ if (__WINDOWS__)
329
+ return this._windowsInnerHTML ?? '';
345
330
  //@ts-ignore
346
331
  const nativeView = this._view;
347
332
  if (__ANDROID__) {
@@ -357,6 +342,11 @@ export class ViewBase extends CustomLayoutView {
357
342
  return '';
358
343
  }
359
344
  set innerHTML(value) {
345
+ if (__WINDOWS__) {
346
+ this._windowsInnerHTML = value ?? '';
347
+ windowsInnerHTML?.(this, value ?? '');
348
+ return;
349
+ }
360
350
  //@ts-ignore
361
351
  const nativeView = this._view;
362
352
  if (__ANDROID__) {
@@ -399,6 +389,9 @@ export class ViewBase extends CustomLayoutView {
399
389
  nativeHit = hitTest.call(nativeView, x, y);
400
390
  }
401
391
  }
392
+ else if (__WINDOWS__ && typeof masonEngine().ElementFromPoint === 'function') {
393
+ nativeHit = masonEngine().ElementFromPoint(nativeView, x, y);
394
+ }
402
395
  if (!nativeHit)
403
396
  return null;
404
397
  const known = nativeOwnerFor(nativeHit);
@@ -444,7 +437,21 @@ export class ViewBase extends CustomLayoutView {
444
437
  callback['mason:event:id'] = id;
445
438
  }
446
439
  if (__WINDOWS__) {
447
- 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') {
448
455
  try {
449
456
  const NSWinRT_ = globalThis.NSWinRT;
450
457
  const MUX = globalThis.Microsoft;
@@ -519,7 +526,12 @@ export class ViewBase extends CustomLayoutView {
519
526
  }
520
527
  }
521
528
  if (__WINDOWS__) {
522
- 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')) {
523
535
  try {
524
536
  const view = this._view;
525
537
  const tappedEvent = callback['mason:event:tapped'];
@@ -650,6 +662,17 @@ export class ViewBase extends CustomLayoutView {
650
662
  const styles = compile(this);
651
663
  //@ts-ignore
652
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
+ }
653
676
  }
654
677
  _handler(subscribe) {
655
678
  const styles = compile(this);
@@ -665,6 +688,7 @@ export class ViewBase extends CustomLayoutView {
665
688
  this.off('mouseLeave', onWindowsActiveLeave);
666
689
  clearWindowsActive(this);
667
690
  }
691
+ this._windowsListenActive(subscribe);
668
692
  // A button dims while held only when it has no :active style of its own.
669
693
  // @ts-ignore
670
694
  const view = this._view;
@@ -672,6 +696,33 @@ export class ViewBase extends CustomLayoutView {
672
696
  view.DimsWhenPressed = !subscribe;
673
697
  }
674
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
+ }
675
726
  _disableHandler(subscribe) {
676
727
  const styles = compile(this);
677
728
  //@ts-ignore
@@ -681,6 +732,17 @@ export class ViewBase extends CustomLayoutView {
681
732
  const styles = compile(this);
682
733
  //@ts-ignore
683
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
+ }
684
746
  }
685
747
  _blurHandler(subscribe) {
686
748
  const styles = compile(this);
@@ -913,13 +975,13 @@ export class ViewBase extends CustomLayoutView {
913
975
  //@ts-ignore
914
976
  this._view.mason_append(child._view);
915
977
  }
916
- if (__WINDOWS__) {
917
- this._windowsAttachPlaceholder(child, -1);
918
- }
919
978
  if (this[isText_]) {
920
979
  child[isTextChild_] = true;
921
980
  }
922
981
  this._children.push(child);
982
+ if (__WINDOWS__) {
983
+ this._windowsAttachPlaceholder(child, -1);
984
+ }
923
985
  return;
924
986
  }
925
987
  if (child instanceof NSView) {
@@ -1007,9 +1069,9 @@ export class ViewBase extends CustomLayoutView {
1007
1069
  group = anonymous;
1008
1070
  continue;
1009
1071
  }
1010
- group = undefined;
1011
1072
  if (c[textNode_] || c instanceof TextNode || text_ in c || (c[isPlaceholder_] && c[native_]) || c._isMasonChild) {
1012
1073
  index++;
1074
+ group = undefined;
1013
1075
  }
1014
1076
  }
1015
1077
  return index;
@@ -1048,9 +1110,6 @@ export class ViewBase extends CustomLayoutView {
1048
1110
  }
1049
1111
  insertChild(child, atIndex) {
1050
1112
  this._invalidateAttachCursor();
1051
- if (__WINDOWS__) {
1052
- this._windowsSplitAnonymousText(atIndex);
1053
- }
1054
1113
  if (child && child[isPlaceholder_] && child._view) {
1055
1114
  const nativeIndex = this._nativeIndexFor(atIndex);
1056
1115
  this._children.splice(atIndex, 0, child);
@@ -1144,6 +1203,7 @@ export class ViewBase extends CustomLayoutView {
1144
1203
  }
1145
1204
  if (__WINDOWS__) {
1146
1205
  this._windowsDetachPlaceholder(child);
1206
+ this._windowsMergeAt(index);
1147
1207
  }
1148
1208
  child[isTextChild_] = false;
1149
1209
  this.requestLayout?.();
@@ -1164,7 +1224,6 @@ export class ViewBase extends CustomLayoutView {
1164
1224
  // Drop the proxy binding so a later re-adopt re-installs cleanly.
1165
1225
  child[textNodeProxied_] = false;
1166
1226
  child[textNode_] = undefined;
1167
- this._syncTextRunLayout();
1168
1227
  this.requestLayout?.();
1169
1228
  return;
1170
1229
  }
@@ -1173,6 +1232,9 @@ export class ViewBase extends CustomLayoutView {
1173
1232
  if (index > -1) {
1174
1233
  this._children.splice(index, 1);
1175
1234
  this._removeView(child);
1235
+ if (__WINDOWS__) {
1236
+ this._windowsMergeAt(index);
1237
+ }
1176
1238
  }
1177
1239
  }
1178
1240
  // Remove the native node directly when supported (no index drift), falling
@@ -1203,33 +1265,31 @@ export class ViewBase extends CustomLayoutView {
1203
1265
  if (typeof view.RemoveRun === 'function')
1204
1266
  view.RemoveRun(node);
1205
1267
  else
1206
- this._windowsRemoveAnonymousRun(index);
1268
+ this._windowsRemoveMember(this._children[index]);
1207
1269
  }
1208
1270
  }
1209
- // Windows text lays out TextNode runs, not child panels, so a placeholder inside one
1210
- // 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.
1211
1273
  _windowsAttachPlaceholder(child, index) {
1212
1274
  const view = this._view;
1213
1275
  if (!view)
1214
1276
  return;
1215
1277
  if (this._windowsHostsRuns()) {
1216
- let run = child[breakRun_];
1217
- if (!run) {
1218
- run = new NativeScript.Mason.TextNode();
1219
- run.SetBreak(true);
1220
- child[breakRun_] = run;
1221
- }
1222
- view.SetRun(run, index);
1278
+ view.SetRun(windowsBreakRun(child), index);
1223
1279
  }
1224
- else {
1225
- 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);
1226
1283
  }
1227
1284
  }
1228
1285
  _windowsDetachPlaceholder(child) {
1229
1286
  const view = this._view;
1230
1287
  if (!view)
1231
1288
  return;
1232
- 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') {
1233
1293
  view.RemoveRun(child[breakRun_]);
1234
1294
  }
1235
1295
  else {
@@ -1249,6 +1309,12 @@ export class ViewBase extends CustomLayoutView {
1249
1309
  }
1250
1310
  if (__WINDOWS__) {
1251
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
+ }
1252
1318
  }
1253
1319
  this._children.splice(0);
1254
1320
  this._invalidateAttachCursor();
@@ -1261,6 +1327,13 @@ export class ViewBase extends CustomLayoutView {
1261
1327
  style.zIndex = value;
1262
1328
  }
1263
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
+ }
1264
1337
  set verticalAlign(value) {
1265
1338
  this.style.verticalAlign = value;
1266
1339
  }
@@ -1471,17 +1544,22 @@ export class ViewBase extends CustomLayoutView {
1471
1544
  const anonymous = this._windowsNeedsAnonymousText();
1472
1545
  switch (operation.type) {
1473
1546
  case 'add':
1474
- if (anonymous)
1475
- entry[anonymousText_] = this._windowsAddAnonymousRun(textNode, this._children.length, false);
1476
- else
1477
- 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);
1478
1554
  //@ts-ignore
1479
1555
  this._children.push({ ...entry, [textNodeIndex_]: this._children.length });
1480
1556
  break;
1481
1557
  case 'replace':
1482
- if (anonymous)
1483
- entry[anonymousText_] = this._windowsAddAnonymousRun(textNode, operation.index, true);
1484
- 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)
1485
1563
  this._nativeReplaceChild(textNode, operation.index);
1486
1564
  this._setOrPushChild(operation.index, entry);
1487
1565
  break;
@@ -1490,15 +1568,16 @@ export class ViewBase extends CustomLayoutView {
1490
1568
  // lag behind it (elements attach lazily on `loaded`), so map it the
1491
1569
  // same way `insertChild` does or the run lands past the end.
1492
1570
  const index = Math.max(0, Math.min(operation.index ?? this._children.length, this._children.length));
1493
- if (anonymous)
1494
- entry[anonymousText_] = this._windowsAddAnonymousRun(textNode, index, false);
1495
- else
1496
- 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));
1497
1577
  this._spliceOrPushChild(index, entry);
1498
1578
  break;
1499
1579
  }
1500
1580
  }
1501
- this._syncTextRunLayout();
1502
1581
  }
1503
1582
  // Only Text lays out runs on Windows, so any other container puts consecutive runs in one
1504
1583
  // anonymous Text, as Android's getOrCreateAnonymousTextContainer does.
@@ -1525,71 +1604,399 @@ export class ViewBase extends CustomLayoutView {
1525
1604
  }
1526
1605
  return hosts;
1527
1606
  }
1528
- _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();
1529
1625
  const children = this._children;
1530
- const old = replace ? children[slot] : undefined;
1531
- const current = old?.[anonymousText_];
1532
- if (current) {
1533
- if (old[textNode_] !== textNode) {
1534
- const at = this._windowsRunsBefore(slot, current);
1535
- current.RemoveRun(old[textNode_]);
1536
- current.SetRun(textNode, at);
1537
- }
1538
- return current;
1539
- }
1540
- const prev = children[slot - 1]?.[anonymousText_];
1541
- if (prev) {
1542
- prev.SetRun(textNode, this._windowsRunsBefore(slot, prev));
1543
- return prev;
1544
- }
1545
- const next = children[replace ? slot + 1 : slot]?.[anonymousText_];
1546
- if (next) {
1547
- next.SetRun(textNode, 0);
1548
- return next;
1549
- }
1550
- const anonymous = this._windowsCreateAnonymousText(this._nativeIndexFor(slot));
1551
- anonymous.SetRun(textNode, 0);
1552
- 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';
1553
1658
  }
1554
- _windowsRunsBefore(slot, anonymous) {
1555
- let n = 0;
1556
- for (let i = slot - 1; i >= 0 && this._children[i]?.[anonymousText_] === anonymous; i--)
1557
- n++;
1558
- 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;
1559
1662
  }
1560
- _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() {
1561
1818
  const anonymous = new NativeScript.Mason.Text();
1819
+ anonymous.IsAnonymous = true;
1562
1820
  // @ts-ignore
1563
- this._styleHelper?.copyTextStyleTo(anonymous);
1821
+ this._styleHelper?.copyTextStyleTo(anonymous, -1, -1, -1, -1, true);
1564
1822
  const font = this[windowsFontSource_];
1565
1823
  if (font)
1566
1824
  anonymous.SetFontFamily(font);
1567
- masonEngine().ReparentChild(this._view, anonymous, nativeIndex);
1568
1825
  return anonymous;
1569
1826
  }
1570
- _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) {
1571
1832
  const children = this._children;
1572
- const anonymous = children[index]?.[anonymousText_];
1573
- if (!anonymous)
1833
+ const view = this._view;
1834
+ if (!view || children.length === 0)
1574
1835
  return;
1575
- anonymous.RemoveRun(children[index][textNode_]);
1576
- if (children[index - 1]?.[anonymousText_] !== anonymous && children[index + 1]?.[anonymousText_] !== anonymous) {
1577
- 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
+ }
1578
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
+ }
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;
1579
1925
  }
1580
- // An element landing between two runs of one anonymous Text splits it, so the runs after it
1581
- // render after it.
1582
- _windowsSplitAnonymousText(slot) {
1583
- const children = this._children;
1584
- const anonymous = children[slot - 1]?.[anonymousText_];
1585
- if (!anonymous || children[slot]?.[anonymousText_] !== anonymous)
1926
+ _windowsMergeAt(slot) {
1927
+ if (!this._windowsNeedsAnonymousText() || this._children.length === 0)
1586
1928
  return;
1587
- const tail = this._windowsCreateAnonymousText(this._nativeIndexFor(slot));
1588
- for (let i = slot, k = 0; children[i]?.[anonymousText_] === anonymous; i++, k++) {
1589
- anonymous.RemoveRun(children[i][textNode_]);
1590
- tail.SetRun(children[i][textNode_], k);
1591
- 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();
1592
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;
1593
2000
  }
1594
2001
  _forEachAnonymousText(fn) {
1595
2002
  let last;
@@ -1600,11 +2007,11 @@ export class ViewBase extends CustomLayoutView {
1600
2007
  last = anonymous;
1601
2008
  }
1602
2009
  }
1603
- _windowsSyncAnonymousText() {
2010
+ _windowsSyncAnonymousText(d0, d1, d2, d3) {
1604
2011
  // @ts-ignore
1605
2012
  const style = this._styleHelper;
1606
2013
  if (style)
1607
- this._forEachAnonymousText((anonymous) => style.copyTextStyleTo(anonymous));
2014
+ this._forEachAnonymousText((anonymous) => style.copyTextStyleTo(anonymous, d0, d1, d2, d3));
1608
2015
  }
1609
2016
  [fontInternalProperty.setNative](value) {
1610
2017
  if (!__WINDOWS__)
@@ -1613,20 +2020,6 @@ export class ViewBase extends CustomLayoutView {
1613
2020
  this[windowsFontSource_] = source;
1614
2021
  this._forEachAnonymousText((anonymous) => anonymous.SetFontFamily(source));
1615
2022
  }
1616
- _syncTextRunLayout() {
1617
- if (!__WINDOWS__ || !this._windowsHostsRuns())
1618
- return;
1619
- // @ts-ignore
1620
- const sh = this._styleHelper;
1621
- if (!sh || sh.display === 'block')
1622
- return;
1623
- try {
1624
- sh.display = 'block';
1625
- }
1626
- catch (_) {
1627
- // empty
1628
- }
1629
- }
1630
2023
  // -- Text setter: framework adapter driven --
1631
2024
  [textProperty.setNative](value) {
1632
2025
  const adapter = frameworkRegistry.find(this);
@@ -2016,6 +2409,12 @@ export class ViewBase extends CustomLayoutView {
2016
2409
  // @ts-ignore
2017
2410
  this.nativeView.style.applyListStyleType(String(value));
2018
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
+ }
2019
2418
  }
2020
2419
  // @ts-ignore
2021
2420
  [listStylePositionProperty.setNative](value) {
@@ -2027,6 +2426,12 @@ export class ViewBase extends CustomLayoutView {
2027
2426
  // @ts-ignore
2028
2427
  this.nativeView.style.applyListStylePosition(String(value));
2029
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
+ }
2030
2435
  }
2031
2436
  get boxSizing() {
2032
2437
  return this.style.boxSizing;
@@ -2729,15 +3134,21 @@ export class ViewBase extends CustomLayoutView {
2729
3134
  // @ts-ignore
2730
3135
  style.boxShadow = value;
2731
3136
  if (__WINDOWS__) {
2732
- // box-shadow isn't a Mason buffer prop — render it as a Composition DropShadow on the element
2733
- // (masked to its rounded-rect shape, re-applied on resize). The corner radius is read natively.
2734
3137
  const nv = this.nativeViewProtected ?? this._view;
2735
3138
  try {
2736
- const sh = parseBoxShadow(typeof value === 'string' ? value : '');
2737
- if (!sh)
2738
- NativeScript.Mason.Css.ClearShadow(nv);
2739
- else
2740
- 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);
2741
3152
  }
2742
3153
  catch (_) { }
2743
3154
  }
@@ -2755,11 +3166,14 @@ export class ViewBase extends CustomLayoutView {
2755
3166
  // doesn't drive transforms on). Parse the CSS string to a matrix and set RenderTransform.
2756
3167
  const nv = this.nativeViewProtected ?? this._view;
2757
3168
  try {
2758
- const mtx = parseCssTransformToMatrix(typeof value === 'string' ? value : '');
2759
- 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)
2760
3172
  NativeScript.Mason.Css.ClearTransform(nv);
2761
- else
2762
- 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
+ }
2763
3177
  }
2764
3178
  catch (_) { }
2765
3179
  }
@@ -2801,7 +3215,7 @@ __decorate([
2801
3215
  textProperty.register(ViewBase);
2802
3216
  // Core's Windows Font resolves app/fonts files to an ms-appx URI (and generics to system fonts);
2803
3217
  // the bare family name only finds installed fonts.
2804
- function windowsFontSource(font) {
3218
+ export function windowsFontSource(font) {
2805
3219
  try {
2806
3220
  const source = font?.getWindowsFontDescriptor?.()?.fontFamilyNative?.Source;
2807
3221
  if (source)
@@ -3009,7 +3423,16 @@ export class Event {
3009
3423
  }
3010
3424
  set button(_) { }
3011
3425
  get target() {
3012
- 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;
3013
3436
  }
3014
3437
  set target(_) { }
3015
3438
  get object() {
@@ -3058,6 +3481,15 @@ export class InputEvent extends Event {
3058
3481
  return this[native_]?.data;
3059
3482
  }
3060
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
+ }
3061
3493
  return this[native_]?.Data ?? null;
3062
3494
  }
3063
3495
  return false;
@@ -3075,6 +3507,11 @@ export class InputEvent extends Event {
3075
3507
  return false;
3076
3508
  }
3077
3509
  }
3510
+ export class CompositionEvent extends Event {
3511
+ get data() {
3512
+ return this[native_]?.Data ?? '';
3513
+ }
3514
+ }
3078
3515
  /** DOM KeyboardEvent: dispatched on Windows. */
3079
3516
  export class KeyboardEvent extends Event {
3080
3517
  get key() {
@@ -3103,6 +3540,10 @@ function wrapNativeEvent(type) {
3103
3540
  return new InputEvent();
3104
3541
  case 'keydown':
3105
3542
  return new KeyboardEvent();
3543
+ case 'compositionstart':
3544
+ case 'compositionupdate':
3545
+ case 'compositionend':
3546
+ return new CompositionEvent();
3106
3547
  default:
3107
3548
  return new Event();
3108
3549
  }