drawnui-react 0.1.0-preview.14 → 0.1.0-preview.16
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.
- package/SKIPPED.md +5 -4
- package/dist/controls/SkiaBackdrop.d.ts +2 -0
- package/dist/controls/SkiaBackdrop.js +2 -0
- package/dist/controls/SkiaButton.d.ts +2 -0
- package/dist/controls/SkiaButton.js +2 -0
- package/dist/controls/SkiaCarousel.d.ts +2 -0
- package/dist/controls/SkiaCarousel.js +2 -0
- package/dist/controls/SkiaDrawer.d.ts +2 -0
- package/dist/controls/SkiaDrawer.js +2 -0
- package/dist/controls/SkiaEditor.js +10 -1
- package/dist/controls/SkiaLabel.d.ts +2 -0
- package/dist/controls/SkiaLabel.js +13 -2
- package/dist/controls/SkiaLayout.d.ts +15 -0
- package/dist/controls/SkiaLayout.js +75 -6
- package/dist/controls/SkiaProgress.js +2 -2
- package/dist/controls/SkiaScroll.d.ts +4 -0
- package/dist/controls/SkiaScroll.js +9 -0
- package/dist/controls/SkiaSlider.d.ts +2 -0
- package/dist/controls/SkiaSlider.js +5 -3
- package/dist/controls/SkiaToggle.d.ts +2 -0
- package/dist/controls/SkiaToggle.js +3 -1
- package/dist/controls/SnappingLayout.d.ts +2 -0
- package/dist/controls/SnappingLayout.js +3 -0
- package/dist/core/Accessibility.d.ts +8 -0
- package/dist/core/Accessibility.js +56 -5
- package/dist/core/Canvas.d.ts +23 -0
- package/dist/core/Canvas.js +65 -3
- package/dist/core/Hover.d.ts +37 -0
- package/dist/core/Hover.js +118 -0
- package/dist/core/KeyboardManager.d.ts +13 -0
- package/dist/core/KeyboardManager.js +18 -0
- package/dist/core/SkiaControl.d.ts +87 -1
- package/dist/core/SkiaControl.js +229 -18
- package/dist/core/SkiaEffect.d.ts +3 -0
- package/dist/core/SkiaEffect.js +8 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +2 -2
- package/dist/react/reconciler.js +29 -10
- package/package.json +4 -1
|
@@ -36,6 +36,8 @@ export declare class CachedObject {
|
|
|
36
36
|
constructor(Type: SkiaCacheType,
|
|
37
37
|
/** Rect the content was recorded for, canvas pixels at recording time. */
|
|
38
38
|
Bounds: SKRect, Scale: number, Picture?: SkPicture | undefined, Image?: Image | undefined);
|
|
39
|
+
/** Canvas.GpuEpoch it was made in: after a WebGL context restore it is remade (a picture may replay old GPU images). */
|
|
40
|
+
Epoch: number;
|
|
39
41
|
/** Replays the cache with its top-left moved to (left, top). */
|
|
40
42
|
Draw(canvas: SkCanvas, left: number, top: number): void;
|
|
41
43
|
Dispose(): void;
|
|
@@ -136,18 +138,43 @@ export declare class SkiaControl {
|
|
|
136
138
|
private compositeSurface?;
|
|
137
139
|
/** Own content or structure changed: the next composite record is a full one. */
|
|
138
140
|
private compositeFull;
|
|
141
|
+
/** Where the kept composite surface starts relative to DrawingRect (the effects margin it was laid out with). */
|
|
142
|
+
private compositeInsetX;
|
|
143
|
+
private compositeInsetY;
|
|
139
144
|
/** Canvas-pixel bounds this control covered when its parent last recorded it (composite erase region). */
|
|
140
145
|
private lastCompositeBounds?;
|
|
141
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* What the last composite record did (diagnostics): "full" or "partial", the number of children re-recorded and which
|
|
148
|
+
* ones; Areas: the pixels erased and drawn again for changes deeper than a child (C# Areas), Changed: the controls
|
|
149
|
+
* those areas belong to (C# Changed).
|
|
150
|
+
*/
|
|
142
151
|
LastCompositeRecord: {
|
|
143
152
|
Mode: "full" | "partial";
|
|
144
153
|
Children: number;
|
|
145
154
|
Dirty: readonly SkiaControl[];
|
|
155
|
+
Areas: readonly SKRect[];
|
|
156
|
+
Changed: readonly SkiaControl[];
|
|
146
157
|
};
|
|
158
|
+
/** C# MaxCompositionAreas: more areas than this in one composite record draw it whole instead. */
|
|
159
|
+
static MaxCompositionAreas: number;
|
|
160
|
+
/** C# MaxCompositionShare: areas covering more than this share of a composite draw it whole instead. */
|
|
161
|
+
static MaxCompositionShare: number;
|
|
162
|
+
/**
|
|
163
|
+
* Changes deeper than a direct child since the last composite record (drawnui-cross 6m): the control, the direct child
|
|
164
|
+
* it is in, where it was drawn before the change (its own drawn bounds, as drawn) and its rect then.
|
|
165
|
+
*/
|
|
166
|
+
private compositeDeep?;
|
|
167
|
+
/** Set while an UpdateDraw climbs: the ancestors re-measure but an ImageComposite among them keeps its partial record. */
|
|
168
|
+
private static drawOrigin;
|
|
169
|
+
/** Nonzero while a composite redraws only some areas: layouts skip children entirely outside the clip. */
|
|
170
|
+
static CompositionCulling: number;
|
|
147
171
|
/** The children a composite record can re-record individually; layouts return their views. */
|
|
148
172
|
protected GetCompositeChildren(): readonly SkiaControl[];
|
|
149
173
|
/** C# TrackChildAsDirty (DirtyChildrenTracker): the child changed without a remeasure of this control. */
|
|
150
174
|
TrackChildAsDirty(child: SkiaControl): void;
|
|
175
|
+
private static readonly rejectRect;
|
|
176
|
+
/** During a partial composite record: true when this control draws nothing inside the canvas clip (skipped whole). */
|
|
177
|
+
OutsideCompositionClip(canvas: SkCanvas): boolean;
|
|
151
178
|
/** Drawn bounds in canvas pixels including transforms and effects margins (C# GetTransformedDirtyBounds). */
|
|
152
179
|
GetTransformedDirtyBounds(): SKRect;
|
|
153
180
|
/** Current cache, if any. */
|
|
@@ -158,6 +185,36 @@ export declare class SkiaControl {
|
|
|
158
185
|
/** Consume every gesture that lands on this control so nothing below (z-order) receives it. */
|
|
159
186
|
BlockGesturesBelow: boolean;
|
|
160
187
|
LockChildrenGestures: LockTouch;
|
|
188
|
+
private receivesHover?;
|
|
189
|
+
/**
|
|
190
|
+
* Whether this control takes mouse hover: the canvas sets IsHovered while the mouse is over it. Opt-in: false by
|
|
191
|
+
* default, true by default only in the controls that always had hover (SkiaButton, SkiaSlider, the toggles,
|
|
192
|
+
* SkiaRadioButton, SkiaCarousel, SkiaDrawer), never because a control has a tap handler. A HoverChanged handler turns
|
|
193
|
+
* it on (C# fluent OnHovered) unless it is set.
|
|
194
|
+
*/
|
|
195
|
+
get ReceivesHover(): boolean;
|
|
196
|
+
set ReceivesHover(value: boolean);
|
|
197
|
+
/** The value of ReceivesHover until it is set. */
|
|
198
|
+
protected ReceivesHoverByDefault(): boolean;
|
|
199
|
+
private isHovered;
|
|
200
|
+
/**
|
|
201
|
+
* True while the mouse is over this control and it takes hover. Every such control under the pointer is hovered at
|
|
202
|
+
* once (a card and the button inside it, as CSS :hover); it stays as it is while content moves under the pointer and
|
|
203
|
+
* is checked again when that stops. Touch never hovers.
|
|
204
|
+
*/
|
|
205
|
+
get IsHovered(): boolean;
|
|
206
|
+
/** IsHovered changed: true when the mouse came over this control, false when it left (C# HoverChanged / OnHovered). */
|
|
207
|
+
HoverChanged?: (sender: SkiaControl, hovered: boolean) => void;
|
|
208
|
+
/** Set by the canvas's HoverManager. */
|
|
209
|
+
ApplyHover(on: boolean): void;
|
|
210
|
+
/** A scroll, carousel or drawer moving its content right now: hover waits until it stops (C# IsScrolling / InTransition). */
|
|
211
|
+
MovesContent(): boolean;
|
|
212
|
+
/**
|
|
213
|
+
* Hover hit path (HoverManager): this control is under the point (in its own space), its children under it follow,
|
|
214
|
+
* top-most first, by the routing rules of ProcessGestures. True when this subtree blocks gestures below it, so the
|
|
215
|
+
* controls under it get no hover (a popup over a list).
|
|
216
|
+
*/
|
|
217
|
+
CollectHovered(point: SKPoint, into: SkiaControl[]): boolean;
|
|
161
218
|
TouchEffectColor: Color;
|
|
162
219
|
/** Plays a ripple (from the tap point) when Tapped fires. */
|
|
163
220
|
AnimationTapped: SkiaTouchAnimation;
|
|
@@ -209,6 +266,11 @@ export declare class SkiaControl {
|
|
|
209
266
|
* built in code-behind is styled on its first measure and keeps whatever the code already set.
|
|
210
267
|
*/
|
|
211
268
|
ApplyInitialStyles(atConstruction?: boolean): void;
|
|
269
|
+
/**
|
|
270
|
+
* C# IsChildrenItem: added by the app (JSX children or the `Children` list), not a part the control made itself. A new
|
|
271
|
+
* `Children` list drops only these, so a control's own parts keep their place.
|
|
272
|
+
*/
|
|
273
|
+
IsChildrenItem: boolean;
|
|
212
274
|
AddSubView(_control: SkiaControl): void;
|
|
213
275
|
InsertSubView(_index: number, control: SkiaControl): void;
|
|
214
276
|
RemoveSubView(_control: SkiaControl): void;
|
|
@@ -414,6 +476,30 @@ export declare class SkiaControl {
|
|
|
414
476
|
* cache holds its composited output, so those are staled before redrawing (DrawnUi RedrawCanvas + parent invalidation).
|
|
415
477
|
*/
|
|
416
478
|
RepaintComposition(): void;
|
|
479
|
+
/**
|
|
480
|
+
* Update() for a change of how this control looks, not of its size (a color set through props, C# NeedDraw): the same
|
|
481
|
+
* re-measure and cache invalidation, but an ImageComposite above redraws only this control's area instead of
|
|
482
|
+
* recording whole (drawnui-cross 6m). The record still goes whole when the control's rect changed after all.
|
|
483
|
+
*/
|
|
484
|
+
UpdateDraw(): void;
|
|
485
|
+
/**
|
|
486
|
+
* A change of this control that keeps its layout, to every ImageComposite above: a direct child is drawn again whole
|
|
487
|
+
* (C# TrackChildAsDirty), a deeper control by its area, read now as it was drawn (its last matrix and effects margin).
|
|
488
|
+
*/
|
|
489
|
+
private ReportToComposites;
|
|
490
|
+
/** The matrix this control will be drawn with (Render), from its current properties; undefined when none. */
|
|
491
|
+
private CurrentMatrix;
|
|
492
|
+
/** Where this control will be drawn: its rect grown by its effects margin, through its current matrix. */
|
|
493
|
+
private DrawnBoundsNow;
|
|
494
|
+
private static MapRect;
|
|
495
|
+
/** Its output depends on all of its content (a visual effect; a backdrop samples below): a change inside redraws it whole. */
|
|
496
|
+
protected get SamplesContent(): boolean;
|
|
497
|
+
/**
|
|
498
|
+
* Where a deep change shows inside the composite (drawnui-cross 6m rule b): the control as drawn before and as drawn
|
|
499
|
+
* now, then through the transform of every ancestor up to the composite. undefined: draw the child whole (an effect
|
|
500
|
+
* or a backdrop on the way, the control gone from the child); null: the layout changed, record whole.
|
|
501
|
+
*/
|
|
502
|
+
private static DeepArea;
|
|
417
503
|
/**
|
|
418
504
|
* DrawnUi IsParentIndependent: this control's size never changes the layout around it, so its own invalidation
|
|
419
505
|
* stops here (ancestors composite again, nothing above re-measures). The parent re-measures it on draw when
|
package/dist/core/SkiaControl.js
CHANGED
|
@@ -22,6 +22,8 @@ export class CachedObject {
|
|
|
22
22
|
this.Picture = Picture;
|
|
23
23
|
this.Image = Image;
|
|
24
24
|
}
|
|
25
|
+
/** Canvas.GpuEpoch it was made in: after a WebGL context restore it is remade (a picture may replay old GPU images). */
|
|
26
|
+
Epoch = 0;
|
|
25
27
|
/** Replays the cache with its top-left moved to (left, top). */
|
|
26
28
|
Draw(canvas, left, top) {
|
|
27
29
|
const CK = Super.CK;
|
|
@@ -132,6 +134,7 @@ export class SkiaControl {
|
|
|
132
134
|
return;
|
|
133
135
|
this.bindingContext = value;
|
|
134
136
|
this.OnBindingContextChanged();
|
|
137
|
+
this.Superview?.Hover?.RequestCheck(); // a recycled cell under a still mouse now shows another item
|
|
135
138
|
}
|
|
136
139
|
/** Index of the bound item inside its ItemsSource, -1 when not templated. */
|
|
137
140
|
ContextIndex = -1;
|
|
@@ -164,15 +167,45 @@ export class SkiaControl {
|
|
|
164
167
|
compositeSurface;
|
|
165
168
|
/** Own content or structure changed: the next composite record is a full one. */
|
|
166
169
|
compositeFull = true;
|
|
170
|
+
/** Where the kept composite surface starts relative to DrawingRect (the effects margin it was laid out with). */
|
|
171
|
+
compositeInsetX = 0;
|
|
172
|
+
compositeInsetY = 0;
|
|
167
173
|
/** Canvas-pixel bounds this control covered when its parent last recorded it (composite erase region). */
|
|
168
174
|
lastCompositeBounds;
|
|
169
|
-
/**
|
|
170
|
-
|
|
175
|
+
/**
|
|
176
|
+
* What the last composite record did (diagnostics): "full" or "partial", the number of children re-recorded and which
|
|
177
|
+
* ones; Areas: the pixels erased and drawn again for changes deeper than a child (C# Areas), Changed: the controls
|
|
178
|
+
* those areas belong to (C# Changed).
|
|
179
|
+
*/
|
|
180
|
+
LastCompositeRecord = { Mode: "full", Children: 0, Dirty: [], Areas: [], Changed: [] };
|
|
181
|
+
/** C# MaxCompositionAreas: more areas than this in one composite record draw it whole instead. */
|
|
182
|
+
static MaxCompositionAreas = 16;
|
|
183
|
+
/** C# MaxCompositionShare: areas covering more than this share of a composite draw it whole instead. */
|
|
184
|
+
static MaxCompositionShare = 0.5;
|
|
185
|
+
/**
|
|
186
|
+
* Changes deeper than a direct child since the last composite record (drawnui-cross 6m): the control, the direct child
|
|
187
|
+
* it is in, where it was drawn before the change (its own drawn bounds, as drawn) and its rect then.
|
|
188
|
+
*/
|
|
189
|
+
compositeDeep;
|
|
190
|
+
/** Set while an UpdateDraw climbs: the ancestors re-measure but an ImageComposite among them keeps its partial record. */
|
|
191
|
+
static drawOrigin = null;
|
|
192
|
+
/** Nonzero while a composite redraws only some areas: layouts skip children entirely outside the clip. */
|
|
193
|
+
static CompositionCulling = 0;
|
|
171
194
|
/** The children a composite record can re-record individually; layouts return their views. */
|
|
172
195
|
GetCompositeChildren() { return []; }
|
|
173
196
|
/** C# TrackChildAsDirty (DirtyChildrenTracker): the child changed without a remeasure of this control. */
|
|
174
197
|
TrackChildAsDirty(child) { if (this.IsCacheComposite)
|
|
175
198
|
this.DirtyChildrenInternal.add(child); }
|
|
199
|
+
static rejectRect = new Float32Array(4);
|
|
200
|
+
/** During a partial composite record: true when this control draws nothing inside the canvas clip (skipped whole). */
|
|
201
|
+
OutsideCompositionClip(canvas) {
|
|
202
|
+
const b = this.DrawnBoundsNow(this.RenderingScale), q = SkiaControl.rejectRect;
|
|
203
|
+
q[0] = b.Left;
|
|
204
|
+
q[1] = b.Top;
|
|
205
|
+
q[2] = b.Right;
|
|
206
|
+
q[3] = b.Bottom;
|
|
207
|
+
return canvas.quickReject(q);
|
|
208
|
+
}
|
|
176
209
|
/** Drawn bounds in canvas pixels including transforms and effects margins (C# GetTransformedDirtyBounds). */
|
|
177
210
|
GetTransformedDirtyBounds() {
|
|
178
211
|
const r = this.ExpandedCacheRect(this.RenderingScale), m = this.RenderTransformMatrix;
|
|
@@ -191,6 +224,55 @@ export class SkiaControl {
|
|
|
191
224
|
/** Consume every gesture that lands on this control so nothing below (z-order) receives it. */
|
|
192
225
|
BlockGesturesBelow = false;
|
|
193
226
|
LockChildrenGestures = "Disabled";
|
|
227
|
+
// ---- hover (drawnui-cross 6m, C# ReceivesHover / IsHovered / HoverChanged) ----
|
|
228
|
+
receivesHover;
|
|
229
|
+
/**
|
|
230
|
+
* Whether this control takes mouse hover: the canvas sets IsHovered while the mouse is over it. Opt-in: false by
|
|
231
|
+
* default, true by default only in the controls that always had hover (SkiaButton, SkiaSlider, the toggles,
|
|
232
|
+
* SkiaRadioButton, SkiaCarousel, SkiaDrawer), never because a control has a tap handler. A HoverChanged handler turns
|
|
233
|
+
* it on (C# fluent OnHovered) unless it is set.
|
|
234
|
+
*/
|
|
235
|
+
get ReceivesHover() { return this.receivesHover ?? (this.HoverChanged ? true : this.ReceivesHoverByDefault()); }
|
|
236
|
+
set ReceivesHover(value) { this.receivesHover = value; }
|
|
237
|
+
/** The value of ReceivesHover until it is set. */
|
|
238
|
+
ReceivesHoverByDefault() { return false; }
|
|
239
|
+
isHovered = false;
|
|
240
|
+
/**
|
|
241
|
+
* True while the mouse is over this control and it takes hover. Every such control under the pointer is hovered at
|
|
242
|
+
* once (a card and the button inside it, as CSS :hover); it stays as it is while content moves under the pointer and
|
|
243
|
+
* is checked again when that stops. Touch never hovers.
|
|
244
|
+
*/
|
|
245
|
+
get IsHovered() { return this.isHovered; }
|
|
246
|
+
/** IsHovered changed: true when the mouse came over this control, false when it left (C# HoverChanged / OnHovered). */
|
|
247
|
+
HoverChanged;
|
|
248
|
+
/** Set by the canvas's HoverManager. */
|
|
249
|
+
ApplyHover(on) {
|
|
250
|
+
if (this.isHovered === on)
|
|
251
|
+
return;
|
|
252
|
+
this.isHovered = on;
|
|
253
|
+
this.HoverChanged?.(this, on);
|
|
254
|
+
}
|
|
255
|
+
/** A scroll, carousel or drawer moving its content right now: hover waits until it stops (C# IsScrolling / InTransition). */
|
|
256
|
+
MovesContent() { return false; }
|
|
257
|
+
/**
|
|
258
|
+
* Hover hit path (HoverManager): this control is under the point (in its own space), its children under it follow,
|
|
259
|
+
* top-most first, by the routing rules of ProcessGestures. True when this subtree blocks gestures below it, so the
|
|
260
|
+
* controls under it get no hover (a popup over a list).
|
|
261
|
+
*/
|
|
262
|
+
CollectHovered(point, into) {
|
|
263
|
+
into.push(this);
|
|
264
|
+
if (!this.CheckChildrenGesturesLocked("Pointer")) {
|
|
265
|
+
const listeners = this.GetGestureListeners();
|
|
266
|
+
for (let i = listeners.length - 1; i >= 0; i--) {
|
|
267
|
+
const child = listeners[i];
|
|
268
|
+
if (!child.IsVisible || child.InputTransparent || !this.IsGestureForChild(child, point))
|
|
269
|
+
continue;
|
|
270
|
+
if (child.CollectHovered(child.TransformPointToLocalSpace(point), into))
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return this.BlockGesturesBelow;
|
|
275
|
+
}
|
|
194
276
|
// ---- touch feedback (same names as DrawnUi) ----
|
|
195
277
|
TouchEffectColor = Colors.White;
|
|
196
278
|
/** Plays a ripple (from the tap point) when Tapped fires. */
|
|
@@ -275,6 +357,11 @@ export class SkiaControl {
|
|
|
275
357
|
if (!SkiaStyles.IsEmpty)
|
|
276
358
|
SkiaStyles.Apply(this, atConstruction);
|
|
277
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* C# IsChildrenItem: added by the app (JSX children or the `Children` list), not a part the control made itself. A new
|
|
362
|
+
* `Children` list drops only these, so a control's own parts keep their place.
|
|
363
|
+
*/
|
|
364
|
+
IsChildrenItem = false;
|
|
278
365
|
AddSubView(_control) { throw new Error(`DrawnUi: ${this.constructor.name} cannot host children`); }
|
|
279
366
|
InsertSubView(_index, control) { this.AddSubView(control); }
|
|
280
367
|
RemoveSubView(_control) { }
|
|
@@ -691,7 +778,10 @@ export class SkiaControl {
|
|
|
691
778
|
}
|
|
692
779
|
else {
|
|
693
780
|
const r = cacheType === "Operations" ? this.ExpandedCacheRect(ctx.Scale) : this.AlignedCacheRect(ctx.Scale);
|
|
694
|
-
const
|
|
781
|
+
const epoch = this.Superview?.GpuEpoch ?? 0;
|
|
782
|
+
if (this.RenderObjectPrevious && this.RenderObjectPrevious.Epoch !== epoch)
|
|
783
|
+
this.DisposePrevious(); // made on a lost GPU context
|
|
784
|
+
const stale = this.cacheDirty || !this.RenderObject || this.RenderObject.Type !== cacheType || this.RenderObject.Epoch !== epoch
|
|
695
785
|
|| this.RenderObject.Scale !== ctx.Scale
|
|
696
786
|
|| Math.round(this.RenderObject.Bounds.Width) !== Math.round(r.Width) || Math.round(this.RenderObject.Bounds.Height) !== Math.round(r.Height);
|
|
697
787
|
if (stale)
|
|
@@ -750,6 +840,7 @@ export class SkiaControl {
|
|
|
750
840
|
const picture = recorder.finishRecordingAsPicture();
|
|
751
841
|
recorder.delete();
|
|
752
842
|
this.RenderObject = new CachedObject("Operations", r, ctx.Scale, picture);
|
|
843
|
+
this.RenderObject.Epoch = this.Superview?.GpuEpoch ?? 0;
|
|
753
844
|
}
|
|
754
845
|
else if (cacheType === "ImageComposite") {
|
|
755
846
|
this.CreateCompositeRenderingObject(ctx, r, w, h);
|
|
@@ -773,6 +864,7 @@ export class SkiaControl {
|
|
|
773
864
|
const image = offscreen.makeImageSnapshot();
|
|
774
865
|
offscreen.delete();
|
|
775
866
|
this.RenderObject = new CachedObject(cacheType, r, ctx.Scale, undefined, image);
|
|
867
|
+
this.RenderObject.Epoch = this.Superview?.GpuEpoch ?? 0;
|
|
776
868
|
}
|
|
777
869
|
this.cacheDirty = false;
|
|
778
870
|
}
|
|
@@ -791,7 +883,9 @@ export class SkiaControl {
|
|
|
791
883
|
}
|
|
792
884
|
let surface = this.compositeSurface;
|
|
793
885
|
const prev = this.RenderObject;
|
|
794
|
-
const
|
|
886
|
+
const epoch = this.Superview?.GpuEpoch ?? 0;
|
|
887
|
+
// the kept surface belongs to the GPU context it was made on: after a context restore it is made again
|
|
888
|
+
const sameGeometry = !!surface && !!prev && prev.Type === "ImageComposite" && prev.Scale === ctx.Scale && prev.Epoch === epoch
|
|
795
889
|
&& Math.round(prev.Bounds.Width) === w && Math.round(prev.Bounds.Height) === h;
|
|
796
890
|
if (!sameGeometry) {
|
|
797
891
|
surface?.delete();
|
|
@@ -804,14 +898,46 @@ export class SkiaControl {
|
|
|
804
898
|
}
|
|
805
899
|
const canvas = surface.getCanvas();
|
|
806
900
|
const children = this.GetCompositeChildren();
|
|
807
|
-
const
|
|
901
|
+
const deep = this.compositeDeep;
|
|
902
|
+
// the same size with another effects margin moves the content inside the surface: record whole (C# 97683f19)
|
|
903
|
+
const insetX = r.Left - this.DrawingRect.Left, insetY = r.Top - this.DrawingRect.Top;
|
|
904
|
+
const sameInset = insetX === this.compositeInsetX && insetY === this.compositeInsetY;
|
|
905
|
+
this.compositeInsetX = insetX;
|
|
906
|
+
this.compositeInsetY = insetY;
|
|
907
|
+
let partial = sameGeometry && sameInset && !this.compositeFull && children.length > 0 && (this.DirtyChildrenInternal.size > 0 || !!deep?.length);
|
|
908
|
+
// changes deeper than a child: only their areas, the child they are in drawn clipped to them (drawnui-cross 6m)
|
|
909
|
+
const areas = [], changed = [], inside = new Set();
|
|
910
|
+
if (partial && deep?.length) {
|
|
911
|
+
let covered = 0;
|
|
912
|
+
for (const d of deep) {
|
|
913
|
+
if (!children.includes(d.Child) || this.DirtyChildrenInternal.has(d.Child))
|
|
914
|
+
continue;
|
|
915
|
+
const area = SkiaControl.DeepArea(d, this, ctx.Scale);
|
|
916
|
+
if (area === null) {
|
|
917
|
+
partial = false;
|
|
918
|
+
break;
|
|
919
|
+
}
|
|
920
|
+
if (!area) {
|
|
921
|
+
this.DirtyChildrenInternal.add(d.Child);
|
|
922
|
+
continue;
|
|
923
|
+
}
|
|
924
|
+
areas.push(area);
|
|
925
|
+
changed.push(d.Origin);
|
|
926
|
+
inside.add(d.Child);
|
|
927
|
+
covered += area.Width * area.Height;
|
|
928
|
+
}
|
|
929
|
+
if (areas.length > SkiaControl.MaxCompositionAreas || covered > r.Width * r.Height * SkiaControl.MaxCompositionShare)
|
|
930
|
+
partial = false;
|
|
931
|
+
}
|
|
932
|
+
if (deep)
|
|
933
|
+
deep.length = 0;
|
|
808
934
|
const offset = prev && sameGeometry ? { X: r.Left - prev.Bounds.Left, Y: r.Top - prev.Bounds.Top } : { X: 0, Y: 0 };
|
|
809
935
|
const saved = canvas.save();
|
|
810
936
|
canvas.translate(-r.Left, -r.Top);
|
|
811
937
|
if (partial) {
|
|
812
938
|
// dirty = reported children + siblings intersecting their old or new bounds (C# makes intersecting children dirty too)
|
|
813
939
|
const dirty = new Set();
|
|
814
|
-
const rects = [];
|
|
940
|
+
const rects = [...areas];
|
|
815
941
|
const boundsOf = (c) => {
|
|
816
942
|
const out = [c.GetTransformedDirtyBounds()];
|
|
817
943
|
if (c.lastCompositeBounds)
|
|
@@ -827,7 +953,7 @@ export class SkiaControl {
|
|
|
827
953
|
while (grew) {
|
|
828
954
|
grew = false;
|
|
829
955
|
for (const c of children) {
|
|
830
|
-
if (dirty.has(c) || !c.IsVisible)
|
|
956
|
+
if (dirty.has(c) || inside.has(c) || !c.IsVisible)
|
|
831
957
|
continue;
|
|
832
958
|
const own = boundsOf(c);
|
|
833
959
|
if (rects.some((d) => own.some((o) => o.Left < d.Right && d.Left < o.Right && o.Top < d.Bottom && d.Top < o.Bottom))) {
|
|
@@ -854,14 +980,23 @@ export class SkiaControl {
|
|
|
854
980
|
this.DirtyChildrenInternal.clear();
|
|
855
981
|
for (const c of dirty)
|
|
856
982
|
this.DirtyChildrenInternal.add(c);
|
|
857
|
-
|
|
983
|
+
for (const c of inside)
|
|
984
|
+
this.DirtyChildrenInternal.add(c);
|
|
985
|
+
SkiaControl.CompositionCulling++;
|
|
986
|
+
try {
|
|
987
|
+
this.PaintContent({ ...ctx, Context: { Canvas: canvas, Surface: surface, Origin: { X: r.Left, Y: r.Top } } });
|
|
988
|
+
}
|
|
989
|
+
finally {
|
|
990
|
+
SkiaControl.CompositionCulling--;
|
|
991
|
+
}
|
|
858
992
|
this.IsRenderingWithComposition = false;
|
|
859
|
-
|
|
993
|
+
const redrawn = children.filter((c) => this.DirtyChildrenInternal.has(c));
|
|
994
|
+
this.LastCompositeRecord = { Mode: "partial", Children: redrawn.length, Dirty: redrawn, Areas: areas, Changed: changed };
|
|
860
995
|
}
|
|
861
996
|
else {
|
|
862
997
|
canvas.clear(CK.TRANSPARENT);
|
|
863
998
|
this.PaintContent({ ...ctx, Context: { Canvas: canvas, Surface: surface, Origin: { X: r.Left, Y: r.Top } } });
|
|
864
|
-
this.LastCompositeRecord = { Mode: "full", Children: children.length, Dirty: children };
|
|
999
|
+
this.LastCompositeRecord = { Mode: "full", Children: children.length, Dirty: children, Areas: [], Changed: [] };
|
|
865
1000
|
}
|
|
866
1001
|
canvas.restoreToCount(saved);
|
|
867
1002
|
for (const c of children)
|
|
@@ -871,6 +1006,7 @@ export class SkiaControl {
|
|
|
871
1006
|
const image = surface.makeImageSnapshot();
|
|
872
1007
|
const old = this.RenderObject;
|
|
873
1008
|
this.RenderObject = new CachedObject("ImageComposite", r, ctx.Scale, undefined, image);
|
|
1009
|
+
this.RenderObject.Epoch = epoch;
|
|
874
1010
|
if (old) {
|
|
875
1011
|
const sv = this.Superview;
|
|
876
1012
|
if (sv)
|
|
@@ -906,7 +1042,11 @@ export class SkiaControl {
|
|
|
906
1042
|
/** Marks the cache stale; re-recorded on the next frame (a composite records fully: its own content changed). */
|
|
907
1043
|
InvalidateCache() { this.cacheDirty = true; this.compositeFull = true; }
|
|
908
1044
|
/** Effects margin recomputed on the next use (C# InvalidateEffectsMargin). */
|
|
909
|
-
InvalidateEffectsMargin() {
|
|
1045
|
+
InvalidateEffectsMargin() {
|
|
1046
|
+
// a layout's margin aggregates what its children paint outside it: every ancestor recomputes too (C# 97683f19)
|
|
1047
|
+
for (let c = this; c; c = c.Parent)
|
|
1048
|
+
c.effectsMarginCache = undefined;
|
|
1049
|
+
}
|
|
910
1050
|
/** Draws PostAnimators above content; an effect returning true asks for another frame. */
|
|
911
1051
|
ExecutePostAnimators(ctx) {
|
|
912
1052
|
if (this.PostAnimators.length === 0)
|
|
@@ -1124,15 +1264,84 @@ export class SkiaControl {
|
|
|
1124
1264
|
* cache holds its composited output, so those are staled before redrawing (DrawnUi RedrawCanvas + parent invalidation).
|
|
1125
1265
|
*/
|
|
1126
1266
|
RepaintComposition() {
|
|
1127
|
-
|
|
1128
|
-
|
|
1267
|
+
this.ReportToComposites();
|
|
1268
|
+
for (let p = this.Parent; p; p = p.Parent)
|
|
1129
1269
|
p.cacheDirty = true;
|
|
1130
|
-
p.TrackChildAsDirty(child);
|
|
1131
|
-
child = p;
|
|
1132
|
-
p = p.Parent;
|
|
1133
|
-
}
|
|
1134
1270
|
this.Repaint();
|
|
1135
1271
|
}
|
|
1272
|
+
/**
|
|
1273
|
+
* Update() for a change of how this control looks, not of its size (a color set through props, C# NeedDraw): the same
|
|
1274
|
+
* re-measure and cache invalidation, but an ImageComposite above redraws only this control's area instead of
|
|
1275
|
+
* recording whole (drawnui-cross 6m). The record still goes whole when the control's rect changed after all.
|
|
1276
|
+
*/
|
|
1277
|
+
UpdateDraw() {
|
|
1278
|
+
this.ReportToComposites();
|
|
1279
|
+
const outer = SkiaControl.drawOrigin;
|
|
1280
|
+
SkiaControl.drawOrigin = this;
|
|
1281
|
+
try {
|
|
1282
|
+
this.InvalidateMeasure();
|
|
1283
|
+
}
|
|
1284
|
+
finally {
|
|
1285
|
+
SkiaControl.drawOrigin = outer;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* A change of this control that keeps its layout, to every ImageComposite above: a direct child is drawn again whole
|
|
1290
|
+
* (C# TrackChildAsDirty), a deeper control by its area, read now as it was drawn (its last matrix and effects margin).
|
|
1291
|
+
*/
|
|
1292
|
+
ReportToComposites() {
|
|
1293
|
+
let before;
|
|
1294
|
+
let child = this;
|
|
1295
|
+
for (let p = this.Parent; p; child = p, p = p.Parent) {
|
|
1296
|
+
if (!p.IsCacheComposite)
|
|
1297
|
+
continue;
|
|
1298
|
+
if (child === this) {
|
|
1299
|
+
p.TrackChildAsDirty(child);
|
|
1300
|
+
continue;
|
|
1301
|
+
}
|
|
1302
|
+
const deep = p.compositeDeep ??= [];
|
|
1303
|
+
if (deep.some((d) => d.Origin === this))
|
|
1304
|
+
continue;
|
|
1305
|
+
before ??= this.GetTransformedDirtyBounds();
|
|
1306
|
+
const r = this.DrawingRect;
|
|
1307
|
+
deep.push({ Origin: this, Child: child, Before: before, Rect: new SKRect(r.Left, r.Top, r.Right, r.Bottom) });
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
/** The matrix this control will be drawn with (Render), from its current properties; undefined when none. */
|
|
1311
|
+
CurrentMatrix(scale) {
|
|
1312
|
+
return this.HasTransform ? this.CreateRenderTransformMatrix(this.DrawingRect, scale) : undefined;
|
|
1313
|
+
}
|
|
1314
|
+
/** Where this control will be drawn: its rect grown by its effects margin, through its current matrix. */
|
|
1315
|
+
DrawnBoundsNow(scale) { return SkiaControl.MapRect(this.CurrentMatrix(scale), this.ExpandedCacheRect(scale)); }
|
|
1316
|
+
static MapRect(m, r) {
|
|
1317
|
+
if (!m)
|
|
1318
|
+
return r;
|
|
1319
|
+
const pts = Super.CK.Matrix.mapPoints(m, [r.Left, r.Top, r.Right, r.Top, r.Right, r.Bottom, r.Left, r.Bottom]);
|
|
1320
|
+
return new SKRect(Math.min(pts[0], pts[2], pts[4], pts[6]), Math.min(pts[1], pts[3], pts[5], pts[7]), Math.max(pts[0], pts[2], pts[4], pts[6]), Math.max(pts[1], pts[3], pts[5], pts[7]));
|
|
1321
|
+
}
|
|
1322
|
+
/** Its output depends on all of its content (a visual effect; a backdrop samples below): a change inside redraws it whole. */
|
|
1323
|
+
get SamplesContent() { return !this.DisableEffects && this.visualEffects.length > 0; }
|
|
1324
|
+
/**
|
|
1325
|
+
* Where a deep change shows inside the composite (drawnui-cross 6m rule b): the control as drawn before and as drawn
|
|
1326
|
+
* now, then through the transform of every ancestor up to the composite. undefined: draw the child whole (an effect
|
|
1327
|
+
* or a backdrop on the way, the control gone from the child); null: the layout changed, record whole.
|
|
1328
|
+
*/
|
|
1329
|
+
static DeepArea(d, composite, scale) {
|
|
1330
|
+
const o = d.Origin, r = o.DrawingRect;
|
|
1331
|
+
if (r.Left !== d.Rect.Left || r.Top !== d.Rect.Top || r.Right !== d.Rect.Right || r.Bottom !== d.Rect.Bottom)
|
|
1332
|
+
return null;
|
|
1333
|
+
if (!o.IsVisible)
|
|
1334
|
+
return undefined;
|
|
1335
|
+
const now = o.DrawnBoundsNow(scale);
|
|
1336
|
+
let area = new SKRect(Math.min(now.Left, d.Before.Left), Math.min(now.Top, d.Before.Top), Math.max(now.Right, d.Before.Right), Math.max(now.Bottom, d.Before.Bottom));
|
|
1337
|
+
let p = o.Parent, child = o;
|
|
1338
|
+
for (; p && p !== composite; child = p, p = p.Parent) {
|
|
1339
|
+
if (p.SamplesContent || !p.IsVisible)
|
|
1340
|
+
return undefined;
|
|
1341
|
+
area = SkiaControl.MapRect(p.CurrentMatrix(scale), area);
|
|
1342
|
+
}
|
|
1343
|
+
return p === composite && child === d.Child ? area : undefined;
|
|
1344
|
+
}
|
|
1136
1345
|
/**
|
|
1137
1346
|
* DrawnUi IsParentIndependent: this control's size never changes the layout around it, so its own invalidation
|
|
1138
1347
|
* stops here (ancestors composite again, nothing above re-measures). The parent re-measures it on draw when
|
|
@@ -1143,7 +1352,9 @@ export class SkiaControl {
|
|
|
1143
1352
|
InvalidateMeasure() {
|
|
1144
1353
|
this.NeedMeasure = true;
|
|
1145
1354
|
this.cacheDirty = true;
|
|
1146
|
-
|
|
1355
|
+
// structure may change: a composite cannot patch it; a draw-only change (UpdateDraw) reported its area instead
|
|
1356
|
+
if (SkiaControl.drawOrigin === null || SkiaControl.drawOrigin === this)
|
|
1357
|
+
this.compositeFull = true;
|
|
1147
1358
|
this.effectsMarginCache = undefined;
|
|
1148
1359
|
if (this.Parent && this.IsParentIndependent)
|
|
1149
1360
|
this.RepaintComposition();
|
|
@@ -125,6 +125,9 @@ export declare class SkiaShaderEffect extends SkiaEffect implements IPostRendere
|
|
|
125
125
|
protected ApplyShaderSource(): void;
|
|
126
126
|
/** Snapshot of what the parent painted (C# CreateSnapshot): the surface the pixels are on, mapped through its origin. */
|
|
127
127
|
protected CreateSnapshot(ctx: DrawingContext, destination: SKRect): CachedTexture | undefined;
|
|
128
|
+
private frozenEpoch;
|
|
129
|
+
/** Canvas.GpuEpoch: GPU textures made before a WebGL context restore are made again. */
|
|
130
|
+
protected GpuEpoch(): number;
|
|
128
131
|
/** Where the parent was when the texture was frozen (Once): the texture moves with it, as its cache does. */
|
|
129
132
|
private frozenAt?;
|
|
130
133
|
private ParentOrigin;
|
package/dist/core/SkiaEffect.js
CHANGED
|
@@ -159,6 +159,9 @@ export class SkiaShaderEffect extends SkiaEffect {
|
|
|
159
159
|
return undefined;
|
|
160
160
|
return { Image: image, Bounds: destination, Origin: { X: ox, Y: oy } };
|
|
161
161
|
}
|
|
162
|
+
frozenEpoch = 0;
|
|
163
|
+
/** Canvas.GpuEpoch: GPU textures made before a WebGL context restore are made again. */
|
|
164
|
+
GpuEpoch() { return this.Parent?.Superview?.GpuEpoch ?? 0; }
|
|
162
165
|
/** Where the parent was when the texture was frozen (Once): the texture moves with it, as its cache does. */
|
|
163
166
|
frozenAt;
|
|
164
167
|
ParentOrigin() { const r = this.Parent?.DrawingRect; return { X: r?.Left ?? 0, Y: r?.Top ?? 0 }; }
|
|
@@ -176,7 +179,7 @@ export class SkiaShaderEffect extends SkiaEffect {
|
|
|
176
179
|
switch (this.UseBackground) {
|
|
177
180
|
case "Never": return undefined;
|
|
178
181
|
case "Once":
|
|
179
|
-
if (!this.AquiredBackground || !this.frozen) {
|
|
182
|
+
if (!this.AquiredBackground || !this.frozen || this.frozenEpoch !== this.GpuEpoch()) { // a frozen texture of a lost GPU context is taken again
|
|
180
183
|
this.ReleaseFrozenSnapshot();
|
|
181
184
|
let snapshot = this.Parent?.CachedImage;
|
|
182
185
|
let owned = false;
|
|
@@ -189,6 +192,7 @@ export class SkiaShaderEffect extends SkiaEffect {
|
|
|
189
192
|
this.frozenOwned = owned;
|
|
190
193
|
this.AquiredBackground = true;
|
|
191
194
|
this.frozenAt = this.ParentOrigin();
|
|
195
|
+
this.frozenEpoch = this.GpuEpoch();
|
|
192
196
|
}
|
|
193
197
|
}
|
|
194
198
|
return this.FollowParent(this.frozen);
|
|
@@ -434,7 +438,8 @@ export class ShaderDoubleTexturesEffect extends SkiaShaderEffect {
|
|
|
434
438
|
return undefined;
|
|
435
439
|
const w = Math.round(d.Width), h = Math.round(d.Height);
|
|
436
440
|
const cur = slot === "p" ? this.resizedPrimary : this.resizedSecondary;
|
|
437
|
-
|
|
441
|
+
const epoch = this.GpuEpoch();
|
|
442
|
+
if (cur && cur.source === source && cur.w === w && cur.h === h && cur.epoch === epoch)
|
|
438
443
|
return cur.image;
|
|
439
444
|
const main = ctx.Context.Surface;
|
|
440
445
|
if (!main)
|
|
@@ -449,7 +454,7 @@ export class ShaderDoubleTexturesEffect extends SkiaShaderEffect {
|
|
|
449
454
|
const image = surface.makeImageSnapshot();
|
|
450
455
|
surface.delete();
|
|
451
456
|
cur?.image.delete();
|
|
452
|
-
const entry = { source, w, h, image };
|
|
457
|
+
const entry = { source, w, h, epoch, image };
|
|
453
458
|
if (slot === "p")
|
|
454
459
|
this.resizedPrimary = entry;
|
|
455
460
|
else
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./core/SkiaControl";
|
|
|
9
9
|
export * from "./core/Canvas";
|
|
10
10
|
export * from "./controls/SkiaLayout";
|
|
11
11
|
export * from "./core/Accessibility";
|
|
12
|
+
export * from "./core/Hover";
|
|
12
13
|
export * from "./controls/SkiaLabel";
|
|
13
14
|
export * from "./controls/TextSpan";
|
|
14
15
|
export * from "./controls/SkiaRichLabel";
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./core/SkiaControl";
|
|
|
9
9
|
export * from "./core/Canvas";
|
|
10
10
|
export * from "./controls/SkiaLayout";
|
|
11
11
|
export * from "./core/Accessibility";
|
|
12
|
+
export * from "./core/Hover";
|
|
12
13
|
export * from "./controls/SkiaLabel";
|
|
13
14
|
export * from "./controls/TextSpan";
|
|
14
15
|
export * from "./controls/SkiaRichLabel";
|
package/dist/react/index.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ import type { GesturesMode } from "../core/Gestures";
|
|
|
42
42
|
* and never appeared in completion.
|
|
43
43
|
*/
|
|
44
44
|
type PropsOf<T> = Partial<{
|
|
45
|
-
[K in keyof T as T[K] extends Function ? (undefined extends T[K] ? K : never) : K extends "Children" | "Views" | "Parent" | "Spans" | "GridStructure" | "AccessibilityId" | "IsAccessibilityElement" | "HasTransform" | "RenderTransformMatrix" | "RenderObjectPrevious" | "LastMeasuredIndex" | "ItemsInsertedAtStart" | "UsingControlStyle" | "Track" | "Thumb" | "FrameOn" | "FrameOff" | "ViewCheckOn" | "ViewOn" | "ViewText" | "Ratio" | "StartThumbX" | "EndThumbX" | "SnapPoints" | "CurrentPosition" | "CurrentSnap" | "ContentOffsetBounds" | "InTransition" | "CanAnimate" | "MaxIndex" | "ChildrenTotal" | "IsAtStart" | "IsAtEnd" | "ScrollProgress" | "ScrollAmount" | "TransitionProgress" | "LastIndex" | "ChildrenCount" | "Horizontal" | "Animator" | "Animation" | "IsPlaying" | "PlayWhenAvailable" | "TotalFrames" | "HasEffects" | "IsDisposed" | "Label" | "IsMultiline" | "HasSelection" | "LayoutVersion" | "LinesCount" | "MeasuredLineHeight" | "Focused" | "SpriteSheet" | "FrameWidth" | "FrameHeight" | "DurationMs" | "FrameDurationMs" | "CurrentSprite" | "Rects" | "HasTapHandler" | "HasDecorations" | "LinesCount" | "Superview" | "DrawingRect" | "MeasuredSize" | "RenderingScale" | "NeedMeasure" | "_superview" | "HitBoxAuto" | "TotalDown" | "TotalTapped" | "TouchDown" | "PostAnimators" | "LoadedSource" | "IsLoading" | "DisplayRect" | "AspectScale" | "Content" | "ContentSize" | "ContentOffsetBounds" | "OverscrollDistance" | "OverScrolled" | "IsUserPanning" | "IsUserFocused" | "IsScrolling" | "IsTemplated" | "FirstVisibleIndex" | "LastVisibleIndex" | "DebugString" | "ChildrenFactory" | "ContextIndex" | "RenderObject" | "UsingCacheType" | "TransitionEffect" | "TransitionFromIndex" | "TransitionToIndex" | "EffectPostRenderers" | "CachedImage" | "ImageBitmap" | "ShouldSubmitOnEnter" | "Header" | "Footer" | "RefreshIndicator" | "ScrollBar" | "ScrollBarHorizontal" | "IsRunning" | "VisibleRatio" | "CurrentIndex" | "LastCompositeRecord" | "DirtyChildrenInternal" | "IsRenderingWithComposition" ? never : K]: T[K];
|
|
45
|
+
[K in keyof T as T[K] extends Function ? (undefined extends T[K] ? K : never) : K extends "Children" | "Views" | "Parent" | "Spans" | "GridStructure" | "AccessibilityId" | "IsAccessibilityElement" | "HasTransform" | "RenderTransformMatrix" | "RenderObjectPrevious" | "LastMeasuredIndex" | "ItemsInsertedAtStart" | "UsingControlStyle" | "Track" | "Thumb" | "FrameOn" | "FrameOff" | "ViewCheckOn" | "ViewOn" | "ViewText" | "Ratio" | "StartThumbX" | "EndThumbX" | "SnapPoints" | "CurrentPosition" | "CurrentSnap" | "ContentOffsetBounds" | "InTransition" | "CanAnimate" | "MaxIndex" | "ChildrenTotal" | "IsAtStart" | "IsAtEnd" | "ScrollProgress" | "ScrollAmount" | "TransitionProgress" | "LastIndex" | "ChildrenCount" | "Horizontal" | "Animator" | "Animation" | "IsPlaying" | "PlayWhenAvailable" | "TotalFrames" | "HasEffects" | "IsDisposed" | "Label" | "IsMultiline" | "HasSelection" | "LayoutVersion" | "LinesCount" | "MeasuredLineHeight" | "Focused" | "SpriteSheet" | "FrameWidth" | "FrameHeight" | "DurationMs" | "FrameDurationMs" | "CurrentSprite" | "Rects" | "HasTapHandler" | "HasDecorations" | "LinesCount" | "Superview" | "DrawingRect" | "MeasuredSize" | "RenderingScale" | "NeedMeasure" | "_superview" | "HitBoxAuto" | "TotalDown" | "TotalTapped" | "TouchDown" | "PostAnimators" | "LoadedSource" | "IsLoading" | "DisplayRect" | "AspectScale" | "Content" | "ContentSize" | "ContentOffsetBounds" | "OverscrollDistance" | "OverScrolled" | "IsUserPanning" | "IsUserFocused" | "IsScrolling" | "IsTemplated" | "FirstVisibleIndex" | "LastVisibleIndex" | "DebugString" | "ChildrenFactory" | "ContextIndex" | "RenderObject" | "UsingCacheType" | "TransitionEffect" | "TransitionFromIndex" | "TransitionToIndex" | "EffectPostRenderers" | "CachedImage" | "ImageBitmap" | "ShouldSubmitOnEnter" | "Header" | "Footer" | "RefreshIndicator" | "ScrollBar" | "ScrollBarHorizontal" | "IsRunning" | "VisibleRatio" | "CurrentIndex" | "LastCompositeRecord" | "DirtyChildrenInternal" | "IsRenderingWithComposition" | "IsHovered" ? never : K]: T[K];
|
|
46
46
|
}>;
|
|
47
47
|
/** `ref` receives the engine control instance (react-reconciler getPublicInstance). */
|
|
48
48
|
type LeafProps<T> = PropsOf<T> & {
|
package/dist/react/index.js
CHANGED
|
@@ -221,9 +221,9 @@ function AccessibilityOverlay({ view }) {
|
|
|
221
221
|
n.Source.NotifyAccessibilityFocused(false);
|
|
222
222
|
}, children: n.Label }, n.Id)) : n.TextLines ? (
|
|
223
223
|
// AccessibilityTextSelectable: one positioned span per drawn line, in the drawn font, so the browser selects and copies it like HTML
|
|
224
|
-
_jsx("div", { role: n.Role, title: n.Hint, "aria-live": n.Live, className: "drawnui-a11y-node drawnui-a11y-text", style: pos, children: n.TextLines.map((l, i) => (_jsxs("span", { "data-w": l.Width, style: { left: l.Left, top: l.Top, height: l.Height, fontFamily: l.FontFamily, fontWeight: l.FontWeight, fontSize: l.FontSize, lineHeight: `${l.Height}px` }, children: [l.Text, i < n.TextLines.length - 1 ? "\n" : ""] }, i))) }, n.Id)) : (
|
|
224
|
+
_jsx("div", { role: n.Role, title: n.Hint, "aria-disabled": n.Disabled || undefined, "aria-live": n.Live, className: "drawnui-a11y-node drawnui-a11y-text", style: pos, children: n.TextLines.map((l, i) => (_jsxs("span", { "data-w": l.Width, style: { left: l.Left, top: l.Top, height: l.Height, fontFamily: l.FontFamily, fontWeight: l.FontWeight, fontSize: l.FontSize, lineHeight: `${l.Height}px` }, children: [l.Text, i < n.TextLines.length - 1 ? "\n" : ""] }, i))) }, n.Id)) : (
|
|
225
225
|
// static text is exposed as real (transparent) text content; aria-label only for roles that need a name
|
|
226
|
-
_jsx("div", { role: n.Role, "aria-label": n.Role === "text" ? undefined : n.Label, title: n.Hint, "aria-live": n.Live, className: "drawnui-a11y-node", style: pos, children: n.Label }, n.Id));
|
|
226
|
+
_jsx("div", { role: n.Role, "aria-label": n.Role === "text" ? undefined : n.Label, title: n.Hint, "aria-disabled": n.Disabled || undefined, "aria-live": n.Live, className: "drawnui-a11y-node", style: pos, children: n.Label }, n.Id));
|
|
227
227
|
})] }));
|
|
228
228
|
}
|
|
229
229
|
// One import for apps: React tags + every engine type (Colors, Thickness, Super, gestures, animators...).
|