@swiftbrowser/web 0.17.8 → 0.18.0
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/package.json +1 -1
- package/src/animation.ts +60 -27
- package/src/appFiles.ts +21 -16
- package/src/audioRecorder.ts +392 -0
- package/src/editorSelection.ts +80 -0
- package/src/files.ts +442 -0
- package/src/gestureComposition.ts +92 -0
- package/src/hostRequests.ts +38 -4
- package/src/interaction.ts +108 -27
- package/src/layout/engine.ts +295 -19
- package/src/layout/types.ts +6 -0
- package/src/layoutDom.ts +13 -5
- package/src/main.ts +4 -0
- package/src/pinch.ts +9 -1
- package/src/pinnedViews.ts +131 -0
- package/src/plainEditor.ts +79 -0
- package/src/protocol.ts +304 -13
- package/src/renderer.ts +354 -43
- package/src/richEditor.ts +330 -0
- package/src/scrollGeometry.ts +79 -0
- package/src/scrollTransition.ts +145 -0
- package/src/styles.css +142 -11
- package/src/symbols.ts +22 -0
- package/src/touchPaging.ts +23 -2
- package/src/undo.ts +126 -0
- package/src/video.ts +59 -8
package/src/protocol.ts
CHANGED
|
@@ -455,6 +455,8 @@ export interface TextRun {
|
|
|
455
455
|
italic?: boolean;
|
|
456
456
|
/** A ShapeStyle JSON object (as `styled` `foreground`). */
|
|
457
457
|
foreground?: unknown;
|
|
458
|
+
/** A Color JSON object behind the run's glyphs (`AttributedString`'s `backgroundColor`). */
|
|
459
|
+
background?: unknown;
|
|
458
460
|
/** A line through or under the run; `color` defaults to the run's own. */
|
|
459
461
|
strikethrough?: { color?: unknown };
|
|
460
462
|
underline?: { color?: unknown };
|
|
@@ -479,7 +481,8 @@ export interface HStackProps {
|
|
|
479
481
|
export interface SpacerProps {
|
|
480
482
|
minLength: number | null;
|
|
481
483
|
}
|
|
482
|
-
|
|
484
|
+
/** `borderless` is `.borderless`: text-only in the tint, as `automatic`, and SwiftUI's own natively. */
|
|
485
|
+
export type ButtonStyle = 'automatic' | 'plain' | 'borderless' | 'bordered' | 'borderedProminent' | 'glass';
|
|
483
486
|
/** Phase 8: `cancel` is the role an `alert` draws apart (bold, or in its own card). */
|
|
484
487
|
export type ButtonRole = 'destructive' | 'cancel' | null;
|
|
485
488
|
/**
|
|
@@ -623,10 +626,22 @@ export interface TextFieldProps {
|
|
|
623
626
|
placeholder: string;
|
|
624
627
|
style: TextFieldStyle;
|
|
625
628
|
secure: boolean;
|
|
626
|
-
/**
|
|
629
|
+
/**
|
|
630
|
+
* Phase 12 `.focused(...)`: whether the field should have focus; present
|
|
631
|
+
* only on bound fields, which report `focus` events. The value the app's
|
|
632
|
+
* pass for a `submit` leaves (true again, or another field's turned true)
|
|
633
|
+
* wins over the platform's dismissal of the keyboard, and a field turning
|
|
634
|
+
* true is scrolled into view ("Focus across a submit").
|
|
635
|
+
*/
|
|
627
636
|
focused?: boolean;
|
|
628
637
|
/** Phase 12 `.onSubmit`: the Enter key sends a `submit` event. */
|
|
629
638
|
submit?: boolean;
|
|
639
|
+
/**
|
|
640
|
+
* `onDeleteBackward`: Backspace with the caret at the start of the text (an
|
|
641
|
+
* empty text included) sends `deletebackward` instead of deleting nothing
|
|
642
|
+
* (docs/ops-protocol.md, "The delete key at the start of a field").
|
|
643
|
+
*/
|
|
644
|
+
deleteBackward?: boolean;
|
|
630
645
|
/** Phase 12 `.submitLabel`: the return key's label (`enterkeyhint`). */
|
|
631
646
|
submitLabel?: string;
|
|
632
647
|
/** `.keyboardType(_:)`: a `UIKeyboardType` case name (`emailAddress`, `URL`, `numberPad`…), the on-screen keyboard (`inputmode`). */
|
|
@@ -638,8 +653,12 @@ export interface TextFieldProps {
|
|
|
638
653
|
/** `.autocorrectionDisabled()` (`autocorrect="off"`). */
|
|
639
654
|
autocorrectionDisabled?: boolean;
|
|
640
655
|
}
|
|
656
|
+
/** `.toggleStyle`: the switch (`automatic`, `switch`) or `button`, a button tinted while on. */
|
|
657
|
+
export type ToggleStyle = 'automatic' | 'switch' | 'button';
|
|
641
658
|
export interface ToggleProps {
|
|
642
659
|
isOn: boolean;
|
|
660
|
+
/** `.toggleStyle(_:)`; absent is `automatic` (the switch). */
|
|
661
|
+
style?: ToggleStyle;
|
|
643
662
|
}
|
|
644
663
|
export type NavStackProps = Record<string, never>;
|
|
645
664
|
export type NavDisplayMode = 'automatic' | 'large' | 'inline';
|
|
@@ -918,9 +937,12 @@ export interface MenuProps {
|
|
|
918
937
|
* `largeTitle` (iOS 26 `.largeTitle`): the items take the large title row in
|
|
919
938
|
* place of the title's text, scrolling with the content as the title does;
|
|
920
939
|
* the bar shows the title once the row has gone under it. Hidden while the
|
|
921
|
-
* screen's title is inline.
|
|
940
|
+
* screen's title is inline. `keyboard` (`.keyboard`): a 44 bar across the
|
|
941
|
+
* screen above the on-screen keyboard while a text input of the screen is
|
|
942
|
+
* focused (the input accessory view), its items in a row from the leading
|
|
943
|
+
* edge, a `spacer` child flexible; hidden otherwise.
|
|
922
944
|
*/
|
|
923
|
-
export type ToolbarPlacement = 'trailing' | 'leading' | 'principal' | 'bottom' | 'secondary' | 'largeTitle';
|
|
945
|
+
export type ToolbarPlacement = 'trailing' | 'leading' | 'principal' | 'bottom' | 'secondary' | 'largeTitle' | 'keyboard';
|
|
924
946
|
/**
|
|
925
947
|
* `.toolbar { ToolbarItem(placement:) { ... } }`, an extra child of a
|
|
926
948
|
* `navscreen` after its content. The children are the items, laid out at
|
|
@@ -958,6 +980,15 @@ export interface SearchFieldProps {
|
|
|
958
980
|
*/
|
|
959
981
|
export interface TapGestureProps {
|
|
960
982
|
location?: boolean;
|
|
983
|
+
/**
|
|
984
|
+
* `.onTapGesture(count:)`: the taps required, 1 when absent. With 2 the
|
|
985
|
+
* element sends one `tap` for two clicks within the double-tap interval
|
|
986
|
+
* (300 ms); a `tapgesture` of one tap around or inside it waits that
|
|
987
|
+
* interval before sending its own, as iOS delays a single tap while a
|
|
988
|
+
* double tap could still land (docs/ops-protocol.md, "Gesture spaces and
|
|
989
|
+
* composition").
|
|
990
|
+
*/
|
|
991
|
+
count?: number;
|
|
961
992
|
}
|
|
962
993
|
|
|
963
994
|
/**
|
|
@@ -1076,7 +1107,7 @@ export interface DefaultsOp {
|
|
|
1076
1107
|
export interface RequestOp {
|
|
1077
1108
|
op: 'request';
|
|
1078
1109
|
id: number;
|
|
1079
|
-
kind: 'fetch' | 'image' | 'share' | 'pickFiles' | 'notification' | 'scanner' | 'websocket' | 'openURL' | 'webAuth' | 'media' | 'download' | 'clipboard' | 'translate' | 'pickColor' | 'mediaSession';
|
|
1110
|
+
kind: 'fetch' | 'image' | 'share' | 'pickFiles' | 'notification' | 'scanner' | 'websocket' | 'openURL' | 'webAuth' | 'media' | 'download' | 'clipboard' | 'translate' | 'pickColor' | 'mediaSession' | 'undo';
|
|
1080
1111
|
params:
|
|
1081
1112
|
| FetchRequestParams
|
|
1082
1113
|
| ImageRequestParams
|
|
@@ -1092,7 +1123,21 @@ export interface RequestOp {
|
|
|
1092
1123
|
| ClipboardRequestParams
|
|
1093
1124
|
| TranslateRequestParams
|
|
1094
1125
|
| PickColorRequestParams
|
|
1095
|
-
| MediaSessionRequestParams
|
|
1126
|
+
| MediaSessionRequestParams
|
|
1127
|
+
| UndoRequestParams;
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* `undo` (docs/ops-protocol.md, "Undo"): what the Swift app's `UndoManager`
|
|
1131
|
+
* can do, after a turn that changed it, for the page's undo host
|
|
1132
|
+
* (src/undo.ts). Answered `{}`; the app does not wait for it. The page's
|
|
1133
|
+
* ⌘Z and ⇧⌘Z come back as `UndoEvent`s.
|
|
1134
|
+
*/
|
|
1135
|
+
export interface UndoRequestParams {
|
|
1136
|
+
canUndo: boolean;
|
|
1137
|
+
canRedo: boolean;
|
|
1138
|
+
/** The name of what undo takes back, '' for none. */
|
|
1139
|
+
undoActionName: string;
|
|
1140
|
+
redoActionName: string;
|
|
1096
1141
|
}
|
|
1097
1142
|
/**
|
|
1098
1143
|
* `translate` (Translation; src/translation.ts): `availability` of a pair
|
|
@@ -1452,7 +1497,12 @@ export type RendererEvent =
|
|
|
1452
1497
|
| VideoEvent
|
|
1453
1498
|
| LazyEvent
|
|
1454
1499
|
| MenuEvent
|
|
1455
|
-
| HoverEvent
|
|
1500
|
+
| HoverEvent
|
|
1501
|
+
// Scroll geometry and animation completion (the block at the end of this file)
|
|
1502
|
+
| ScrollGeometryEvent
|
|
1503
|
+
| AnimationCompleteEvent
|
|
1504
|
+
// The page's undo and redo keys, for the app's undo manager (src/undo.ts)
|
|
1505
|
+
| UndoEvent;
|
|
1456
1506
|
|
|
1457
1507
|
/**
|
|
1458
1508
|
* Phase 13: the page's answer to the `request` op with this `id`: `value`
|
|
@@ -1810,8 +1860,28 @@ export interface GestureProps {
|
|
|
1810
1860
|
rotate?: boolean;
|
|
1811
1861
|
minimumScaleDelta?: number;
|
|
1812
1862
|
minimumAngleDelta?: number;
|
|
1863
|
+
/**
|
|
1864
|
+
* `DragGesture(coordinateSpace:)`: the space of a `drag` event's `location`
|
|
1865
|
+
* and `startLocation`. `local` (the default) is the element's own box;
|
|
1866
|
+
* `global` the root's coordinates, scrolling included, the same a
|
|
1867
|
+
* `reportsFrame` geometry event reports, so a named space is the global
|
|
1868
|
+
* point less that space's reported origin.
|
|
1869
|
+
*/
|
|
1870
|
+
coordinateSpace?: GestureCoordinateSpace;
|
|
1871
|
+
/**
|
|
1872
|
+
* How the gesture composes with the others on the pointer's way to the
|
|
1873
|
+
* root (src/interaction.ts). Absent, `.gesture`: the innermost gesture
|
|
1874
|
+
* whose motion matches wins. `highPriority` (`.highPriorityGesture`): asked
|
|
1875
|
+
* before the gestures of the views inside it. `simultaneous`
|
|
1876
|
+
* (`.simultaneousGesture`): begins when its own distance is met and runs
|
|
1877
|
+
* beside whatever else owns the pointer, never claiming it from them.
|
|
1878
|
+
*/
|
|
1879
|
+
mode?: GestureMode;
|
|
1813
1880
|
}
|
|
1814
1881
|
|
|
1882
|
+
export type GestureCoordinateSpace = 'local' | 'global';
|
|
1883
|
+
export type GestureMode = 'simultaneous' | 'highPriority';
|
|
1884
|
+
|
|
1815
1885
|
/**
|
|
1816
1886
|
* `.swipeActions`: children are `[content, ...trailing actions, ...leading
|
|
1817
1887
|
* actions]` (`trailing` and `leading` count them); the actions are `button`s
|
|
@@ -1895,6 +1965,11 @@ export interface ListProps {
|
|
|
1895
1965
|
export interface ScrollViewProps {
|
|
1896
1966
|
refreshable?: boolean;
|
|
1897
1967
|
refreshing?: boolean;
|
|
1968
|
+
/**
|
|
1969
|
+
* `.scrollIndicators(.hidden)` (or `ScrollView(showsIndicators: false)`):
|
|
1970
|
+
* false hides the scroll bars natively; the page draws none either way.
|
|
1971
|
+
*/
|
|
1972
|
+
showsIndicators?: boolean;
|
|
1898
1973
|
/** Phase 12 `.scrollTargetBehavior`: CSS scroll snapping on the axis. */
|
|
1899
1974
|
snap?: 'viewAligned' | 'paging';
|
|
1900
1975
|
/**
|
|
@@ -1916,6 +1991,13 @@ export interface ScrollViewProps {
|
|
|
1916
1991
|
export interface Style {
|
|
1917
1992
|
/** `.allowsHitTesting(false)`: `pointer-events: none` on the subtree. */
|
|
1918
1993
|
hitTesting?: boolean;
|
|
1994
|
+
/**
|
|
1995
|
+
* `.contentShape(Rectangle())`: the whole box takes taps and gestures,
|
|
1996
|
+
* whatever is drawn in it (a clear fill, a stroke, the gaps between
|
|
1997
|
+
* views). Natively the modifier itself; the page's boxes already take
|
|
1998
|
+
* input across their area, so it only marks the box (`data-sb-content-shape`).
|
|
1999
|
+
*/
|
|
2000
|
+
contentShape?: 'rectangle';
|
|
1919
2001
|
}
|
|
1920
2002
|
|
|
1921
2003
|
export interface Style {
|
|
@@ -1928,6 +2010,54 @@ export interface Style {
|
|
|
1928
2010
|
scrollVisibility?: { threshold: number };
|
|
1929
2011
|
}
|
|
1930
2012
|
|
|
2013
|
+
/**
|
|
2014
|
+
* The effects a scroll transition draws in one phase: the visual-effect
|
|
2015
|
+
* fields of a `Style` (none of them changes the layout).
|
|
2016
|
+
*/
|
|
2017
|
+
export type ScrollTransitionEffect = Pick<
|
|
2018
|
+
Style,
|
|
2019
|
+
| 'offset'
|
|
2020
|
+
| 'scale'
|
|
2021
|
+
| 'scaleAnchor'
|
|
2022
|
+
| 'rotation'
|
|
2023
|
+
| 'rotationAnchor'
|
|
2024
|
+
| 'rotation3D'
|
|
2025
|
+
| 'opacity'
|
|
2026
|
+
| 'blur'
|
|
2027
|
+
| 'brightness'
|
|
2028
|
+
| 'contrast'
|
|
2029
|
+
| 'saturation'
|
|
2030
|
+
| 'grayscale'
|
|
2031
|
+
| 'hueRotation'
|
|
2032
|
+
>;
|
|
2033
|
+
|
|
2034
|
+
/**
|
|
2035
|
+
* `.scrollTransition(_:axis:transition:)`: the transition's effects in its
|
|
2036
|
+
* three phases (its closure called once for each), which the renderer draws
|
|
2037
|
+
* as the box moves through its scroll view, without a round trip.
|
|
2038
|
+
*/
|
|
2039
|
+
export interface ScrollTransition {
|
|
2040
|
+
/**
|
|
2041
|
+
* `interactive`: between phases as the box crosses the scroll view's edge,
|
|
2042
|
+
* by how far it is out (0 wholly in view, 1 wholly out); `animated`: the
|
|
2043
|
+
* phase's effects, animated, once the box is partly out; `identity`: the
|
|
2044
|
+
* identity phase's always.
|
|
2045
|
+
*/
|
|
2046
|
+
configuration: 'interactive' | 'animated' | 'identity';
|
|
2047
|
+
/** The axis it follows; the scroll view's own when absent. */
|
|
2048
|
+
axis?: 'horizontal' | 'vertical';
|
|
2049
|
+
identity: ScrollTransitionEffect;
|
|
2050
|
+
/** Going out past the top or leading edge. */
|
|
2051
|
+
topLeading: ScrollTransitionEffect;
|
|
2052
|
+
/** Going out past the bottom or trailing edge. */
|
|
2053
|
+
bottomTrailing: ScrollTransitionEffect;
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2056
|
+
export interface Style {
|
|
2057
|
+
/** `.scrollTransition`: effects drawn as the box scrolls in and out of view (scrollTransition.ts). */
|
|
2058
|
+
scrollTransition?: ScrollTransition;
|
|
2059
|
+
}
|
|
2060
|
+
|
|
1931
2061
|
export interface Style {
|
|
1932
2062
|
/** `.blendMode`: the CSS `mix-blend-mode` the box is composited with. */
|
|
1933
2063
|
blendMode?: string;
|
|
@@ -1945,8 +2075,9 @@ export type DragPhase = 'began' | 'changed' | 'ended' | 'cancelled';
|
|
|
1945
2075
|
|
|
1946
2076
|
/**
|
|
1947
2077
|
* A `gesture` with `drag`: coalesced to one per animation frame while
|
|
1948
|
-
* `changed`. Coordinates are points relative to the element's box
|
|
1949
|
-
* `velocity` is in points per
|
|
2078
|
+
* `changed`. Coordinates are points relative to the element's box (the
|
|
2079
|
+
* root's with `coordinateSpace: "global"`); `velocity` is in points per
|
|
2080
|
+
* second (`ended` only, else 0).
|
|
1950
2081
|
*/
|
|
1951
2082
|
export interface DragEvent {
|
|
1952
2083
|
type: 'drag';
|
|
@@ -1964,7 +2095,10 @@ export interface DragEvent {
|
|
|
1964
2095
|
* `rotation` the turn of the line between them, in degrees, clockwise
|
|
1965
2096
|
* positive; the velocities are per second. `startLocation` is where the
|
|
1966
2097
|
* fingers' midpoint began, in points from the element's top leading corner;
|
|
1967
|
-
* `startAnchor` the same as a fraction of the element's size.
|
|
2098
|
+
* `startAnchor` the same as a fraction of the element's size. `location` is
|
|
2099
|
+
* where the midpoint is now (a SwiftBrowser addition: SwiftUI's values stop
|
|
2100
|
+
* at the start), so two fingers can pan as they zoom; a trackpad pinch keeps
|
|
2101
|
+
* its start. A renderer that cannot tell leaves it out.
|
|
1968
2102
|
*/
|
|
1969
2103
|
export interface PinchEvent {
|
|
1970
2104
|
type: 'pinch';
|
|
@@ -1976,6 +2110,7 @@ export interface PinchEvent {
|
|
|
1976
2110
|
rotationVelocity: number;
|
|
1977
2111
|
startLocation: Point;
|
|
1978
2112
|
startAnchor: Point;
|
|
2113
|
+
location?: Point;
|
|
1979
2114
|
}
|
|
1980
2115
|
/** A `gesture` with `longPress` was held `minimumDuration` without moving 10 px. */
|
|
1981
2116
|
export interface LongPressEvent {
|
|
@@ -2067,7 +2202,9 @@ export type AlertStyle = 'alert' | 'dialog';
|
|
|
2067
2202
|
* A root-level element (child of id 0) placed after the tree, like `sheet`.
|
|
2068
2203
|
* The children are the `button`s in order; a `cancel` role is drawn apart.
|
|
2069
2204
|
* With no button children the renderer draws an "OK" that sends `tap` with
|
|
2070
|
-
* the alert's own id; so does a tap on a dialog's scrim.
|
|
2205
|
+
* the alert's own id; so does a tap on a dialog's scrim. `textfield`
|
|
2206
|
+
* children (`.alert { TextField(...); Button(...) }`) are drawn in the card
|
|
2207
|
+
* between the message and the buttons, in their order.
|
|
2071
2208
|
*/
|
|
2072
2209
|
export interface AlertProps {
|
|
2073
2210
|
title: string;
|
|
@@ -2115,8 +2252,48 @@ export interface DatePickerProps {
|
|
|
2115
2252
|
/** A `<textarea>` filling the proposal; input sends `text` like a `textfield`. */
|
|
2116
2253
|
export interface TextEditorProps {
|
|
2117
2254
|
text: string;
|
|
2118
|
-
/** Bound focus (UIKit's `becomeFirstResponder`): the editor takes or gives up focus; `focus` events report changes. */
|
|
2255
|
+
/** Bound focus (UIKit's `becomeFirstResponder`): the editor takes or gives up focus (scrolled into view as it does); `focus` events report changes. */
|
|
2119
2256
|
focused?: boolean;
|
|
2257
|
+
/** As a `textfield`'s: Backspace at the start of the text sends `deletebackward`. */
|
|
2258
|
+
deleteBackward?: boolean;
|
|
2259
|
+
/**
|
|
2260
|
+
* Attributed text (`TextEditor(text: $attributedString)`): the runs `text`
|
|
2261
|
+
* is made of, drawn with each run's weight, slant, lines and color. An
|
|
2262
|
+
* editor with runs (an empty array included) is the rich editor for its
|
|
2263
|
+
* life; it still reports plain `text`, and the app keeps the runs.
|
|
2264
|
+
*/
|
|
2265
|
+
runs?: TextRun[];
|
|
2266
|
+
/**
|
|
2267
|
+
* A bound selection (`selection:`), on a plain editor or a rich one: the
|
|
2268
|
+
* editor reports the viewer's with `selection` events, and moves to one
|
|
2269
|
+
* the app sets (when the app focuses the editor, if it is not focused).
|
|
2270
|
+
*/
|
|
2271
|
+
selection?: TextSelectionRange;
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
/** A range of an editor's text in UTF-16 offsets; `start === end` is the caret. */
|
|
2275
|
+
export interface TextSelectionRange {
|
|
2276
|
+
start: number;
|
|
2277
|
+
end: number;
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
/** A `texteditor` with `selection` in its props: the viewer moved the caret or selected. */
|
|
2281
|
+
export interface SelectionEvent {
|
|
2282
|
+
type: 'selection';
|
|
2283
|
+
id: ElementId;
|
|
2284
|
+
value: TextSelectionRange;
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
/**
|
|
2288
|
+
* A rich `texteditor`'s runs after an edit of their attributes alone (the
|
|
2289
|
+
* native editor's own Bold, Italic and Underline, iOS 26's edit menu): the
|
|
2290
|
+
* text unchanged, `value` its runs as the editor now shows them, each run's
|
|
2291
|
+
* other attributes (a color, a link) as the app sent them.
|
|
2292
|
+
*/
|
|
2293
|
+
export interface RunsEvent {
|
|
2294
|
+
type: 'runs';
|
|
2295
|
+
id: ElementId;
|
|
2296
|
+
value: TextRun[];
|
|
2120
2297
|
}
|
|
2121
2298
|
|
|
2122
2299
|
/** A `stepper` half was tapped: +1 or −1. */
|
|
@@ -2139,7 +2316,18 @@ export interface DateEvent {
|
|
|
2139
2316
|
id: ElementId;
|
|
2140
2317
|
value: number;
|
|
2141
2318
|
}
|
|
2142
|
-
export type Phase8ControlEvent = StepEvent | SlideEvent | DateEvent | FocusEvent | SubmitEvent;
|
|
2319
|
+
export type Phase8ControlEvent = StepEvent | SlideEvent | DateEvent | FocusEvent | SubmitEvent | SelectionEvent | RunsEvent | DeleteBackwardEvent;
|
|
2320
|
+
|
|
2321
|
+
/**
|
|
2322
|
+
* Backspace in a `textfield` or `texteditor` with `deleteBackward`, with
|
|
2323
|
+
* nothing selected and the caret at offset 0 (so nothing to delete): the
|
|
2324
|
+
* app merges the field into what comes before it, say. The key deletes
|
|
2325
|
+
* nothing of its own.
|
|
2326
|
+
*/
|
|
2327
|
+
export interface DeleteBackwardEvent {
|
|
2328
|
+
type: 'deletebackward';
|
|
2329
|
+
id: ElementId;
|
|
2330
|
+
}
|
|
2143
2331
|
|
|
2144
2332
|
/** Phase 12: a bound `textfield` (one with `focused` in its props) gained or lost focus. */
|
|
2145
2333
|
export interface FocusEvent {
|
|
@@ -2211,6 +2399,12 @@ export interface Style {
|
|
|
2211
2399
|
strikethrough?: boolean;
|
|
2212
2400
|
/** View `.italic(_:)`: slants the texts below (false turns it off). */
|
|
2213
2401
|
italic?: boolean;
|
|
2402
|
+
/**
|
|
2403
|
+
* `.scrollDisabled(_:)`, inherited: the views below do not scroll; a
|
|
2404
|
+
* `texteditor` is then as tall as its lines (a text view that does not
|
|
2405
|
+
* scroll), whatever the proposal. False turns an ancestor's off.
|
|
2406
|
+
*/
|
|
2407
|
+
scrollDisabled?: boolean;
|
|
2214
2408
|
/**
|
|
2215
2409
|
* `.ignoresSafeArea(edges:)`: the engine extends the box to the screen
|
|
2216
2410
|
* edge on each listed side when the box touches that safe-area edge. The
|
|
@@ -2592,3 +2786,100 @@ export interface MediaRequestParams {
|
|
|
2592
2786
|
/** `file`: a resource's path inside the app's bundle, in place of `data`: the page answers the URL it serves the resource at. */
|
|
2593
2787
|
path?: string;
|
|
2594
2788
|
}
|
|
2789
|
+
|
|
2790
|
+
// ---------------------------------------------------------------------------
|
|
2791
|
+
// Scroll geometry, settable offsets, pinned views, animation completion
|
|
2792
|
+
// (docs/ops-protocol.md, "Scroll geometry, pinned views and animation completion")
|
|
2793
|
+
// ---------------------------------------------------------------------------
|
|
2794
|
+
|
|
2795
|
+
export interface ScrollViewProps {
|
|
2796
|
+
/**
|
|
2797
|
+
* `.onScrollGeometryChange(for:of:action:)`: the page sends `scrollgeometry`
|
|
2798
|
+
* to the view after each layout pass and, while it scrolls, once per
|
|
2799
|
+
* animation frame, whenever a field changed (src/scrollGeometry.ts).
|
|
2800
|
+
*/
|
|
2801
|
+
reportsGeometry?: boolean;
|
|
2802
|
+
/**
|
|
2803
|
+
* `ScrollPosition.scrollTo(x:y:)` (a `.scrollPosition` bound to a point):
|
|
2804
|
+
* the content offset to scroll to, carried out once per `serial` after the
|
|
2805
|
+
* pass's layout, smoothly when the commit is animated. An axis left out
|
|
2806
|
+
* keeps its offset; the browser clamps the ends.
|
|
2807
|
+
*/
|
|
2808
|
+
scrollOffset?: ScrollOffsetCommand;
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
export interface ScrollOffsetCommand {
|
|
2812
|
+
x?: number;
|
|
2813
|
+
y?: number;
|
|
2814
|
+
/** Increases with every request; the page carries out each serial once. */
|
|
2815
|
+
serial: number;
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
/**
|
|
2819
|
+
* SwiftUI's `ScrollGeometry` for a `scrollview` with `reportsGeometry`:
|
|
2820
|
+
* where its visible area is in its content and how big both are, in points
|
|
2821
|
+
* (2 decimals). Sent after a layout pass and, while the view scrolls, once
|
|
2822
|
+
* per animation frame, when any field changed since the last report.
|
|
2823
|
+
*/
|
|
2824
|
+
export interface ScrollGeometryEvent {
|
|
2825
|
+
type: 'scrollgeometry';
|
|
2826
|
+
id: ElementId;
|
|
2827
|
+
/** The visible area's origin in the content (`scrollLeft`, `scrollTop`). */
|
|
2828
|
+
offset: { x: number; y: number };
|
|
2829
|
+
/** The content's laid-out size. */
|
|
2830
|
+
contentSize: { width: number; height: number };
|
|
2831
|
+
/** The scroll view's own size. */
|
|
2832
|
+
containerSize: { width: number; height: number };
|
|
2833
|
+
/** Space the view scrolls into past its content (under a bar covering its bottom); zeros on the web otherwise. */
|
|
2834
|
+
contentInsets: { top: number; leading: number; bottom: number; trailing: number };
|
|
2835
|
+
}
|
|
2836
|
+
|
|
2837
|
+
/** `PinnedScrollableViews`: what a lazy stack or grid keeps in view as its sections scroll. */
|
|
2838
|
+
export type PinnedView = 'sectionHeaders' | 'sectionFooters';
|
|
2839
|
+
|
|
2840
|
+
export interface VStackProps {
|
|
2841
|
+
/**
|
|
2842
|
+
* `LazyVStack(pinnedViews:)`: the `sectionheader` (`sectionfooter`) of each
|
|
2843
|
+
* `section` child stays at the scroll view's edge while its section
|
|
2844
|
+
* passes, pushed out by the next section's (src/pinnedViews.ts).
|
|
2845
|
+
*/
|
|
2846
|
+
pinned?: PinnedView[];
|
|
2847
|
+
}
|
|
2848
|
+
export interface HStackProps {
|
|
2849
|
+
/** `LazyHStack(pinnedViews:)`: as for `vstack`, along the leading edge. */
|
|
2850
|
+
pinned?: PinnedView[];
|
|
2851
|
+
}
|
|
2852
|
+
export interface LazyVGridProps {
|
|
2853
|
+
/** `LazyVGrid(pinnedViews:)`: as for `vstack`. */
|
|
2854
|
+
pinned?: PinnedView[];
|
|
2855
|
+
}
|
|
2856
|
+
export interface LazyHGridProps {
|
|
2857
|
+
/** `LazyHGrid(pinnedViews:)`: as for `hstack`. */
|
|
2858
|
+
pinned?: PinnedView[];
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
export interface CommitOp {
|
|
2862
|
+
/**
|
|
2863
|
+
* `withAnimation(_:completionCriteria:_:completion:)`: the page answers
|
|
2864
|
+
* `animationcomplete` with this serial once the pass's animations have
|
|
2865
|
+
* ended (at once, after the pass, when nothing animated).
|
|
2866
|
+
*/
|
|
2867
|
+
completion?: number;
|
|
2868
|
+
/** `logicallyComplete` (the default) ends with the animation's duration; `removed` once every effect is gone. */
|
|
2869
|
+
completionCriteria?: 'logicallyComplete' | 'removed';
|
|
2870
|
+
}
|
|
2871
|
+
|
|
2872
|
+
/** The pass whose `commit` carried `completion` has finished animating. Not addressed to an element. */
|
|
2873
|
+
export interface AnimationCompleteEvent {
|
|
2874
|
+
type: 'animationcomplete';
|
|
2875
|
+
serial: number;
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
/**
|
|
2879
|
+
* The system's undo or redo (⌘Z, ⇧⌘Z outside a text input; src/undo.ts),
|
|
2880
|
+
* for the app's `UndoManager`, which takes a step back or forward. Not
|
|
2881
|
+
* addressed to an element; sent once the app has reported an `undo` request.
|
|
2882
|
+
*/
|
|
2883
|
+
export interface UndoEvent {
|
|
2884
|
+
type: 'undo' | 'redo';
|
|
2885
|
+
}
|