@effindomv2/fui-as 0.1.37 → 0.1.39

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 (118) hide show
  1. package/browser/routed-app-conventions.ts +1 -1
  2. package/browser/src/common-harness.ts +1 -27
  3. package/browser/src/index.ts +19 -26
  4. package/browser/src/routed-harness.ts +1 -194
  5. package/browser/src/shared-browser.ts +6 -0
  6. package/package.json +23 -13
  7. package/scripts/build.sh +47 -46
  8. package/scripts/framework-host-services.ts +1 -1
  9. package/scripts/generate-host-events.ts +15 -241
  10. package/scripts/generate-host-services.ts +13 -261
  11. package/scripts/hostgen/assemblyscript-host-events.ts +165 -0
  12. package/scripts/hostgen/assemblyscript-host-services.ts +207 -0
  13. package/scripts/hostgen/common.ts +73 -0
  14. package/scripts/hostgen/registry.ts +159 -0
  15. package/src/Fui.ts +65 -5
  16. package/src/FuiExports.ts +12 -1
  17. package/src/bindings/ui.ts +157 -8
  18. package/src/controls/Button.ts +98 -71
  19. package/src/controls/Checkbox.ts +23 -21
  20. package/src/controls/ComboBox.ts +1201 -0
  21. package/src/controls/ContextMenu.ts +279 -165
  22. package/src/controls/Dialog.ts +91 -17
  23. package/src/controls/Dropdown.ts +101 -333
  24. package/src/controls/NavLink.ts +29 -6
  25. package/src/controls/Popup.ts +10 -5
  26. package/src/controls/ProgressBar.ts +1 -2
  27. package/src/controls/RadioButton.ts +34 -13
  28. package/src/controls/RadioGroup.ts +32 -19
  29. package/src/controls/Slider.ts +21 -23
  30. package/src/controls/Switch.ts +34 -17
  31. package/src/controls/index.ts +2 -1
  32. package/src/controls/internal/ButtonPresenter.ts +5 -2
  33. package/src/controls/internal/CheckboxIndicatorPresenter.ts +10 -10
  34. package/src/controls/internal/DropdownChevronPresenter.ts +3 -3
  35. package/src/controls/internal/DropdownFieldPresenter.ts +6 -6
  36. package/src/controls/internal/DropdownOptionRowPresenter.ts +5 -4
  37. package/src/controls/internal/PressableLabeledControl.ts +4 -7
  38. package/src/controls/internal/RadioIndicatorPresenter.ts +7 -7
  39. package/src/controls/internal/SelectablePopupList.ts +463 -0
  40. package/src/controls/internal/SliderPresenter.ts +5 -5
  41. package/src/controls/internal/SwitchIndicatorPresenter.ts +63 -17
  42. package/src/controls/internal/TextInputCore.ts +307 -41
  43. package/src/controls/internal/TextInputPresenter.ts +2 -2
  44. package/src/controls/templating.ts +10 -0
  45. package/src/core/Application.ts +17 -8
  46. package/src/core/Bitmap.ts +192 -3
  47. package/src/core/ContextMenuManager.ts +128 -44
  48. package/src/core/DebugApi.ts +17 -2
  49. package/src/core/DragGesture.ts +8 -7
  50. package/src/core/EventRouter.ts +332 -12
  51. package/src/core/Fetch.ts +15 -7
  52. package/src/core/FetchFfi.ts +1 -15
  53. package/src/core/File.ts +75 -34
  54. package/src/core/FocusAdornerManager.ts +3 -3
  55. package/src/core/FocusVisibility.ts +7 -0
  56. package/src/core/FrameScheduler.ts +104 -5
  57. package/src/core/ImageSampling.ts +43 -0
  58. package/src/core/Logger.ts +2 -0
  59. package/src/core/MobileTextSelectionToolbarManager.ts +901 -0
  60. package/src/core/Node.ts +1039 -97
  61. package/src/core/Platform.ts +16 -16
  62. package/src/core/SelectionHandleAdornerManager.ts +697 -0
  63. package/src/core/Theme.ts +34 -20
  64. package/src/core/ToolTipManager.ts +3 -3
  65. package/src/core/Typography.ts +411 -19
  66. package/src/core/Worker.ts +69 -33
  67. package/src/core/event_exports.ts +123 -5
  68. package/src/core/ffi.ts +5 -865
  69. package/src/core/generated/FetchHostAbi.ts +10 -0
  70. package/src/core/generated/FrameworkHostServices.ts +1 -1
  71. package/src/core/generated/HostAbi.ts +220 -0
  72. package/src/core/generated/UiAbi.ts +356 -0
  73. package/src/core/generated/UiEnums.ts +186 -0
  74. package/src/drawing/DrawCallback.ts +17 -1
  75. package/src/drawing/DrawContext.ts +140 -32
  76. package/src/nodes/CustomDrawable.ts +8 -1
  77. package/src/nodes/FlexBox.ts +40 -11
  78. package/src/nodes/Grid.ts +5 -5
  79. package/src/nodes/Image.ts +20 -1
  80. package/src/nodes/RichText.ts +36 -25
  81. package/src/nodes/ScrollBar.ts +2 -1
  82. package/src/nodes/ScrollBox.ts +7 -2
  83. package/src/nodes/ScrollView.ts +17 -6
  84. package/src/nodes/Svg.ts +18 -1
  85. package/src/nodes/Text.ts +1 -1
  86. package/src/nodes/TextCore.ts +115 -20
  87. package/src/nodes/index.ts +1 -1
  88. package/src/text/DynamicTextLayout.ts +275 -0
  89. package/src/text/TextLayout.ts +308 -0
  90. package/src/worker/Worker.ts +3 -36
  91. package/src/worker/WorkerJob.ts +5 -9
  92. package/src/worker/ffi.ts +0 -6
  93. package/browser/src/common-harness/host-imports.ts +0 -447
  94. package/browser/src/common-harness/interop.ts +0 -39
  95. package/browser/src/common-harness/managed-harness-bitmap-host.ts +0 -92
  96. package/browser/src/common-harness/managed-harness-canvas-host.ts +0 -72
  97. package/browser/src/common-harness/managed-harness-fetch-host.ts +0 -201
  98. package/browser/src/common-harness/managed-harness-file-host.ts +0 -1066
  99. package/browser/src/common-harness/managed-harness-file-payloads.ts +0 -143
  100. package/browser/src/common-harness/managed-harness-file-types.ts +0 -71
  101. package/browser/src/common-harness/managed-harness-session.ts +0 -15
  102. package/browser/src/common-harness/managed-harness.ts +0 -1472
  103. package/browser/src/common-harness/managed-history.ts +0 -168
  104. package/browser/src/common-harness/persisted-restore-policy.ts +0 -50
  105. package/browser/src/common-harness/persisted-ui-state-controller.ts +0 -309
  106. package/browser/src/common-harness/text-session-bridge.ts +0 -452
  107. package/browser/src/common-harness/types.ts +0 -206
  108. package/browser/src/common-harness/ui-chrome.ts +0 -206
  109. package/browser/src/common-harness/ui-imports.ts +0 -559
  110. package/browser/src/common-harness/wasm-module-cache.ts +0 -47
  111. package/browser/src/file-processing-worker.ts +0 -89
  112. package/browser/src/host-events.ts +0 -118
  113. package/browser/src/host-services.ts +0 -483
  114. package/browser/src/persisted-ui-state.ts +0 -206
  115. package/browser/src/routed-app-conventions.ts +0 -292
  116. package/browser/src/worker-bootstrap.ts +0 -916
  117. package/browser/src/worker-manager.ts +0 -234
  118. package/browser/src/worker-types.ts +0 -68
@@ -147,10 +147,20 @@ export function span(text: string): RichTextSpan {
147
147
 
148
148
  const STYLE_RUN_WORD_STRIDE: i32 = 7;
149
149
 
150
+ function pushUniqueFontId(fontIds: Array<u32>, fontId: u32): void {
151
+ if (fontId == 0) {
152
+ return;
153
+ }
154
+ for (let index = 0; index < fontIds.length; ++index) {
155
+ if (unchecked(fontIds[index]) == fontId) {
156
+ return;
157
+ }
158
+ }
159
+ fontIds.push(fontId);
160
+ }
161
+
150
162
  export class RichText extends Text {
151
163
  private hasBaseFontValue: bool = false;
152
- private baseUsesDirectFontId: bool = false;
153
- private baseFontIdValue: u32 = 0;
154
164
  private baseFontFamilyValue: FontFamily | null = null;
155
165
  private hasBaseFontSizeValue: bool = false;
156
166
  private baseFontSizeValue: f32 = 0.0;
@@ -176,27 +186,17 @@ export class RichText extends Text {
176
186
  return this;
177
187
  }
178
188
 
179
- font(fontId: u32, size: f32): this {
189
+ fontStack(stack: FontStack, size: f32): this {
180
190
  this.hasBaseFontValue = true;
181
- this.baseUsesDirectFontId = true;
182
- this.baseFontIdValue = fontId;
183
- this.baseFontFamilyValue = null;
191
+ this.baseFontFamilyValue = FontFamily.withRegularStack(stack);
184
192
  this.hasBaseFontSizeValue = true;
185
193
  this.baseFontSizeValue = size;
186
- if (fontId == 0) {
187
- warn("Typography", "RichText.font() received font id 0; the text will render with the default font fallback.");
188
- }
189
194
  this.rebuildAttributedText();
190
195
  return this;
191
196
  }
192
197
 
193
- fontStack(stack: FontStack, size: f32): this {
194
- return this.font(stack.id, size);
195
- }
196
-
197
198
  fontFamily(family: FontFamily): this {
198
199
  this.hasBaseFontValue = true;
199
- this.baseUsesDirectFontId = false;
200
200
  this.baseFontFamilyValue = family;
201
201
  this.rebuildAttributedText();
202
202
  return this;
@@ -247,6 +247,23 @@ export class RichText extends Text {
247
247
  return this.fragmentsValue([span(content)]);
248
248
  }
249
249
 
250
+ _requiredFontIds(): Array<u32> {
251
+ const fontIds = super._requiredFontIds();
252
+ const fonts = activeTheme.value.fonts;
253
+ const defaultFamily = this.baseFontFamilyValue !== null ? changetype<FontFamily>(this.baseFontFamilyValue) : fonts.bodyFamily;
254
+ const defaultWeight = this.hasBaseFontWeightValue ? this.baseFontWeightValue : FontWeight.Regular;
255
+ const defaultStyle = this.hasBaseFontStyleValue ? this.baseFontStyleValue : FontStyle.Normal;
256
+ for (let i = 0; i < this.fragments.length; ++i) {
257
+ const piece = unchecked(this.fragments[i]);
258
+ const pieceFamily = piece._hasFontFamily() ? piece._fontFamilyOr(defaultFamily) : defaultFamily;
259
+ const pieceWeight = piece._fontWeightOr(defaultWeight);
260
+ const pieceStyle = piece._fontStyleOr(defaultStyle);
261
+ const resolvedFontId = pieceFamily.resolve(pieceWeight, pieceStyle);
262
+ pushUniqueFontId(fontIds, resolvedFontId);
263
+ }
264
+ return fontIds;
265
+ }
266
+
250
267
  private rebuildAttributedText(): void {
251
268
  const fonts = activeTheme.value.fonts;
252
269
  const defaultFamily = this.baseFontFamilyValue !== null ? changetype<FontFamily>(this.baseFontFamilyValue) : fonts.bodyFamily;
@@ -255,14 +272,10 @@ export class RichText extends Text {
255
272
  const defaultSize = this.hasBaseFontSizeValue ? this.baseFontSizeValue : fonts.sizeBody;
256
273
  const defaultColor = this.hasBaseColorValue ? this.baseColorValue : activeTheme.value.colors.textPrimary;
257
274
  if (this.hasBaseFontValue || this.fragments.length > 0) {
258
- if (this.baseUsesDirectFontId) {
259
- super.font(this.baseFontIdValue, defaultSize);
260
- } else {
261
- super.font(
262
- defaultFamily.resolve(defaultWeight, defaultStyle),
263
- defaultSize,
264
- );
265
- }
275
+ super._fontId(
276
+ defaultFamily.resolve(defaultWeight, defaultStyle),
277
+ defaultSize,
278
+ );
266
279
  }
267
280
  super.textColor(defaultColor);
268
281
  let merged = "";
@@ -285,9 +298,7 @@ export class RichText extends Text {
285
298
  const pieceFamily = piece._hasFontFamily() ? piece._fontFamilyOr(defaultFamily) : defaultFamily;
286
299
  const pieceWeight = piece._fontWeightOr(defaultWeight);
287
300
  const pieceStyle = piece._fontStyleOr(defaultStyle);
288
- const resolvedFontId = this.baseUsesDirectFontId && !piece._hasFontFamily()
289
- ? this.baseFontIdValue
290
- : pieceFamily.resolve(pieceWeight, pieceStyle);
301
+ const resolvedFontId = pieceFamily.resolve(pieceWeight, pieceStyle);
291
302
  if (resolvedFontId == 0) {
292
303
  warn(
293
304
  "Typography",
@@ -8,6 +8,7 @@ import { isCoarsePointer } from "../core/Platform";
8
8
  import { Signal } from "../core/Signal";
9
9
  import { Theme, activeTheme } from "../core/Theme";
10
10
  import { warn } from "../core/Logger";
11
+ import { PointerEventArgs } from "../core/Node";
11
12
  import { FlexBox } from "./FlexBox";
12
13
  import { Column } from "./helpers";
13
14
  import { ScrollState } from "./ScrollState";
@@ -16,7 +17,7 @@ const DEFAULT_TRACK_WIDTH: f32 = 8.0;
16
17
  const DEFAULT_THUMB_WIDTH: f32 = 8.0;
17
18
  const DEFAULT_MIN_THUMB_HEIGHT: f32 = 18.0;
18
19
 
19
- function noopPointerCallback(_x: f32, _y: f32): void {}
20
+ function noopPointerCallback(_event: PointerEventArgs): void {}
20
21
 
21
22
  class ScrollMetrics {
22
23
  viewportSize: f32 = 0.0;
@@ -2,7 +2,7 @@ import { HandlerAction } from "../core/Action";
2
2
  import { AnimationTiming } from "../core/Animation";
3
3
  import { Disposable, disposeAll } from "../core/Disposable";
4
4
  import { HandleValue, Orientation, Unit } from "../core/ffi";
5
- import { Node } from "../core/Node";
5
+ import { Node, PointerEventArgs } from "../core/Node";
6
6
  import { throwNullArgument } from "../core/Errors";
7
7
  import {
8
8
  canRestorePersistedScrollOffset,
@@ -20,7 +20,7 @@ import { NodeTransitions } from "../core/Transitions";
20
20
  const DEFAULT_SCROLLBAR_GUTTER: f32 = 0.0;
21
21
  const OVERFLOW_TOLERANCE: f32 = 0.5;
22
22
 
23
- function noopPointerCallback(_x: f32, _y: f32): void {}
23
+ function noopPointerCallback(_event: PointerEventArgs): void {}
24
24
 
25
25
  export class ScrollBox extends FlexBox {
26
26
  private readonly scrollStateValue: ScrollState;
@@ -140,6 +140,11 @@ export class ScrollBox extends FlexBox {
140
140
  return this;
141
141
  }
142
142
 
143
+ smoothScrolling(flag: bool = true): this {
144
+ this.viewportValue.smoothScrolling(flag);
145
+ return this;
146
+ }
147
+
143
148
  persistScroll(flag: bool = true): this {
144
149
  this.persistScrollValue = flag;
145
150
  if (!flag) {
@@ -1,6 +1,6 @@
1
1
  import * as ui from "../bindings/ui";
2
2
  import { Animation, AnimationTiming, getAnimationManager } from "../core/Animation";
3
- import { Node } from "../core/Node";
3
+ import { PointerClickEventArgs, PointerEventArgs, Node } from "../core/Node";
4
4
  import { throwNullArgument } from "../core/Errors";
5
5
  import { NodeTransitions } from "../core/Transitions";
6
6
  import {
@@ -75,6 +75,7 @@ export class ScrollView extends Node {
75
75
  private pendingProgrammaticOffsetX: f32 = 0.0;
76
76
  private pendingProgrammaticOffsetY: f32 = 0.0;
77
77
  private hasFriction: bool = false;
78
+ private smoothScrollingValue: bool = true;
78
79
  private _scrollState: ScrollState = new ScrollState();
79
80
  private persistScrollValue: bool = true;
80
81
  private persistedScrollRestorePending: bool = false;
@@ -97,7 +98,7 @@ export class ScrollView extends Node {
97
98
  super();
98
99
  // Make the viewport hit-testable so blank interior/padding starts resolve to this
99
100
  // scroll surface instead of only working over interactive descendants.
100
- this.onPointerDown((_x: f32, _y: f32): void => {});
101
+ this.onPointerDown((_event: PointerEventArgs): void => {});
101
102
  }
102
103
 
103
104
  bindScrollState(state: ScrollState): this {
@@ -286,6 +287,15 @@ export class ScrollView extends Node {
286
287
  return this;
287
288
  }
288
289
 
290
+ smoothScrolling(flag: bool = true): this {
291
+ this.smoothScrollingValue = flag;
292
+ if (this.hasBuiltHandle()) {
293
+ ui.setSmoothScrolling(this.handle, flag);
294
+ this.notifyRetainedMutation();
295
+ }
296
+ return this;
297
+ }
298
+
289
299
  persistScroll(flag: bool = true): this {
290
300
  this.persistScrollValue = flag;
291
301
  if (!flag) {
@@ -357,17 +367,17 @@ export class ScrollView extends Node {
357
367
  this._applyAnimatedScrollOffset(x, y);
358
368
  }
359
369
 
360
- onClick(cb: () => void): this {
361
- super.onClick(cb);
370
+ onPointerClick(cb: (event: PointerClickEventArgs) => void): this {
371
+ super.onPointerClick(cb);
362
372
  return this;
363
373
  }
364
374
 
365
- onPointerEnter(cb: () => void): this {
375
+ onPointerEnter(cb: (event: PointerEventArgs) => void): this {
366
376
  super.onPointerEnter(cb);
367
377
  return this;
368
378
  }
369
379
 
370
- onPointerLeave(cb: () => void): this {
380
+ onPointerLeave(cb: (event: PointerEventArgs) => void): this {
371
381
  super.onPointerLeave(cb);
372
382
  return this;
373
383
  }
@@ -395,6 +405,7 @@ export class ScrollView extends Node {
395
405
  this.finishBuild();
396
406
  ui.setScrollEnabled(this.handle, this.enableScrollX, this.enableScrollY);
397
407
  ui.setShowScrollbars(this.handle, this.showScrollbarsValue);
408
+ ui.setSmoothScrolling(this.handle, this.smoothScrollingValue);
398
409
  if (this.hasFriction) {
399
410
  ui.setScrollFriction(this.handle, this.frictionValue);
400
411
  }
package/src/nodes/Svg.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  import { Action, HandlerAction } from "../core/Action";
12
12
  import * as ui from "../bindings/ui";
13
13
  import { NodeType, SemanticRole, Unit } from "../core/ffi";
14
+ import { ImageSampling } from "../core/ImageSampling";
14
15
  import { Signal } from "../core/Signal";
15
16
  import { FlexBox, FlexBoxProps } from "./FlexBox";
16
17
 
@@ -18,6 +19,7 @@ export class Svg extends FlexBox {
18
19
  private svgIdValue: u32;
19
20
  private sourceUrlValue: string = "";
20
21
  private tintColorValue: u32 = 0;
22
+ private samplingValue: ImageSampling = ImageSampling.linear();
21
23
  private ownedSvgAssetId: u32 = 0;
22
24
  private requestedWidthValue: f32 = 0.0;
23
25
  private requestedWidthUnit: Unit = Unit.Auto;
@@ -119,6 +121,15 @@ export class Svg extends FlexBox {
119
121
  return this;
120
122
  }
121
123
 
124
+ sampling(sampling: ImageSampling): this {
125
+ this.samplingValue = sampling;
126
+ if (this.hasBuiltHandle()) {
127
+ this.applySvgSource();
128
+ this.notifyRetainedMutation();
129
+ }
130
+ return this;
131
+ }
132
+
122
133
  altText(value: string): this {
123
134
  this.semanticRole(SemanticRole.Image);
124
135
  this.semanticLabel(value);
@@ -163,7 +174,13 @@ export class Svg extends FlexBox {
163
174
  }
164
175
 
165
176
  private applySvgSource(): void {
166
- ui.setSvg(this.handle, this.svgIdValue, this.tintColorValue);
177
+ ui.setSvg(
178
+ this.handle,
179
+ this.svgIdValue,
180
+ this.tintColorValue,
181
+ <u32>this.samplingValue.kind,
182
+ this.samplingValue.maxAniso,
183
+ );
167
184
  }
168
185
 
169
186
  private applyResolvedSizing(): void {
package/src/nodes/Text.ts CHANGED
@@ -51,7 +51,7 @@ export class Text extends TextCore {
51
51
  if (props.hasFont && props.hasFontFamily) {
52
52
  text.fontSize(props.fontSize);
53
53
  } else if (props.hasFont) {
54
- text.font(props.fontId, props.fontSize);
54
+ text._fontId(props.fontId, props.fontSize);
55
55
  }
56
56
  if (props.hasFontWeight) {
57
57
  text.fontWeight(props.fontWeightValue);
@@ -1,7 +1,7 @@
1
1
  import * as ui from "../bindings/ui";
2
2
  import { HandlerAction } from "../core/Action";
3
3
  import { Disposable, disposeAll } from "../core/Disposable";
4
- import { Node } from "../core/Node";
4
+ import { PointerClickEventArgs, PointerEventArgs, Node, SelectionChangedEventArgs, TextChangedEventArgs } from "../core/Node";
5
5
  import { warn } from "../core/Logger";
6
6
  import { Theme, activeTheme } from "../core/Theme";
7
7
  import { FontFamily, FontStack, FontStyle, FontWeight } from "../core/Typography";
@@ -78,6 +78,62 @@ export class TextProps {
78
78
  hasSelectable: bool = false;
79
79
  }
80
80
 
81
+ function utf8CodeUnitByteLength(codeUnit: u32): u32 {
82
+ if (codeUnit <= 0x7F) {
83
+ return 1;
84
+ }
85
+ if (codeUnit <= 0x7FF) {
86
+ return 2;
87
+ }
88
+ return 3;
89
+ }
90
+
91
+ function utf8CodePointByteLength(codePoint: u32): u32 {
92
+ if (codePoint <= 0x7F) {
93
+ return 1;
94
+ }
95
+ if (codePoint <= 0x7FF) {
96
+ return 2;
97
+ }
98
+ if (codePoint <= 0xFFFF) {
99
+ return 3;
100
+ }
101
+ return 4;
102
+ }
103
+
104
+ function readCodePoint(text: string, index: i32): u32 {
105
+ const first = <u32>text.charCodeAt(index);
106
+ if (first < 0xD800 || first > 0xDBFF || index + 1 >= text.length) {
107
+ return first;
108
+ }
109
+ const second = <u32>text.charCodeAt(index + 1);
110
+ if (second < 0xDC00 || second > 0xDFFF) {
111
+ return first;
112
+ }
113
+ return 0x10000 + ((first - 0xD800) << 10) + (second - 0xDC00);
114
+ }
115
+
116
+ function codePointStringLength(codePoint: u32): i32 {
117
+ return codePoint > 0xFFFF ? 2 : 1;
118
+ }
119
+
120
+ function stringOffsetFromUtf8ByteOffset(text: string, byteOffset: u32): i32 {
121
+ let bytes: u32 = 0;
122
+ let cursor = 0;
123
+ while (cursor < text.length) {
124
+ const codePoint = readCodePoint(text, cursor);
125
+ const byteLength = codePoint > 0xFFFF
126
+ ? utf8CodePointByteLength(codePoint)
127
+ : utf8CodeUnitByteLength(codePoint);
128
+ if (bytes + byteLength > byteOffset) {
129
+ break;
130
+ }
131
+ bytes += byteLength;
132
+ cursor += codePointStringLength(codePoint);
133
+ }
134
+ return cursor;
135
+ }
136
+
81
137
  export class TextCore extends Node {
82
138
  private contentValue: string;
83
139
  private widthValue: f32 = 0.0;
@@ -133,13 +189,17 @@ export class TextCore extends Node {
133
189
  private hasObscured: bool = false;
134
190
  private editableValue: bool = false;
135
191
  private hasEditable: bool = false;
192
+ private editorCommandKeysValue: bool = false;
193
+ private hasEditorCommandKeys: bool = false;
194
+ private editorAcceptsTabValue: bool = false;
195
+ private hasEditorAcceptsTab: bool = false;
136
196
  private caretColorValue: u32 = 0;
137
197
  private hasCaretColor: bool = false;
138
198
  private selectableValue: bool = false;
139
199
  private selectionColor: u32 = 0;
140
200
  private hasSelectable: bool = false;
141
- private textChangedCb: ((text: string) => void) | null = null;
142
- private selectionChangedCb: ((start: u32, end: u32) => void) | null = null;
201
+ private textChangedCb: ((event: TextChangedEventArgs) => void) | null = null;
202
+ private selectionChangedCb: ((event: SelectionChangedEventArgs) => void) | null = null;
143
203
  private selectionStartValue: u32 = 0;
144
204
  private selectionEndValue: u32 = 0;
145
205
  private readonly disposables: Array<Disposable> = new Array<Disposable>();
@@ -326,14 +386,15 @@ export class TextCore extends Node {
326
386
  return this;
327
387
  }
328
388
 
329
- font(fontId: u32, size: f32): this {
389
+ /** @internal */
390
+ _fontId(fontId: u32, size: f32): this {
330
391
  this.usesDirectFontId = true;
331
392
  this.fontFamilyValue = null;
332
393
  this.fontId = fontId;
333
394
  this.fontSizeValue = size;
334
395
  this.hasFont = true;
335
396
  if (fontId == 0) {
336
- warn("Typography", "Text.font() received font id 0; the text will render with the default font fallback.");
397
+ warn("Typography", "Text._fontId() received font id 0; the text will render with the default font fallback.");
337
398
  }
338
399
  if (this.hasBuiltHandle()) {
339
400
  this.applyResolvedFont();
@@ -342,7 +403,7 @@ export class TextCore extends Node {
342
403
  }
343
404
 
344
405
  fontStack(stack: FontStack, size: f32): this {
345
- this.font(stack.id, size);
406
+ this._fontId(stack.id, size);
346
407
  return this;
347
408
  }
348
409
 
@@ -495,6 +556,26 @@ export class TextCore extends Node {
495
556
  return this;
496
557
  }
497
558
 
559
+ _editorCommandKeys(flag: bool = true): this {
560
+ this.editorCommandKeysValue = flag;
561
+ this.hasEditorCommandKeys = true;
562
+ if (this.hasBuiltHandle()) {
563
+ ui.setEditorCommandKeys(this.handle, flag);
564
+ this.notifyRetainedMutation();
565
+ }
566
+ return this;
567
+ }
568
+
569
+ _editorAcceptsTab(flag: bool = true): this {
570
+ this.editorAcceptsTabValue = flag;
571
+ this.hasEditorAcceptsTab = true;
572
+ if (this.hasBuiltHandle()) {
573
+ ui.setEditorAcceptsTab(this.handle, flag);
574
+ this.notifyRetainedMutation();
575
+ }
576
+ return this;
577
+ }
578
+
498
579
  caretColor(color: u32): this {
499
580
  this.caretColorValue = color;
500
581
  this.hasCaretColor = true;
@@ -522,27 +603,27 @@ export class TextCore extends Node {
522
603
  return this;
523
604
  }
524
605
 
525
- onTextChanged(cb: (text: string) => void): this {
606
+ onTextChanged(cb: (event: TextChangedEventArgs) => void): this {
526
607
  this.textChangedCb = cb;
527
608
  return this;
528
609
  }
529
610
 
530
- onSelectionChanged(cb: (start: u32, end: u32) => void): this {
611
+ onSelectionChanged(cb: (event: SelectionChangedEventArgs) => void): this {
531
612
  this.selectionChangedCb = cb;
532
613
  return this;
533
614
  }
534
615
 
535
- onClick(cb: () => void): this {
536
- super.onClick(cb);
616
+ onPointerClick(cb: (event: PointerClickEventArgs) => void): this {
617
+ super.onPointerClick(cb);
537
618
  return this;
538
619
  }
539
620
 
540
- onPointerEnter(cb: () => void): this {
621
+ onPointerEnter(cb: (event: PointerEventArgs) => void): this {
541
622
  super.onPointerEnter(cb);
542
623
  return this;
543
624
  }
544
625
 
545
- onPointerLeave(cb: () => void): this {
626
+ onPointerLeave(cb: (event: PointerEventArgs) => void): this {
546
627
  super.onPointerLeave(cb);
547
628
  return this;
548
629
  }
@@ -620,6 +701,12 @@ export class TextCore extends Node {
620
701
  if (this.hasEditable) {
621
702
  ui.setEditable(this.handle, this.editableValue);
622
703
  }
704
+ if (this.hasEditorCommandKeys) {
705
+ ui.setEditorCommandKeys(this.handle, this.editorCommandKeysValue);
706
+ }
707
+ if (this.hasEditorAcceptsTab) {
708
+ ui.setEditorAcceptsTab(this.handle, this.editorAcceptsTabValue);
709
+ }
623
710
  if (this.hasSelectable) {
624
711
  ui.setSelectable(this.handle, this.selectableValue, this.selectionColor);
625
712
  }
@@ -641,6 +728,15 @@ export class TextCore extends Node {
641
728
  return this.hasHeight && this.heightUnit == Unit.Percent ? this.heightValue : -1.0;
642
729
  }
643
730
 
731
+ _requiredFontIds(): Array<u32> {
732
+ const fontIds = new Array<u32>();
733
+ const fontId = this.resolveFontId();
734
+ if (fontId != 0) {
735
+ fontIds.push(fontId);
736
+ }
737
+ return fontIds;
738
+ }
739
+
644
740
  private handleThemeChanged(theme: Theme): void {
645
741
  if (this.hasBuiltHandle() && !this.hasColor) {
646
742
  ui.setTextColor(this.handle, theme.colors.textPrimary);
@@ -685,20 +781,19 @@ export class TextCore extends Node {
685
781
  this.contentValue = text;
686
782
  const callback = this.textChangedCb;
687
783
  if (callback !== null) {
688
- callback(text);
784
+ callback(new TextChangedEventArgs(text));
689
785
  }
690
786
  }
691
787
 
692
788
  _handleTextReplaced(start: u32, end: u32, text: string): void {
693
- const length = this.contentValue.length;
694
- const clampedStart = min<u32>(start, <u32>length);
695
- const clampedEnd = min<u32>(max<u32>(start, end), <u32>length);
696
- const prefix = this.contentValue.substring(0, <i32>clampedStart);
697
- const suffix = this.contentValue.substring(<i32>clampedEnd);
789
+ const startOffset = stringOffsetFromUtf8ByteOffset(this.contentValue, start);
790
+ const endOffset = stringOffsetFromUtf8ByteOffset(this.contentValue, max<u32>(start, end));
791
+ const prefix = this.contentValue.substring(0, startOffset);
792
+ const suffix = this.contentValue.substring(endOffset);
698
793
  this.contentValue = prefix + text + suffix;
699
794
  const callback = this.textChangedCb;
700
795
  if (callback !== null) {
701
- callback(this.contentValue);
796
+ callback(new TextChangedEventArgs(this.contentValue));
702
797
  }
703
798
  }
704
799
 
@@ -707,7 +802,7 @@ export class TextCore extends Node {
707
802
  this.selectionEndValue = end;
708
803
  const callback = this.selectionChangedCb;
709
804
  if (callback !== null) {
710
- callback(start, end);
805
+ callback(new SelectionChangedEventArgs(start, end));
711
806
  }
712
807
  }
713
808
 
@@ -1,6 +1,6 @@
1
1
  export { Column, Row, pct, px } from "./helpers";
2
2
  export { CustomDrawable } from "./CustomDrawable";
3
- export { FlexBox, FlexBoxProps } from "./FlexBox";
3
+ export { Border, FlexBox, FlexBoxProps } from "./FlexBox";
4
4
  export { GradientStop } from "./GradientStop";
5
5
  export { Grid } from "./Grid";
6
6
  export { Image } from "./Image";