@swiftbrowser/web 0.17.7 → 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/node/dist/node/apps.d.ts +5 -0
- package/node/dist/node/apps.d.ts.map +1 -1
- package/node/dist/node/apps.js +3 -0
- package/node/dist/node/apps.js.map +1 -1
- package/node/dist/node/config.d.ts +2 -0
- package/node/dist/node/config.d.ts.map +1 -1
- package/node/dist/node/config.js +2 -0
- package/node/dist/node/config.js.map +1 -1
- package/package.json +1 -1
- package/public/_headers +5 -0
- 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 +50 -5
- 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 +10 -1
- package/src/notifications.ts +134 -1
- package/src/pinch.ts +9 -1
- package/src/pinnedViews.ts +131 -0
- package/src/plainEditor.ts +79 -0
- package/src/protocol.ts +307 -14
- 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/vite-env.d.ts +2 -0
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
|
|
@@ -1229,7 +1274,7 @@ export interface PickFilesRequestParams {
|
|
|
1229
1274
|
* response value is a `NotificationResult`.
|
|
1230
1275
|
*/
|
|
1231
1276
|
export interface NotificationRequestParams {
|
|
1232
|
-
action: 'status' | 'request' | 'show' | 'close' | 'badge';
|
|
1277
|
+
action: 'status' | 'request' | 'show' | 'close' | 'badge' | 'pushSubscribe' | 'pushUnsubscribe' | 'receive';
|
|
1233
1278
|
/** `show`: the request's identifier, the notification's `tag`. */
|
|
1234
1279
|
id?: string;
|
|
1235
1280
|
title?: string;
|
|
@@ -1240,6 +1285,8 @@ export interface NotificationRequestParams {
|
|
|
1240
1285
|
badge?: number;
|
|
1241
1286
|
/** `close`: the identifiers to close. */
|
|
1242
1287
|
ids?: string[];
|
|
1288
|
+
/** `pushSubscribe`: the Web Push application server key (a VAPID public key, base64url). */
|
|
1289
|
+
applicationServerKey?: string;
|
|
1243
1290
|
}
|
|
1244
1291
|
|
|
1245
1292
|
/**
|
|
@@ -1450,7 +1497,12 @@ export type RendererEvent =
|
|
|
1450
1497
|
| VideoEvent
|
|
1451
1498
|
| LazyEvent
|
|
1452
1499
|
| MenuEvent
|
|
1453
|
-
| 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;
|
|
1454
1506
|
|
|
1455
1507
|
/**
|
|
1456
1508
|
* Phase 13: the page's answer to the `request` op with this `id`: `value`
|
|
@@ -1808,8 +1860,28 @@ export interface GestureProps {
|
|
|
1808
1860
|
rotate?: boolean;
|
|
1809
1861
|
minimumScaleDelta?: number;
|
|
1810
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;
|
|
1811
1880
|
}
|
|
1812
1881
|
|
|
1882
|
+
export type GestureCoordinateSpace = 'local' | 'global';
|
|
1883
|
+
export type GestureMode = 'simultaneous' | 'highPriority';
|
|
1884
|
+
|
|
1813
1885
|
/**
|
|
1814
1886
|
* `.swipeActions`: children are `[content, ...trailing actions, ...leading
|
|
1815
1887
|
* actions]` (`trailing` and `leading` count them); the actions are `button`s
|
|
@@ -1893,6 +1965,11 @@ export interface ListProps {
|
|
|
1893
1965
|
export interface ScrollViewProps {
|
|
1894
1966
|
refreshable?: boolean;
|
|
1895
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;
|
|
1896
1973
|
/** Phase 12 `.scrollTargetBehavior`: CSS scroll snapping on the axis. */
|
|
1897
1974
|
snap?: 'viewAligned' | 'paging';
|
|
1898
1975
|
/**
|
|
@@ -1914,6 +1991,13 @@ export interface ScrollViewProps {
|
|
|
1914
1991
|
export interface Style {
|
|
1915
1992
|
/** `.allowsHitTesting(false)`: `pointer-events: none` on the subtree. */
|
|
1916
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';
|
|
1917
2001
|
}
|
|
1918
2002
|
|
|
1919
2003
|
export interface Style {
|
|
@@ -1926,6 +2010,54 @@ export interface Style {
|
|
|
1926
2010
|
scrollVisibility?: { threshold: number };
|
|
1927
2011
|
}
|
|
1928
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
|
+
|
|
1929
2061
|
export interface Style {
|
|
1930
2062
|
/** `.blendMode`: the CSS `mix-blend-mode` the box is composited with. */
|
|
1931
2063
|
blendMode?: string;
|
|
@@ -1943,8 +2075,9 @@ export type DragPhase = 'began' | 'changed' | 'ended' | 'cancelled';
|
|
|
1943
2075
|
|
|
1944
2076
|
/**
|
|
1945
2077
|
* A `gesture` with `drag`: coalesced to one per animation frame while
|
|
1946
|
-
* `changed`. Coordinates are points relative to the element's box
|
|
1947
|
-
* `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).
|
|
1948
2081
|
*/
|
|
1949
2082
|
export interface DragEvent {
|
|
1950
2083
|
type: 'drag';
|
|
@@ -1962,7 +2095,10 @@ export interface DragEvent {
|
|
|
1962
2095
|
* `rotation` the turn of the line between them, in degrees, clockwise
|
|
1963
2096
|
* positive; the velocities are per second. `startLocation` is where the
|
|
1964
2097
|
* fingers' midpoint began, in points from the element's top leading corner;
|
|
1965
|
-
* `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.
|
|
1966
2102
|
*/
|
|
1967
2103
|
export interface PinchEvent {
|
|
1968
2104
|
type: 'pinch';
|
|
@@ -1974,6 +2110,7 @@ export interface PinchEvent {
|
|
|
1974
2110
|
rotationVelocity: number;
|
|
1975
2111
|
startLocation: Point;
|
|
1976
2112
|
startAnchor: Point;
|
|
2113
|
+
location?: Point;
|
|
1977
2114
|
}
|
|
1978
2115
|
/** A `gesture` with `longPress` was held `minimumDuration` without moving 10 px. */
|
|
1979
2116
|
export interface LongPressEvent {
|
|
@@ -2065,7 +2202,9 @@ export type AlertStyle = 'alert' | 'dialog';
|
|
|
2065
2202
|
* A root-level element (child of id 0) placed after the tree, like `sheet`.
|
|
2066
2203
|
* The children are the `button`s in order; a `cancel` role is drawn apart.
|
|
2067
2204
|
* With no button children the renderer draws an "OK" that sends `tap` with
|
|
2068
|
-
* 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.
|
|
2069
2208
|
*/
|
|
2070
2209
|
export interface AlertProps {
|
|
2071
2210
|
title: string;
|
|
@@ -2113,8 +2252,48 @@ export interface DatePickerProps {
|
|
|
2113
2252
|
/** A `<textarea>` filling the proposal; input sends `text` like a `textfield`. */
|
|
2114
2253
|
export interface TextEditorProps {
|
|
2115
2254
|
text: string;
|
|
2116
|
-
/** 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. */
|
|
2117
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[];
|
|
2118
2297
|
}
|
|
2119
2298
|
|
|
2120
2299
|
/** A `stepper` half was tapped: +1 or −1. */
|
|
@@ -2137,7 +2316,18 @@ export interface DateEvent {
|
|
|
2137
2316
|
id: ElementId;
|
|
2138
2317
|
value: number;
|
|
2139
2318
|
}
|
|
2140
|
-
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
|
+
}
|
|
2141
2331
|
|
|
2142
2332
|
/** Phase 12: a bound `textfield` (one with `focused` in its props) gained or lost focus. */
|
|
2143
2333
|
export interface FocusEvent {
|
|
@@ -2209,6 +2399,12 @@ export interface Style {
|
|
|
2209
2399
|
strikethrough?: boolean;
|
|
2210
2400
|
/** View `.italic(_:)`: slants the texts below (false turns it off). */
|
|
2211
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;
|
|
2212
2408
|
/**
|
|
2213
2409
|
* `.ignoresSafeArea(edges:)`: the engine extends the box to the screen
|
|
2214
2410
|
* edge on each listed side when the box touches that safe-area edge. The
|
|
@@ -2590,3 +2786,100 @@ export interface MediaRequestParams {
|
|
|
2590
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. */
|
|
2591
2787
|
path?: string;
|
|
2592
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
|
+
}
|