@gjsify/react-native 0.45.0 → 0.47.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/PROPS.md +525 -0
- package/README.md +45 -163
- package/SUPPORT.md +472 -0
- package/lib/esm/accessor.js +1 -0
- package/lib/esm/animated/brand.js +1 -0
- package/lib/esm/animated/easing.js +1 -0
- package/lib/esm/animated/index.js +1 -0
- package/lib/esm/animated/properties.js +1 -0
- package/lib/esm/animated/timing.js +1 -0
- package/lib/esm/animated/value.js +1 -0
- package/lib/esm/announce.js +1 -0
- package/lib/esm/app-registry.js +1 -1
- package/lib/esm/components.js +1 -1
- package/lib/esm/generated/own-exports.js +1 -1
- package/lib/esm/generated/unsupported-async-storage.js +0 -0
- package/lib/esm/generated/unsupported-expo-audio.js +1 -0
- package/lib/esm/generated/unsupported-expo-constants.js +1 -0
- package/lib/esm/generated/unsupported-expo-font.js +1 -0
- package/lib/esm/generated/unsupported-expo-image.js +1 -0
- package/lib/esm/generated/unsupported-expo-linking.js +1 -0
- package/lib/esm/generated/unsupported-expo-splash-screen.js +1 -0
- package/lib/esm/generated/unsupported-expo-status-bar.js +1 -0
- package/lib/esm/generated/unsupported-expo-system-ui.js +1 -0
- package/lib/esm/generated/unsupported-expo-video.js +1 -0
- package/lib/esm/generated/unsupported-expo-web-browser.js +1 -0
- package/lib/esm/generated/unsupported-nativewind.js +1 -0
- package/lib/esm/generated/unsupported-react-native-gesture-handler.js +1 -0
- package/lib/esm/generated/unsupported-react-native-safe-area-context.js +1 -0
- package/lib/esm/generated/unsupported-react-native-webview.js +1 -0
- package/lib/esm/generated/unsupported-react-native.js +1 -0
- package/lib/esm/generated/unsupported-router.js +1 -0
- package/lib/esm/generated/unsupported-vector-icons.js +1 -0
- package/lib/esm/index.js +1 -1
- package/lib/esm/lists/controller.js +1 -1
- package/lib/esm/primitives/answers.js +1 -0
- package/lib/esm/primitives/defaults.js +1 -0
- package/lib/esm/primitives/errors.js +1 -1
- package/lib/esm/primitives/handles.js +1 -0
- package/lib/esm/primitives/index.js +1 -1
- package/lib/esm/primitives/intents.js +1 -1
- package/lib/esm/primitives/resolve.js +1 -1
- package/lib/esm/primitives/style.js +1 -1
- package/lib/esm/primitives/table.js +1 -1
- package/lib/esm/prop-table.js +1 -0
- package/lib/esm/router/href.js +1 -0
- package/lib/esm/router/index.js +1 -1
- package/lib/esm/router/navigation.js +1 -1
- package/lib/esm/router/tabs.js +1 -1
- package/lib/esm/solid/index.js +1 -1
- package/lib/esm/stylesheet.js +1 -1
- package/lib/esm/support-table.js +1 -1
- package/lib/esm/surfaces/async-storage.js +1 -0
- package/lib/esm/surfaces/expo-audio.js +1 -0
- package/lib/esm/surfaces/expo-constants.js +1 -0
- package/lib/esm/surfaces/expo-font.js +1 -0
- package/lib/esm/surfaces/expo-image.js +1 -0
- package/lib/esm/surfaces/expo-linking.js +1 -0
- package/lib/esm/surfaces/expo-splash-screen.js +1 -0
- package/lib/esm/surfaces/expo-status-bar.js +1 -0
- package/lib/esm/surfaces/expo-system-ui.js +1 -0
- package/lib/esm/surfaces/expo-video.js +1 -0
- package/lib/esm/surfaces/expo-web-browser.js +1 -0
- package/lib/esm/surfaces/icon-map.js +1 -0
- package/lib/esm/surfaces/nativewind.js +1 -0
- package/lib/esm/surfaces/react-native-gesture-handler.js +1 -0
- package/lib/esm/surfaces/react-native-safe-area-context.js +1 -0
- package/lib/esm/surfaces/react-native-webview.js +1 -0
- package/lib/esm/surfaces/vector-icons.js +1 -0
- package/lib/esm/unsupported.js +1 -1
- package/lib/types/accessor.d.ts +10 -0
- package/lib/types/animated/animated.spec.d.ts +2 -0
- package/lib/types/animated/brand.d.ts +8 -0
- package/lib/types/animated/easing.d.ts +70 -0
- package/lib/types/animated/easing.spec.d.ts +2 -0
- package/lib/types/animated/index.d.ts +55 -0
- package/lib/types/animated/properties.d.ts +33 -0
- package/lib/types/animated/timing.d.ts +37 -0
- package/lib/types/animated/value.d.ts +103 -0
- package/lib/types/announce.d.ts +18 -0
- package/lib/types/components.d.ts +82 -3
- package/lib/types/generated/unsupported-async-storage.d.ts +1 -0
- package/lib/types/generated/unsupported-expo-audio.d.ts +4 -0
- package/lib/types/generated/unsupported-expo-constants.d.ts +2 -0
- package/lib/types/generated/unsupported-expo-font.d.ts +4 -0
- package/lib/types/generated/unsupported-expo-image.d.ts +3 -0
- package/lib/types/generated/unsupported-expo-linking.d.ts +4 -0
- package/lib/types/generated/unsupported-expo-splash-screen.d.ts +5 -0
- package/lib/types/generated/unsupported-expo-status-bar.d.ts +5 -0
- package/lib/types/generated/unsupported-expo-system-ui.d.ts +2 -0
- package/lib/types/generated/unsupported-expo-video.d.ts +3 -0
- package/lib/types/generated/unsupported-expo-web-browser.d.ts +6 -0
- package/lib/types/generated/unsupported-nativewind.d.ts +5 -0
- package/lib/types/generated/unsupported-react-native-gesture-handler.d.ts +10 -0
- package/lib/types/generated/unsupported-react-native-safe-area-context.d.ts +4 -0
- package/lib/types/generated/unsupported-react-native-webview.d.ts +1 -0
- package/lib/types/generated/{unsupported-exports.d.ts → unsupported-react-native.d.ts} +0 -2
- package/lib/types/generated/unsupported-vector-icons.d.ts +11 -0
- package/lib/types/index.d.ts +5 -1
- package/lib/types/primitives/answers.d.ts +69 -0
- package/lib/types/primitives/defaults.d.ts +52 -0
- package/lib/types/primitives/defaults.spec.d.ts +2 -0
- package/lib/types/primitives/errors.d.ts +9 -0
- package/lib/types/primitives/handles.d.ts +56 -0
- package/lib/types/primitives/index.d.ts +8 -2
- package/lib/types/primitives/intents.d.ts +36 -0
- package/lib/types/primitives/resolve.d.ts +25 -1
- package/lib/types/primitives/table.d.ts +63 -1
- package/lib/types/prop-table.d.ts +56 -0
- package/lib/types/prop-table.spec.d.ts +2 -0
- package/lib/types/router/href.d.ts +58 -0
- package/lib/types/router/href.spec.d.ts +2 -0
- package/lib/types/router/index.d.ts +3 -1
- package/lib/types/router/navigation.d.ts +47 -5
- package/lib/types/router/tabs.d.ts +35 -0
- package/lib/types/solid/index.d.ts +15 -1
- package/lib/types/support-table.d.ts +79 -10
- package/lib/types/surfaces/async-storage.d.ts +57 -0
- package/lib/types/surfaces/expo-audio.d.ts +1 -0
- package/lib/types/surfaces/expo-constants.d.ts +11 -0
- package/lib/types/surfaces/expo-font.d.ts +34 -0
- package/lib/types/surfaces/expo-image.d.ts +1 -0
- package/lib/types/surfaces/expo-linking.d.ts +36 -0
- package/lib/types/surfaces/expo-splash-screen.d.ts +1 -0
- package/lib/types/surfaces/expo-status-bar.d.ts +16 -0
- package/lib/types/surfaces/expo-system-ui.d.ts +1 -0
- package/lib/types/surfaces/expo-video.d.ts +1 -0
- package/lib/types/surfaces/expo-web-browser.d.ts +21 -0
- package/lib/types/surfaces/icon-map.d.ts +14 -0
- package/lib/types/surfaces/nativewind.d.ts +1 -0
- package/lib/types/surfaces/react-native-gesture-handler.d.ts +10 -0
- package/lib/types/surfaces/react-native-safe-area-context.d.ts +60 -0
- package/lib/types/surfaces/react-native-webview.d.ts +4 -0
- package/lib/types/surfaces/surfaces.spec.d.ts +2 -0
- package/lib/types/surfaces/vector-icons.d.ts +15 -0
- package/lib/types/unsupported.d.ts +12 -3
- package/package.json +85 -14
- package/lib/esm/generated/unsupported-exports.js +0 -1
- package/lib/esm/generated/unsupported-router-exports.js +0 -1
- /package/lib/types/generated/{unsupported-router-exports.d.ts → unsupported-router.d.ts} +0 -0
package/lib/esm/support-table.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{OWN_EXPORT_NAMES as e}from"./generated/own-exports.js";const t={View:{status:`partial`,tier:`P1`,gtk:`Gtk.Box, or Gtk.Overlay when a child is absolutely positioned`,reason:`The container primitive. Which widget it becomes depends on its children, not on the element.`,limits:[`An absolutely positioned child is placed by alignment plus a margin, because Gtk.Overlay positions an overlay child by its halign/valign and has no coordinate pair. An offset on only ONE edge of an axis therefore leaves the other axis at GTK’s default (fill), where React Native would keep the child at its static position — a position GTK has no way to express for an overlay child.`,`onLayout is refused: GTK reports allocation through Gtk.Widget.vfunc_size_allocate, a subclass override rather than a signal.`,`pointerEvents answers auto and none only. box-none and box-only split hit-testing between a widget and its subtree, and Gtk.Widget:can-target is one boolean for both.`]},Text:{status:`partial`,tier:`P1`,gtk:`Gtk.Label`,reason:`Wrapping is ON by default in React Native and OFF on a Gtk.Label, so the default is set explicitly.`,limits:[`A nested <Text> is refused by the host naming the tag: Gtk.Label takes no children (measured), so React Native’s inline-styling idiom has no counterpart. Use Pango markup through a ref, or separate labels.`,`ellipsizeMode="clip" is refused: PangoEllipsizeMode is NONE, START, MIDDLE, END (measured) and has no clip member, so honouring it would add an ellipsis the author asked not to have.`,`onPress is refused: a Gtk.Label emits no clicked signal (measured). Wrap it in a <Pressable>.`]},Pressable:{status:`partial`,tier:`P1`,gtk:`Gtk.Button (flat)`,reason:`Press state is a GTK CSS :active pseudo-class; children-as-a-function is implemented over the state flag, and costs nothing when it is unused.`,limits:[`children-as-a-function-of-{ pressed } reads the widget’s Gtk.StateFlags.ACTIVE through Gtk.Widget::state-flags-changed, because Gtk.Button installs no active property (measured). An element that does NOT use the function form subscribes to nothing — press styling written as active:* is CSS and never reaches the reconciler (ADR 0032 § 7), and pressWatchCount() is what holds the two apart.`,`onPressIn/onPressOut are refused: they report the press as an EVENT, and the state flag reports it as a state. Use the function form, or active:*.`,`onLongPress is refused: a long press is a Gtk.GestureLongPress controller added to the widget, not a property or a signal on it.`,`hitSlop is refused: GTK hit-tests the allocation and cannot grow it past the widget. Pad the button instead, which enlarges the real target.`]},ScrollView:{status:`partial`,tier:`P1`,gtk:`Gtk.ScrolledWindow + an implicit content box`,reason:`contentContainerStyle styles the inner box, which is a second styleable node.`,limits:[`onScroll and scrollEventThrottle are refused: GTK reports scroll position as notify::value on the Gtk.Adjustment behind hadjustment/vadjustment, an object rather than a signal on the scrolled window. Reach the adjustment through a ref.`,`scrollEnabled is refused: a Gtk.ScrolledWindow has no switch that stops scrolling, and setting both policies to never clamps the child as well as hiding the bars.`,`refreshControl is refused, matching RefreshControl’s own entry: GTK has no pull-to-refresh idiom.`,`Layout utilities that need a box (items-*, gap-*, justify-*) are refused on style and belong on contentContainerStyle — which is React Native’s own rule, not a GTK one.`]},ActivityIndicator:{status:`partial`,tier:`P1`,gtk:`Adw.Spinner`,reason:`Direct counterpart.`,limits:[`animating={false} hides the widget. MEASURED: Adw.Spinner installs 36 properties and every one is Gtk.Widget’s — there is nothing that stops it while it is on screen, so "not animating" is "not shown". That is also exactly what hidesWhenStopped asks for, which is why hidesWhenStopped is a declared no-op.`,`size="small"/"large" are 16 and 32 px — Gtk.IconSize’s own two steps — not React Native’s 20/36, which are Android dp and land between GTK’s steps. A numeric size is used verbatim.`]},TextInput:{status:`partial`,tier:`P1`,gtk:`Gtk.Entry / Gtk.TextView`,reason:`Single- versus multi-line is one prop in React Native and two different widgets in GTK.`,limits:[`multiline={true} is a Gtk.TextView, whose content lives in a Gtk.TextBuffer rather than in a property — MEASURED: 61 properties, no text. So value, defaultValue and onChangeText are refused by name on a multiline input, as are placeholder, maxLength and secureTextEntry, none of which Gtk.TextView installs. Single-line is complete.`,`onFocus/onBlur are refused: focus arrives through a Gtk.EventControllerFocus, a controller rather than a signal on the widget.`,`autoFocus is refused: Gtk.Widget.grab_focus() only works once the widget is mapped, which is a moment this layer does not own. Call it from a ref in an effect.`,`keyboardType maps onto Gtk.Entry:input-purpose; returnKeyType, autoCapitalize, autoCorrect and keyboardAppearance are declared no-ops, because they describe an on-screen keyboard.`]},Linking:{status:`partial`,tier:`P1`,gtk:`Gtk.UriLauncher`,reason:`openURL and canOpenURL only.`,limits:[`openURL asks can_launch FIRST and rejects when the answer is no. MEASURED: Gtk.UriLauncher.launch never calls back for a scheme with no handler (3 000 ms, no callback, exit 0), and a promise that never settles is worse than a rejection.`,`getInitialURL always resolves null. A desktop deep link arrives as Gio.Application::open AFTER startup, so there is no value to read before it — which is also what React Native returns for a normal launch.`,`addEventListener/addListener are refused: URL delivery is the application object’s own wiring (HANDLES_OPEN plus the open signal), above this layer.`,`openSettings and sendIntent are refused: a per-app settings page and an Android Intent have no desktop counterpart.`]},Switch:{status:`partial`,tier:`P1`,gtk:`Gtk.Switch`,reason:`Direct counterpart.`,limits:[`onValueChange binds notify::active, not state-set: state-set runs BEFORE the state changes and must return false to let the default handler proceed, and a handler that forgets makes the switch stick at exit 0.`,`trackColor and thumbColor are refused: Adwaita paints the switch from the theme accent and its track is a CSS subnode, not a property. Style it from the application stylesheet.`]},Platform:{status:`partial`,tier:`P1`,reason:`OS is "linux" | "macos" | "windows"; select() picks the default branch.`,limits:[`OS reports "linux", which is not a member of React Native’s own PlatformOSType. Reporting "macos" on a Linux desktop would be a lie select() cannot recover from, and "web" implies a DOM.`,`select() does NOT consult a native branch, for ADR 0032 § 9’s reason: a native branch is written for a React Native runtime, and handing it to a GTK build is a failure that surfaces in a window. A spec with neither this OS nor default is a named refusal rather than undefined.`,`Version throws by name: it is a mobile OS version and a desktop has no counterpart meaning the same thing.`,`constants throws by name: it is the native bridge’s constants object, and there is no bridge here.`]},Modal:{status:`planned`,tier:`P1`,gtk:`Adw.Dialog`,reason:`An Adw.Dialog cannot be an ordinary element. MEASURED on libadwaita 1.9.3: box.append(dialog) calls g_error() — SIGABRT and a core dump, not a catchable exception — but ONLY when the box is rooted in a window. A detached box accepts the append in silence, so a re-test on a bare box appears to disprove this and puts the primitive back. A dialog is PRESENTED against a parent, never parented by it, so this is a PORTAL and needs a host seam that does not exist yet.`},useColorScheme:{status:`supported`,tier:`P1`,gtk:`Adw.StyleManager.dark`,reason:`Follows the Adwaita colour scheme — the dark property, which is what the user is looking at, not color-scheme, which is what the application asked for.`},Share:{status:`partial`,tier:`P1`,gtk:`Gdk.Clipboard`,reason:`No desktop share sheet worth pretending about; copying the link is the honest mapping.`,limits:[`action is always sharedAction. dismissedAction means the user closed a share sheet without choosing, and nothing here asks the user anything — reporting a dismissal would be inventing an event. The constant is still exported, so a comparison against it resolves instead of failing to import.`,`activityType is always undefined: there is no activity to name.`,`Gtk.UriLauncher is NOT used here, although the planning entry named it. Launching a URI OPENS it in another application, which is a share sheet’s behavioural inverse — that call is Linking.openURL’s, and it is there.`]},AppRegistry:{status:`partial`,tier:`P1`,gtk:`Adw.Application + Adw.ApplicationWindow`,reason:`The entry point. Nothing renders without a window, so this is P1 despite being a shim.`,limits:[`runApplication takes gjsify options (applicationId is required) rather than React Native’s { rootTag, initialProps } — a phone host supplies the application identity, a desktop one IS the application.`,`unmountApplicationComponentAtRootTag throws: there is no root tag to address.`]},StyleSheet:{status:`partial`,tier:`P1`,gtk:`Gdk.Monitor.scale for hairlineWidth`,reason:`create/flatten/compose/hairlineWidth/absoluteFill. Style objects go through the same partition as classes (ADR 0032 § 4), which is why create can be identity.`,limits:[`create is IDENTITY, which is also what React Native’s own is now (it once registered styles and returned numeric ids). It cannot validate: half the vocabulary resolves against the parent (flex-1 is hexpand on a row and vexpand on a column), and create has no tree. The style object is validated where className is, at element resolution.`,`hairlineWidth is a GETTER, not a constant: Gdk.Display.get_default() is null before Gtk.init() (measured) and real code reads this at module scope, so before the display exists it answers 1. It takes the SMALLEST monitor scale, because GTK4 has no primary monitor (measured — get_primary_monitor is gone) and a hairline that is sub-pixel on a monitor can vanish, while one that is a device pixel too thick cannot.`,`setStyleAttributePreprocessor throws by name: it installs a process-wide transform on every style value, and configureStyle({ tokens }) is the scoped hook that already does that job.`]},FlatList:{status:`partial`,tier:`P2`,gtk:`Gtk.ListView + Gio.ListStore, owned by the component`,reason:`GTK virtualises for real. The list is NOT an ordinary element: a Gtk.ListView takes no children (measured — no append, add, insert, prepend, remove or set_child), so the component owns the view and drives the model from data, with React only inside the item factory.`,limits:[`data, renderItem, keyExtractor, ListEmptyComponent, ListHeaderComponent, ListFooterComponent, horizontal and onEndReached are answered. Everything else on React Native’s list surface is refused BY NAME in the primitive table, most of it because it configures React Native’s own virtualisation and Gtk.ListView does that job itself.`,`The header and footer are OUTSIDE the scroller, so they stay put while the rows scroll. Measured: putting them inside means wrapping the list in a Gtk.Box, which makes the scroller scroll a GtkViewport and allocates the list its whole content height (11 000 px for 500 rows) while it still realises only 205 of them — rows with no widget inside the allocated area.`,`A row’s React tree is rendered on a microtask, not inside the bind. GTK binds a row the moment the view is rooted in a window (measured), which under React is inside a commit or an effect — where a nested root cannot flush and the host refuses by name. A microtask drains before GTK’s next frame, so no row is ever painted empty.`,`A change to data replaces the model rows whose KEYS changed with one splice, which re-binds them; rows whose keys did not change are re-rendered in place instead, because GTK does not re-bind a row whose model object is unchanged (measured: items_changed over the same object does nothing).`,`onEndReached is bound to the scroller’s own Gtk.Adjustment (notify::value / upper / page-size) and fires once per arrival at the end. A list with nothing to scroll never fires, which is every list before it has been allocated.`,`renderItem’s separators.highlight/unhighlight/updateProps throw by name: a Gtk.ListView has no separator widget to restyle.`]},SectionList:{status:`partial`,tier:`P2`,gtk:`Gtk.ListView + one flattened Gio.ListStore`,reason:`The same component as FlatList, handed sections instead of data.`,limits:[`Every FlatList limit applies.`,`The sections are FLATTENED into one model with header ROWS, so a header scrolls with its section. GTK’s own sticky headers do exist — measured: Gtk.SectionModel is present, Gtk.FlattenListModel and every selection model implement it (Gio.ListStore and Gtk.StringList do not), Gtk.ListView.set_header_factory is there, and a flatten model over two stores answered get_section(0) = [0, 2] — and they are not used, because that route needs a second factory, a model of models, and Gtk.ListHeader’s start/end/n-items reconciled with React Native’s section object. stickySectionHeadersEnabled is therefore refused by name rather than silently false.`,`renderSectionFooter is not answered: a footer row would need the flattening to know where a section ends before the next one is read, which the header form does not.`]},VirtualizedList:{status:`partial`,tier:`P2`,gtk:`Gtk.ListView`,reason:`Its public surface is wide and mostly not worth honouring literally; the useful subset backs FlatList, and this name is that subset plus getItem/getItemCount.`,limits:[`Every FlatList limit applies.`,`getItem(data, index) and getItemCount(data) are answered, which is the one thing this name adds over FlatList. The virtualisation knobs — initialNumToRender, maxToRenderPerBatch, windowSize, updateCellsBatchingPeriod, removeClippedSubviews, getItemLayout — are refused by name: Gtk.ListView creates and recycles rows itself and installs no property that changes the batching (measured: 205 of 500 rows in a 400×300 window).`,`CellRendererComponent, debug, onLayout and the other internals of React Native’s own implementation are not answered at all — an unlisted prop is refused by name, which is the point.`]},VirtualizedSectionList:{status:`partial`,tier:`P2`,gtk:`Gtk.ListView`,reason:`The section-shaped sibling of VirtualizedList, which is SectionList here.`,limits:[`Every SectionList limit applies; it is the same component under React Native’s other name.`]},Image:{status:`partial`,tier:`P2`,gtk:`Gtk.Picture`,reason:`resizeMode becomes content-fit, and the default is inverted: React Native defaults to cover, a Gtk.Picture to contain (measured).`,limits:[`resizeMode answers cover, contain, stretch and center. repeat is refused by name: GtkContentFit is FILL, CONTAIN, COVER, SCALE_DOWN (measured) and has no tiling member — tiling is a Gdk.Paintable implementation, not a property of the widget that draws one.`,`source takes { uri } with a local path, a file: URI or a resource: URI. http:/https:/data: are refused by name (they need a fetch, a decoder and a cache — an async pipeline this layer does not own); a require() id is refused (it is an index into React Native’s asset registry, and ADR 0032 § 12 leaves the build chain to the consumer); an array is refused (it is the per-device-scale picker, and GTK scales one texture by the surface scale factor).`,`onLoad, onLoadStart, onLoadEnd, onError and onProgress are refused: Gtk.Picture emits NO signals at all (measured), and a file that does not exist leaves paintable null with no diagnostic — so a callback that never fires would hide exactly the case it exists to report.`,`blurRadius and tintColor are refused: a per-pixel effect is a Gsk render node, not a widget property.`]},ImageBackground:{status:`partial`,tier:`P2`,gtk:`Gtk.Picture in a Gtk.Overlay`,reason:`A picture with the children stacked over it. The picture is the overlay’s MAIN child, because a Gtk.Overlay paints every overlay child ABOVE it.`,limits:[`Every Image limit applies to source and resizeMode.`,`The element is sized by its PICTURE, not by its children — the opposite of React Native, where the image is absolutely positioned and contributes nothing. Measured: a Gtk.Overlay measures only its main child (a 9 px main child beside a 266 px overlay child gave the overlay 9 px), and gtk_overlay_set_measure_overlay() is a per-child METHOD rather than a property, so the host’s data-driven placement has no way to name it. Give the element a size, or let its parent stretch it (flex-1).`,`imageStyle styles the picture and style styles the container, as in React Native. imageRef is refused: this element’s ref is the Gtk.Overlay and overlay.get_child() is the picture.`]},TouchableOpacity:{status:`partial`,tier:`P2`,gtk:`Gtk.Button (flat)`,reason:`The same machinery as Pressable, written over it: one shared record of routes in the primitive table, one line of component.`,limits:[`activeOpacity is refused by name — write active:opacity-70. The pressed appearance is a GTK CSS :active declaration (ADR 0032 § 7), and honouring a raw number here would put a value into the styling path that did not come from the project’s token scale (ADR 0032 § 3).`,`Every Pressable limit applies: onPressIn/onPressOut, onLongPress, hitSlop and the press-delay props are refused by name.`]},TouchableHighlight:{status:`partial`,tier:`P2`,gtk:`Gtk.Button (flat)`,reason:`As TouchableOpacity. The pressed style is Adwaita’s own unless a variant says otherwise.`,limits:[`underlayColor is refused by name — write active:bg-<token>, for the same reason activeOpacity is: a raw colour would bypass the token scale that every other colour in this vocabulary comes from.`,`onShowUnderlay/onHideUnderlay are refused: there is no underlay widget to show.`,`Every TouchableOpacity limit applies.`]},TouchableWithoutFeedback:{status:`partial`,tier:`P2`,gtk:`Gtk.Box + Gtk.GestureClick`,reason:`No chrome, so no button: a vertical Gtk.Box like a View, with a Gtk.GestureClick added to it. Measured: Gtk.Button emits activate and clicked, a Gtk.Box emits neither, and Gtk.GestureClick emits pressed/released/stopped/unpaired-release.`,limits:[`It is a real box in the tree, not a transparent clone of its child — React Native clones the single child and attaches the handlers to it, and GTK has no way for a widget to be its own child. So it lays out like a View and takes one row of the parent’s box.`,`disabled becomes can-target: false rather than sensitive: false, because sensitive greys out every descendant of a wrapper that is supposed to have no appearance of its own.`,`onPress only. The rest of the Touchable surface is refused by name, as on TouchableOpacity.`]},Button:{status:`partial`,tier:`P2`,gtk:`Gtk.Button`,reason:`The one component whose React Native styling story is "you cannot", which GTK agrees with. title, onPress and disabled.`,limits:[`style and className are REFUSED by name, which is faithful: React Native’s Button takes neither. An Adwaita button is painted by the theme and by its own classes (suggested-action, destructive-action), which an application stylesheet sets. Use Pressable when you need to style it.`,`color is refused: it is the background on Android and the text colour on iOS — one prop, two meanings — and GTK’s answer to both is a class rather than a colour.`,`It takes no children: title writes Gtk.Button:label, and a text child would be a second authority for the same slot. React Native’s Button takes no children either.`]},Dimensions:{status:`partial`,tier:`P2`,gtk:`Gtk.Window allocation, Gdk.Monitor geometry`,reason:`get("window") is the window, not the screen — a desktop app is not full-screen, so the screen’s number would be wrong in the ordinary case. get("screen") is the monitor, because that is what it asks for.`,limits:[`get("window") throws by name when there is no window yet, which includes every read at module scope. There is no honest number before the application builds its window, and a zero divides. Read it from a component or an effect, or use useWindowDimensions.`,`The reported size is the window’s ALLOCATION, falling back to default-width/default-height before it has been allocated. It is deliberately NOT the Gdk.Surface size: measured, a 640×480 window has a 668×509 surface, which carries the client-side-decoration shadow.`,`The window is found through Gtk.Window.get_toplevels() (the mapped one first), so it answers for an application that built its own window as well as for one AppRegistry created.`,`fontScale comes from Gtk.Settings:gtk-xft-dpi / 1024 / 96 (measured: 98304, i.e. 1). set() throws by name: it is how React Native’s native side PUBLISHES metrics, and there is no bridge here.`]},useWindowDimensions:{status:`partial`,tier:`P2`,gtk:`Gdk.Surface notify::width/height, Gtk.Window allocation`,reason:`The hook form of Dimensions, through useSyncExternalStore so a resize between render and commit cannot tear.`,limits:[`The NOTIFIER and the VALUE are different objects, and it is measured rather than chosen: Gtk.Widget installs no width or height property and emits no size-allocate signal (the wall <View onLayout> is refused against), while Gdk.Surface installs read-only width and height and notifies on them. So the surface says when and the window says what.`,`PRECONDITION NOT MEASURED: whether the window’s allocation is already updated inside that handler. A compositor-driven resize cannot be triggered from a probe — set_default_size on a mapped window is a no-op (measured) — so this is recorded as unknown rather than guessed.`,`Every Dimensions limit applies to the value itself.`]},Alert:{status:`partial`,tier:`P2`,gtk:`Adw.AlertDialog`,reason:`Direct counterpart, and buildable where Modal is not: Alert is a FUNCTION CALL, so no element is ever inserted into a widget. Measured on libadwaita 1.9.3 — present(null) from a plain function, with no parent and no window, returned with no diagnostic.`,limits:[`destructive maps to Adw.ResponseAppearance.DESTRUCTIVE and cancel becomes the dialog’s CLOSE RESPONSE, which is stronger than an appearance: it is what Escape and the compositor’s close both produce. The first non-cancel button becomes the default response, which is Adwaita’s convention and has no React Native counterpart.`,`Response IDs are positional (response-0, …) rather than derived from the label, so two buttons with the same text do not collide into one response.`,`prompt throws by name: it is iOS-only, and its contract (four overloads, a login/password variant, a callback whose arity depends on the type) is what makes it a refusal rather than a port. Adw.AlertDialog:extra-child is there if you want to build it.`]},Appearance:{status:`supported`,tier:`P2`,gtk:`Adw.StyleManager`,reason:`The imperative sibling of useColorScheme, over the SAME reader — getColorScheme reads Adw.StyleManager:dark (what the user is looking at) and setColorScheme writes :color-scheme (what the application asked for), which is exactly the split React Native’s getter and setter have.`},SafeAreaView:{status:`partial`,tier:`P2`,gtk:`Gtk.Box`,reason:`The INSET has no desktop meaning; the layout does. It is a View in every other respect, and it has to be a real export to be imported.`,limits:[`The safe-area insets are always zero, because a desktop window has none. What is a no-op is the inset — not the box, not the column, not the children: a component that rendered nothing would be a screen that silently disappeared.`,`It is a View, so every View limit applies (the absolute-child overlay switch, onLayout refused, pointerEvents auto/none only).`]},StatusBar:{status:`partial`,tier:`P2`,reason:`A desktop window has no status bar to configure, and <StatusBar/> is in the first ten lines of most React Native screens — so it renders NOTHING and says so, rather than failing to import.`,limits:[`The component renders null. Its declarative props (barStyle, hidden, backgroundColor, translucent, animated) are accepted and do nothing, which is what a declared no-op is.`,`Every imperative static REFUSES by name: setBarStyle, setHidden, setBackgroundColor, setTranslucent, setNetworkActivityIndicatorVisible, pushStackEntry, popStackEntry, replaceStackEntry. A setter that appears to work is indistinguishable from one that does.`,`currentHeight throws by name rather than answering 0: code reads it straight into a layout (paddingTop: StatusBar.currentHeight), and a number here would inset every ported screen by a bar that is not there.`]},KeyboardAvoidingView:{status:`partial`,tier:`P2`,gtk:`Gtk.Box`,reason:`No on-screen keyboard eats a desktop window layout, so the AVOIDING is the no-op. React Native’s KeyboardAvoidingView is a View that changes its own height; what is left here is the View.`,limits:[`behavior, keyboardVerticalOffset and enabled are declared no-ops: they describe the avoidance, which is already off.`,`contentContainerStyle is refused by name: it styles the inner view React Native adds to do the avoiding, and there is no second node here. Put it on style.`,`It is a View, so every View limit applies.`]},Keyboard:{status:`partial`,tier:`P2`,reason:`Its events are on-screen-keyboard events, which do not occur — so the questions with a correct answer get it and the ones whose answer would have to be invented refuse.`,limits:[`addListener REFUSES by name, for every event. A subscription that resolves and then never fires is the silent drop this layer exists to remove: a keyboardDidShow handler that never runs looks like a bug in your own code, for ever.`,`dismiss() and removeAllListeners() are no-ops — nothing was shown, so nothing has to be hidden, and nothing is registered to remove.`,`isVisible() answers false and metrics() answers undefined, which are React Native’s own answers for a keyboard that is not up.`,`scheduleLayoutAnimation throws by name: it is LayoutAnimation’s subsystem (tier P3), not a keyboard behaviour.`]},RefreshControl:{status:`refused`,reason:`GTK has no pull-to-refresh idiom and should not grow one. Give the desktop build a refresh action instead.`},AppState:{status:`planned`,tier:`P3`,gtk:`Gtk.Application / Gdk.Surface state`,reason:`active/background from window focus and visibility.`},PixelRatio:{status:`planned`,tier:`P3`,gtk:`Gdk.Surface.scale-factor`,reason:`The scale factor of the surface the widget is on.`},PlatformColor:{status:`planned`,tier:`P3`,gtk:`Adwaita named colours`,reason:`Maps unusually well — GTK’s palette is exactly this idea.`},AccessibilityInfo:{status:`planned`,tier:`P3`,gtk:`Gtk.Accessible / AT-SPI`,reason:`The highest-value P3 entry: GTK’s accessibility model is strong and the props map onto it well.`},Animated:{status:`planned`,tier:`P3`,gtk:`Adw.TimedAnimation / Adw.SpringAnimation`,reason:`Genuinely mappable, but it is a subsystem rather than a component. Doing it badly is worse than not doing it.`},Easing:{status:`planned`,tier:`P3`,reason:`Pure maths; it lands with Animated or not at all.`},LayoutAnimation:{status:`planned`,tier:`P3`,reason:`Needs an animated layout pass, which is the same subsystem as Animated.`},InteractionManager:{status:`planned`,tier:`P3`,reason:`Deferring work until interactions settle; a main-loop idle source is the counterpart.`},useAnimatedValue:{status:`planned`,tier:`P3`,reason:`Part of the Animated subsystem.`},useAnimatedValueXY:{status:`planned`,tier:`P3`,reason:`Part of the Animated subsystem.`},useAnimatedColor:{status:`planned`,tier:`P3`,reason:`Part of the Animated subsystem.`},PanResponder:{status:`planned`,tier:`P3`,gtk:`Gtk.Gesture* controllers`,reason:`The controllers exist; the arbitration model is not React Native’s, so this is its own project.`},usePressability:{status:`planned`,tier:`P3`,reason:`The hook behind the Touchable family; it lands with the gesture work.`},DrawerLayoutAndroid:{status:`planned`,tier:`P3`,gtk:`Adw.OverlaySplitView`,reason:`The pattern survives on a desktop even though the component is Android-only.`},I18nManager:{status:`planned`,tier:`P3`,gtk:`Gtk.Widget.direction`,reason:`RTL is a widget-direction question on GTK.`},LogBox:{status:`no-desktop-meaning`,tier:`P3`,reason:`A development overlay for a phone; the console is the desktop equivalent.`},Systrace:{status:`no-desktop-meaning`,reason:`Android systrace has no desktop counterpart.`},Vibration:{status:`no-desktop-meaning`,reason:`A desktop machine does not vibrate.`},ToastAndroid:{status:`planned`,tier:`P3`,gtk:`Adw.Toast`,reason:`Android-only by name, and Adwaita has the exact widget.`},InputAccessoryView:{status:`no-desktop-meaning`,reason:`An iOS keyboard accessory bar; there is no keyboard to accessorise.`},TouchableNativeFeedback:{status:`planned`,tier:`P3`,gtk:`Gtk.Button`,reason:`Android-only ripple; shimmed to its portable sibling.`},ActionSheetIOS:{status:`planned`,tier:`P3`,gtk:`Adw.AlertDialog with responses`,reason:`iOS-only by name; the pattern is a dialog with choices.`},PushNotificationIOS:{status:`refused`,reason:`Platform notification plumbing. A desktop app uses Gio.Notification directly.`},PermissionsAndroid:{status:`refused`,reason:`Android runtime permissions have no desktop counterpart; portals are asked for at use time.`},Settings:{status:`refused`,reason:`An iOS user-defaults bridge. GSettings is the desktop answer and is not this API.`},Clipboard:{status:`planned`,tier:`P3`,gtk:`Gdk.Clipboard`,reason:`Deprecated upstream in favour of a community package, but trivial here.`},BackHandler:{status:`planned`,tier:`P3`,reason:'An Android hardware back button. Routing has landed and this did NOT arrive with it, which the earlier reason assumed it would: BackHandler INTERCEPTS a back press and consumes it, and MEASURED on libadwaita 1.9.3, Adw.NavigationView emits `popped` AFTER the fact and has no vetoable "about to pop" signal at all — its only prevention is Adw.NavigationPage:can-pop, a property rather than an event. The honest counterpart is usePreventRemove, which the routing layer does honour through its popped bridge; this name needs a key controller of its own on the window.'},DynamicColorIOS:{status:`planned`,tier:`P3`,reason:`A light/dark colour pair; the Adwaita scheme already provides the switch.`},processColor:{status:`planned`,tier:`P3`,reason:`Colour string to a platform value; a Gdk.RGBA on this side.`},UTFSequence:{status:`planned`,tier:`P3`,reason:`A table of unicode constants. Pure data, no platform in it.`},experimental_LayoutConformance:{status:`refused`,reason:`An experimental switch between two React Native layout implementations. Neither is used here.`},unstable_VirtualView:{status:`refused`,reason:`Unstable React Native internal.`},VirtualViewMode:{status:`refused`,reason:`Unstable React Native internal.`},unstable_NativeText:{status:`refused`,reason:`Unstable React Native internal.`},unstable_NativeView:{status:`refused`,reason:`Unstable React Native internal.`},unstable_TextAncestorContext:{status:`refused`,reason:`Unstable React Native internal.`},ReactNativeVersion:{status:`planned`,tier:`P3`,reason:`The version this layer targets, reported honestly rather than spoofed.`},DeviceInfo:{status:`refused`,reason:`A native module surface describing a phone.`},DevMenu:{status:`no-desktop-meaning`,reason:`The shake-to-open developer menu.`},DevSettings:{status:`no-desktop-meaning`,reason:`Development-client settings for a phone runtime.`},NativeModules:{status:`refused`,reason:`The native-module bridge. There is no bridge here; this layer renders in-process onto GTK.`},TurboModuleRegistry:{status:`refused`,reason:`The TurboModule lookup. Same reason as NativeModules.`},NativeComponentRegistry:{status:`refused`,reason:`Fabric component registration. The host owns widget creation.`},requireNativeComponent:{status:`refused`,reason:`Looks up a native view manager. Write a GTK widget descriptor instead.`},codegenNativeComponent:{status:`refused`,reason:`React Native codegen for Fabric components.`},codegenNativeCommands:{status:`refused`,reason:`React Native codegen for Fabric commands.`},UIManager:{status:`refused`,reason:`The legacy view-manager surface. The GTK host is the view manager here.`},findNodeHandle:{status:`refused`,reason:`Returns a native view tag. A ref here is the Gtk.Widget itself, which is more useful.`},registerCallableModule:{status:`refused`,reason:`Registers a module callable from the native side. There is no native side.`},Networking:{status:`refused`,reason:`React Native’s XHR internals. Use fetch, which gjsify provides.`},NativeDialogManagerAndroid:{status:`refused`,reason:`An Android dialog native module. Alert is the portable spelling.`},ProgressBarAndroid:{status:`planned`,tier:`P3`,gtk:`Gtk.ProgressBar`,reason:`Android-only by name; GTK has the widget.`},Touchable:{status:`refused`,reason:`The legacy mixin behind the Touchable family, not a public component.`},EventEmitter:{status:`supported`,reason:`Pure JavaScript; nothing in it touches a platform.`},NativeEventEmitter:{status:`planned`,tier:`P3`,reason:`It would construct and subscribe, but nothing native would ever emit into it — shipping that needs a decision, not a class.`},DeviceEventEmitter:{status:`planned`,tier:`P3`,reason:`The global emitter. Lands with NativeEventEmitter, and for the same reason.`},NativeAppEventEmitter:{status:`refused`,reason:`The legacy iOS app-event emitter.`},RootTagContext:{status:`refused`,reason:`A React Native surface identifier. This layer has one root per Adw window.`},unstable_batchedUpdates:{status:`supported`,reason:`React 19 batches automatically; this is the identity call it already is upstream.`}},n={router:{status:`partial`,tier:`P1`,gtk:`Adw.NavigationView (push/pop) via React Navigation’s StackActions`,reason:`push, back, replace and navigate — the four methods the measured application calls, 19 of the 27 calls being push.`,limits:[`push falls back to NAVIGATE when the navigator that owns the target is not mounted yet. StackActions.push is dispatched at ONE navigator and an href can name a screen several navigators down; for an unmounted navigator, arriving there IS the new entry, so the fallback is correct rather than approximate — but a push into a mounted navigator that is not a stack cannot add an entry, because PUSH is the stack router’s action and no other router answers it.`,`back() THROWS when there is nothing to go back to, where expo-router and React Navigation both return quietly. A quiet return is a back button that does nothing with no message, which is the silent drop this layer refuses everywhere else.`,`setParams, dismiss, dismissAll, dismissTo and canGoBack are not implemented. They are not in the measured surface, and each is a named refusal rather than an undefined property read.`,`An href is a path. expo-router also accepts an object form ({ pathname, params }); this layer takes the string, which is what all 27 measured calls pass.`]},useLocalSearchParams:{status:`partial`,tier:`P1`,reason:`The current route’s params — the [param] values and the query string — read through React Navigation’s own useRoute().`,limits:[`Values are strings, because a URL segment is one. A number or a boolean that arrived through a dispatched param is stringified; anything structural (an object, an array) is left out, and a [param] cannot produce one. expo-router additionally returns string[] for a repeated query key, which this layer does not.`,`React Navigation’s seven nesting keys — screen, params, initial, state, path, pop, merge — are filtered out, so a route cannot use those seven as param names.`]},usePathname:{status:`partial`,tier:`P1`,reason:`The current URL without its query string, from React Navigation’s getPathFromState over the published root state.`,limits:[`On the +not-found route it reports "/+not-found" rather than the URL that missed. getPathFromState builds a path from the STATE, and the state records which screen matched, not the text that reached it.`,`It answers "/" before the navigation container is ready. That is not a placeholder — nothing has been navigated to yet — but a component that renders on the first commit and compares against a literal will see it.`]},Stack:{status:`partial`,tier:`P1`,gtk:`Adw.NavigationView + Adw.NavigationPage`,reason:`The stack navigator: React declares which pages exist, the widget owns their order, and the route key is the tag that joins the two.`,limits:[`A screen answers title, headerShown and animation. Every other expo-router / React Navigation stack option is refused BY NAME at the point of declaration, because an option that is accepted and ignored is invisible until someone looks at the window.`,`The header is an Adw.HeaderBar inside an Adw.ToolbarView, which grows its own back button and reads the page’s own title. A custom header component is not supported; headerShown={false} drops the bar, and with it the back affordance.`,`animation is "default" or "none" — Adw.NavigationView has one transition and a switch for it (animate-transitions), not a set of named ones.`,`Screen preloading is not implemented. React Navigation’s preloadedRoutes would need pages added to the widget’s pool without entering the stack, which is expressible and untested here.`]},Tabs:{status:`partial`,tier:`P1`,gtk:`Adw.ViewStack + Adw.ViewSwitcher`,reason:`The tab navigator. The switcher is driven by the stack’s own page model, so a route file adds a button with no tab-bar bookkeeping.`,limits:[`A tab answers title only. tabBarIcon is refused: in React Native it is a COMPONENT and Adwaita paints a switcher button from Adw.ViewStackPage:icon-name, an icon NAME on a page object the add returns — reachable through a ref, not through this declaration.`,`Every tab is mounted. React Native’s tab navigator is lazy because a phone cannot afford five screens; an Adw.ViewStack page that is not the visible child is not realised, and laziness would buy a flash on first switch.`,`The switcher sits in the header bar with policy WIDE (MEASURED: the default is NARROW, the phone-shaped one). A narrow-window breakpoint is the application’s to declare — Adw.ViewSwitcherBar is not wired here.`,`tabBarBadge, tabBarPosition and the rest of the tab-bar vocabulary are refused by name for the same reason as tabBarIcon: they describe a bar this layer does not draw.`]},Link:{status:`planned`,tier:`P2`,gtk:`Gtk.Button (flat) or Gtk.LinkButton`,reason:"An href as an element rather than a call. Cheap once `router` exists, and the honest widget question — button or link — is worth measuring first."},Redirect:{status:`planned`,tier:`P2`,reason:`A declarative navigate-on-render. It needs a rule for what happens when it redirects during the first commit, which is the commit that must not be empty.`},Slot:{status:`planned`,tier:`P2`,gtk:`Adw.Bin`,reason:`A layout that renders its child route with no navigator around it. It is the one layout shape that has no widget of its own.`},useRouter:{status:`planned`,tier:`P2`,reason:"The hook form of `router`. Identical behaviour, and it exists so a test can substitute the object — which is worth having once there is something to substitute."},useSegments:{status:`planned`,tier:`P2`,reason:`The current route split into segments. Derivable from the published root state, and unused in the measured application.`},useGlobalSearchParams:{status:`planned`,tier:`P2`,reason:`The params of the focused route anywhere in the tree, rather than of the calling screen. It re-renders on every navigation by design, which is why expo-router documents preferring the local form.`},useNavigation:{status:`planned`,tier:`P2`,reason:`React Navigation’s own hook, re-exported by expo-router. It works already through @react-navigation/core; exporting it from here is a decision about what this surface promises, not a build.`},useFocusEffect:{status:`planned`,tier:`P2`,reason:`As useNavigation: it is core’s, and it works. The open question is the same one.`},useRootNavigationState:{status:`planned`,tier:`P3`,reason:"The root state as a hook. The store `usePathname` reads is already there; this is a second selector over it."},Drawer:{status:`planned`,tier:`P3`,gtk:`Adw.OverlaySplitView`,reason:`A sidebar navigator. The pattern survives on a desktop better than it does on a phone, and Adwaita has the exact widget — it is a third navigator, not a variation on these two.`},withLayoutContext:{status:`planned`,tier:`P3`,reason:"The escape hatch that lets a third-party navigator take its screens from the file tree. It is exactly `useRouteNode` plus screen synthesis, made public — worth doing once a third navigator exists to prove the shape."},Navigator:{status:`planned`,tier:`P3`,reason:`expo-router’s low-level navigator primitive. It belongs with withLayoutContext and for the same reason.`},ErrorBoundary:{status:`planned`,tier:`P3`,gtk:`Adw.StatusPage`,reason:`A per-route error screen. React 19 routes an uncaught error to the root’s handler and @gjsify/gtk-host/react rethrows it from render() — deliberately, so a refusal is not swallowed — and a boundary here has to be reconciled with that rather than bolted beside it.`},ExpoRoot:{status:`refused`,reason:"It takes a Metro `require.context`, which does not exist in this build chain. `RouterRoot` takes the manifest a bundler plugin emits instead — the same job, with the one input that is available."},useUnstableGlobalHref:{status:`refused`,reason:`Unstable by its own name, and it answers the question usePathname already answers for the only surface this layer has.`},useNavigationContainerRef:{status:`refused`,reason:"The container ref is this layer’s own (one process routes one tree), and handing it out would let a consumer dispatch around the refusals `router` exists to give."},SplashScreen:{status:`refused`,reason:`A native splash screen belongs to a phone launcher. A GTK application maps its window when it is ready, which is the desktop equivalent and is Gio.Application’s job, not the router’s.`}},r=Object.keys(t),i=Object.keys(n),a=new Set([`supported`,`partial`]),o=[[`@gjsify/react-native`,t],[`@gjsify/react-native/router`,n]],lookup=e=>{for(let[t,n]of o){let r=n[e];if(r!==void 0)return{module:t,entry:r}}},s=new Set(e),isOwnExport=e=>s.has(e),isImportable=e=>{let t=lookup(e);return t===void 0?isOwnExport(e):a.has(t.entry.status)};function explainUnsupported(e){let t=lookup(e);if(t===void 0)return isOwnExport(e)?`@gjsify/react-native: "${e}" is this layer's own export rather than a React Native name, and it is available.`:`@gjsify/react-native: "${e}" is not a React Native export this layer knows about. If the installed react-native really exports it, the support table is out of date — run scripts/check-rn-surface.mjs, which compares the two.`;let{module:n,entry:r}=t,i=r.tier?` (tier ${r.tier})`:``,a=r.gtk?` The GTK counterpart is ${r.gtk}.`:``;switch(r.status){case`supported`:case`partial`:return`${n}: "${e}" is available.`;case`planned`:return`${n}: "${e}" is not implemented yet${i}. ${r.reason}${a}`;case`refused`:return`${n}: "${e}" will not be implemented. ${r.reason}`;case`no-desktop-meaning`:return`${n}: "${e}" has no meaning on a desktop window${i}. ${r.reason}`;case`not-reachable`:return`${n}: "${e}" cannot be implemented in this build chain. ${r.reason}`}}export{e as OWN_EXPORT_NAMES,i as ROUTER_NAMES,n as ROUTER_SUPPORT_TABLE,r as SUPPORTED_NAMES,t as SUPPORT_TABLE,explainUnsupported,isImportable,isOwnExport};
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{OWN_EXPORT_NAMES as e}from"./generated/own-exports.js";const t={View:{status:`partial`,tier:`P1`,gtk:`Gtk.Box, or Gtk.Overlay when a child is absolutely positioned`,reason:`The container primitive. Which widget it becomes depends on its children, not on the element.`,limits:[`An absolutely positioned child is placed by alignment plus a margin, because Gtk.Overlay positions an overlay child by its halign/valign and has no coordinate pair. An offset on only ONE edge of an axis therefore leaves the other axis at GTK’s default (fill), where React Native would keep the child at its static position — a position GTK has no way to express for an overlay child.`,`onLayout is refused: GTK reports allocation through Gtk.Widget.vfunc_size_allocate, a subclass override rather than a signal.`,`pointerEvents answers auto and none only. box-none and box-only split hit-testing between a widget and its subtree, and Gtk.Widget:can-target is one boolean for both.`]},Text:{status:`partial`,tier:`P1`,gtk:`Gtk.Label`,reason:`THREE Gtk.Label defaults disagree with React Native’s and are set explicitly — wrap, xalign and yalign. The whole set of default divergences, including the ones that agree, is enumerated in primitives/defaults.ts.`,limits:[`Gtk.Label CENTRES by default and React Native’s text alignment is unset, which means the script’s natural edge — left in LTR. MEASURED as a position rather than a property: a label allocated 400×100 reports get_layout_offsets() = (193, 41) with GTK’s defaults and (0, 0) with xalign/yalign 0. Found by porting a 25-route application, where every string on every screen rendered centred and nothing reported it; text-center still works, because widgetProps is the base the style partition overrides.`,`A nested <Text> is refused by the host naming the tag: Gtk.Label takes no children (measured), so React Native’s inline-styling idiom has no counterpart. Use Pango markup through a ref, or separate labels.`,`ellipsizeMode="clip" is refused: PangoEllipsizeMode is NONE, START, MIDDLE, END (measured) and has no clip member, so honouring it would add an ellipsis the author asked not to have.`,`onPress is refused: a Gtk.Label emits no clicked signal (measured). Wrap it in a <Pressable>.`]},Pressable:{status:`partial`,tier:`P1`,gtk:`Gtk.Button (flat)`,reason:`Press state is a GTK CSS :active pseudo-class; children-as-a-function is implemented over the state flag, and costs nothing when it is unused.`,limits:[`children-as-a-function-of-{ pressed } reads the widget’s Gtk.StateFlags.ACTIVE through Gtk.Widget::state-flags-changed, because Gtk.Button installs no active property (measured). An element that does NOT use the function form subscribes to nothing — press styling written as active:* is CSS and never reaches the reconciler (ADR 0032 § 7), and pressWatchCount() is what holds the two apart.`,`onPressIn/onPressOut are refused: they report the press as an EVENT, and the state flag reports it as a state. Use the function form, or active:*.`,`onLongPress is refused: a long press is a Gtk.GestureLongPress controller added to the widget, not a property or a signal on it.`,`hitSlop is refused: GTK hit-tests the allocation and cannot grow it past the widget. Pad the button instead, which enlarges the real target.`]},ScrollView:{status:`partial`,tier:`P1`,gtk:`Gtk.ScrolledWindow + an implicit content box`,reason:`contentContainerStyle styles the inner box, which is a second styleable node.`,limits:[`onScroll and scrollEventThrottle are refused: GTK reports scroll position as notify::value on the Gtk.Adjustment behind hadjustment/vadjustment, an object rather than a signal on the scrolled window. Reach the adjustment through a ref.`,`scrollEnabled is refused: a Gtk.ScrolledWindow has no switch that stops scrolling, and setting both policies to never clamps the child as well as hiding the bars.`,`refreshControl is refused, matching RefreshControl’s own entry: GTK has no pull-to-refresh idiom.`,`Layout utilities that need a box (items-*, gap-*, justify-*) are refused on style and belong on contentContainerStyle — which is React Native’s own rule, not a GTK one.`]},ActivityIndicator:{status:`partial`,tier:`P1`,gtk:`Adw.Spinner`,reason:`Direct counterpart.`,limits:[`animating={false} hides the widget. MEASURED: Adw.Spinner installs 36 properties and every one is Gtk.Widget’s — there is nothing that stops it while it is on screen, so "not animating" is "not shown". That is also exactly what hidesWhenStopped asks for, which is why hidesWhenStopped is a declared no-op.`,`size="small"/"large" are 16 and 32 px — Gtk.IconSize’s own two steps — not React Native’s 20/36, which are Android dp and land between GTK’s steps. A numeric size is used verbatim.`]},TextInput:{status:`partial`,tier:`P1`,gtk:`Gtk.Entry / Gtk.TextView`,reason:`Single- versus multi-line is one prop in React Native and two different widgets in GTK.`,limits:[`multiline={true} is a Gtk.TextView, whose content lives in a Gtk.TextBuffer rather than in a property — MEASURED: 61 properties, no text. So value, defaultValue and onChangeText are refused by name on a multiline input, as are placeholder, maxLength and secureTextEntry, none of which Gtk.TextView installs. Single-line is complete.`,`onFocus/onBlur are refused: focus arrives through a Gtk.EventControllerFocus, a controller rather than a signal on the widget.`,`autoFocus is refused: Gtk.Widget.grab_focus() only works once the widget is mapped, which is a moment this layer does not own. Call it from a ref in an effect.`,`keyboardType maps onto Gtk.Entry:input-purpose; returnKeyType, autoCapitalize, autoCorrect and keyboardAppearance are declared no-ops, because they describe an on-screen keyboard.`]},Linking:{status:`partial`,tier:`P1`,gtk:`Gtk.UriLauncher`,reason:`openURL and canOpenURL only.`,limits:[`openURL asks can_launch FIRST and rejects when the answer is no. MEASURED: Gtk.UriLauncher.launch never calls back for a scheme with no handler (3 000 ms, no callback, exit 0), and a promise that never settles is worse than a rejection.`,`getInitialURL always resolves null. A desktop deep link arrives as Gio.Application::open AFTER startup, so there is no value to read before it — which is also what React Native returns for a normal launch.`,`addEventListener/addListener are refused: URL delivery is the application object’s own wiring (HANDLES_OPEN plus the open signal), above this layer.`,`openSettings and sendIntent are refused: a per-app settings page and an Android Intent have no desktop counterpart.`]},Switch:{status:`partial`,tier:`P1`,gtk:`Gtk.Switch`,reason:`Direct counterpart.`,limits:[`onValueChange binds notify::active, not state-set: state-set runs BEFORE the state changes and must return false to let the default handler proceed, and a handler that forgets makes the switch stick at exit 0.`,`trackColor and thumbColor are refused: Adwaita paints the switch from the theme accent and its track is a CSS subnode, not a property. Style it from the application stylesheet.`]},Platform:{status:`partial`,tier:`P1`,reason:`OS is "linux" | "macos" | "windows"; select() picks the default branch.`,limits:[`OS reports "linux", which is not a member of React Native’s own PlatformOSType. Reporting "macos" on a Linux desktop would be a lie select() cannot recover from, and "web" implies a DOM.`,`select() does NOT consult a native branch, for ADR 0032 § 9’s reason: a native branch is written for a React Native runtime, and handing it to a GTK build is a failure that surfaces in a window. A spec with neither this OS nor default is a named refusal rather than undefined.`,`Version throws by name: it is a mobile OS version and a desktop has no counterpart meaning the same thing.`,`constants throws by name: it is the native bridge’s constants object, and there is no bridge here.`]},Modal:{status:`planned`,tier:`P1`,gtk:`Adw.Dialog`,reason:`An Adw.Dialog cannot be an ordinary element. MEASURED on libadwaita 1.9.3: box.append(dialog) calls g_error() — SIGABRT and a core dump, not a catchable exception — but ONLY when the box is rooted in a window. A detached box accepts the append in silence, so a re-test on a bare box appears to disprove this and puts the primitive back. A dialog is PRESENTED against a parent, never parented by it, so this is a PORTAL and needs a host seam that does not exist yet.`},useColorScheme:{status:`supported`,tier:`P1`,gtk:`Adw.StyleManager.dark`,reason:`Follows the Adwaita colour scheme — the dark property, which is what the user is looking at, not color-scheme, which is what the application asked for.`},Share:{status:`partial`,tier:`P1`,gtk:`Gdk.Clipboard`,reason:`No desktop share sheet worth pretending about; copying the link is the honest mapping.`,limits:[`action is always sharedAction. dismissedAction means the user closed a share sheet without choosing, and nothing here asks the user anything — reporting a dismissal would be inventing an event. The constant is still exported, so a comparison against it resolves instead of failing to import.`,`activityType is always undefined: there is no activity to name.`,`Gtk.UriLauncher is NOT used here, although the planning entry named it. Launching a URI OPENS it in another application, which is a share sheet’s behavioural inverse — that call is Linking.openURL’s, and it is there.`]},AppRegistry:{status:`partial`,tier:`P1`,gtk:`Adw.Application + Adw.ApplicationWindow`,reason:`The entry point. Nothing renders without a window, so this is P1 despite being a shim.`,limits:[`runApplication takes gjsify options (applicationId is required) rather than React Native’s { rootTag, initialProps } — a phone host supplies the application identity, a desktop one IS the application.`,`unmountApplicationComponentAtRootTag throws: there is no root tag to address.`]},StyleSheet:{status:`partial`,tier:`P1`,gtk:`Gdk.Monitor.scale for hairlineWidth`,reason:`create/flatten/compose/hairlineWidth/absoluteFill. Style objects go through the same partition as classes (ADR 0032 § 4), which is why create can be identity.`,limits:[`create is IDENTITY, which is also what React Native’s own is now (it once registered styles and returned numeric ids). It cannot validate: half the vocabulary resolves against the parent (flex-1 is hexpand on a row and vexpand on a column), and create has no tree. The style object is validated where className is, at element resolution.`,`hairlineWidth is a GETTER, not a constant: Gdk.Display.get_default() is null before Gtk.init() (measured) and real code reads this at module scope, so before the display exists it answers 1. It takes the SMALLEST monitor scale, because GTK4 has no primary monitor (measured — get_primary_monitor is gone) and a hairline that is sub-pixel on a monitor can vanish, while one that is a device pixel too thick cannot.`,`setStyleAttributePreprocessor throws by name: it installs a process-wide transform on every style value, and configureStyle({ tokens }) is the scoped hook that already does that job.`]},FlatList:{status:`partial`,tier:`P2`,gtk:`Gtk.ListView + Gio.ListStore, owned by the component`,reason:`GTK virtualises for real. The list is NOT an ordinary element: a Gtk.ListView takes no children (measured — no append, add, insert, prepend, remove or set_child), so the component owns the view and drives the model from data, with React only inside the item factory.`,limits:[`data, renderItem, keyExtractor, ListEmptyComponent, ListHeaderComponent, ListFooterComponent, horizontal and onEndReached are answered. Everything else on React Native’s list surface is refused BY NAME in the primitive table, most of it because it configures React Native’s own virtualisation and Gtk.ListView does that job itself.`,`The header and footer are OUTSIDE the scroller, so they stay put while the rows scroll. Measured: putting them inside means wrapping the list in a Gtk.Box, which makes the scroller scroll a GtkViewport and allocates the list its whole content height (11 000 px for 500 rows) while it still realises only 205 of them — rows with no widget inside the allocated area.`,`A row’s React tree is rendered on a microtask, not inside the bind. GTK binds a row the moment the view is rooted in a window (measured), which under React is inside a commit or an effect — where a nested root cannot flush and the host refuses by name. A microtask drains before GTK’s next frame, so no row is ever painted empty.`,`A change to data replaces the model rows whose KEYS changed with one splice, which re-binds them; rows whose keys did not change are re-rendered in place instead, because GTK does not re-bind a row whose model object is unchanged (measured: items_changed over the same object does nothing).`,`onEndReached is bound to the scroller’s own Gtk.Adjustment (notify::value / upper / page-size) and fires once per arrival at the end. A list with nothing to scroll never fires, which is every list before it has been allocated.`,`renderItem’s separators.highlight/unhighlight/updateProps throw by name: a Gtk.ListView has no separator widget to restyle.`]},SectionList:{status:`partial`,tier:`P2`,gtk:`Gtk.ListView + one flattened Gio.ListStore`,reason:`The same component as FlatList, handed sections instead of data.`,limits:[`Every FlatList limit applies.`,`The sections are FLATTENED into one model with header ROWS, so a header scrolls with its section. GTK’s own sticky headers do exist — measured: Gtk.SectionModel is present, Gtk.FlattenListModel and every selection model implement it (Gio.ListStore and Gtk.StringList do not), Gtk.ListView.set_header_factory is there, and a flatten model over two stores answered get_section(0) = [0, 2] — and they are not used, because that route needs a second factory, a model of models, and Gtk.ListHeader’s start/end/n-items reconciled with React Native’s section object. stickySectionHeadersEnabled is therefore refused by name rather than silently false.`,`renderSectionFooter is not answered: a footer row would need the flattening to know where a section ends before the next one is read, which the header form does not.`]},VirtualizedList:{status:`partial`,tier:`P2`,gtk:`Gtk.ListView`,reason:`Its public surface is wide and mostly not worth honouring literally; the useful subset backs FlatList, and this name is that subset plus getItem/getItemCount.`,limits:[`Every FlatList limit applies.`,`getItem(data, index) and getItemCount(data) are answered, which is the one thing this name adds over FlatList. The virtualisation knobs — initialNumToRender, maxToRenderPerBatch, windowSize, updateCellsBatchingPeriod, removeClippedSubviews, getItemLayout — are refused by name: Gtk.ListView creates and recycles rows itself and installs no property that changes the batching (measured: 205 of 500 rows in a 400×300 window).`,`CellRendererComponent, debug, onLayout and the other internals of React Native’s own implementation are not answered at all — an unlisted prop is refused by name, which is the point.`]},VirtualizedSectionList:{status:`partial`,tier:`P2`,gtk:`Gtk.ListView`,reason:`The section-shaped sibling of VirtualizedList, which is SectionList here.`,limits:[`Every SectionList limit applies; it is the same component under React Native’s other name.`]},Image:{status:`partial`,tier:`P2`,gtk:`Gtk.Picture`,reason:`resizeMode becomes content-fit, and the default is inverted: React Native defaults to cover, a Gtk.Picture to contain (measured).`,limits:[`resizeMode answers cover, contain, stretch and center. repeat is refused by name: GtkContentFit is FILL, CONTAIN, COVER, SCALE_DOWN (measured) and has no tiling member — tiling is a Gdk.Paintable implementation, not a property of the widget that draws one.`,`source takes { uri } with a local path, a file: URI or a resource: URI. http:/https:/data: are refused by name (they need a fetch, a decoder and a cache — an async pipeline this layer does not own); a require() id is refused (it is an index into React Native’s asset registry, and ADR 0032 § 12 leaves the build chain to the consumer); an array is refused (it is the per-device-scale picker, and GTK scales one texture by the surface scale factor).`,`onLoad, onLoadStart, onLoadEnd, onError and onProgress are refused: Gtk.Picture emits NO signals at all (measured), and a file that does not exist leaves paintable null with no diagnostic — so a callback that never fires would hide exactly the case it exists to report.`,`blurRadius and tintColor are refused: a per-pixel effect is a Gsk render node, not a widget property.`]},ImageBackground:{status:`partial`,tier:`P2`,gtk:`Gtk.Picture in a Gtk.Overlay`,reason:`A picture with the children stacked over it. The picture is the overlay’s MAIN child, because a Gtk.Overlay paints every overlay child ABOVE it.`,limits:[`Every Image limit applies to source and resizeMode.`,`The element is sized by its PICTURE, not by its children — the opposite of React Native, where the image is absolutely positioned and contributes nothing. Measured: a Gtk.Overlay measures only its main child (a 9 px main child beside a 266 px overlay child gave the overlay 9 px), and gtk_overlay_set_measure_overlay() is a per-child METHOD rather than a property, so the host’s data-driven placement has no way to name it. Give the element a size, or let its parent stretch it (flex-1).`,`imageStyle styles the picture and style styles the container, as in React Native. imageRef is refused: this element’s ref is the Gtk.Overlay and overlay.get_child() is the picture.`]},TouchableOpacity:{status:`partial`,tier:`P2`,gtk:`Gtk.Button (flat)`,reason:`The same machinery as Pressable, written over it: one shared record of routes in the primitive table, one line of component.`,limits:[`activeOpacity is refused by name — write active:opacity-70. The pressed appearance is a GTK CSS :active declaration (ADR 0032 § 7), and honouring a raw number here would put a value into the styling path that did not come from the project’s token scale (ADR 0032 § 3).`,`Every Pressable limit applies: onPressIn/onPressOut, onLongPress, hitSlop and the press-delay props are refused by name.`]},TouchableHighlight:{status:`partial`,tier:`P2`,gtk:`Gtk.Button (flat)`,reason:`As TouchableOpacity. The pressed style is Adwaita’s own unless a variant says otherwise.`,limits:[`underlayColor is refused by name — write active:bg-<token>, for the same reason activeOpacity is: a raw colour would bypass the token scale that every other colour in this vocabulary comes from.`,`onShowUnderlay/onHideUnderlay are refused: there is no underlay widget to show.`,`Every TouchableOpacity limit applies.`]},TouchableWithoutFeedback:{status:`partial`,tier:`P2`,gtk:`Gtk.Box + Gtk.GestureClick`,reason:`No chrome, so no button: a vertical Gtk.Box like a View, with a Gtk.GestureClick added to it. Measured: Gtk.Button emits activate and clicked, a Gtk.Box emits neither, and Gtk.GestureClick emits pressed/released/stopped/unpaired-release.`,limits:[`It is a real box in the tree, not a transparent clone of its child — React Native clones the single child and attaches the handlers to it, and GTK has no way for a widget to be its own child. So it lays out like a View and takes one row of the parent’s box.`,`disabled becomes can-target: false rather than sensitive: false, because sensitive greys out every descendant of a wrapper that is supposed to have no appearance of its own.`,`onPress only. The rest of the Touchable surface is refused by name, as on TouchableOpacity.`]},Button:{status:`partial`,tier:`P2`,gtk:`Gtk.Button`,reason:`The one component whose React Native styling story is "you cannot", which GTK agrees with. title, onPress and disabled.`,limits:[`style and className are REFUSED by name, which is faithful: React Native’s Button takes neither. An Adwaita button is painted by the theme and by its own classes (suggested-action, destructive-action), which an application stylesheet sets. Use Pressable when you need to style it.`,`color is refused: it is the background on Android and the text colour on iOS — one prop, two meanings — and GTK’s answer to both is a class rather than a colour.`,`It takes no children: title writes Gtk.Button:label, and a text child would be a second authority for the same slot. React Native’s Button takes no children either.`]},Dimensions:{status:`partial`,tier:`P2`,gtk:`Gtk.Window allocation, Gdk.Monitor geometry`,reason:`get("window") is the window, not the screen — a desktop app is not full-screen, so the screen’s number would be wrong in the ordinary case. get("screen") is the monitor, because that is what it asks for.`,limits:[`get("window") throws by name when there is no window yet, which includes every read at module scope. There is no honest number before the application builds its window, and a zero divides. Read it from a component or an effect, or use useWindowDimensions.`,`The reported size is the window’s ALLOCATION, falling back to default-width/default-height before it has been allocated. It is deliberately NOT the Gdk.Surface size: measured, a 640×480 window has a 668×509 surface, which carries the client-side-decoration shadow.`,`The window is found through Gtk.Window.get_toplevels() (the mapped one first), so it answers for an application that built its own window as well as for one AppRegistry created.`,`fontScale comes from Gtk.Settings:gtk-xft-dpi / 1024 / 96 (measured: 98304, i.e. 1). set() throws by name: it is how React Native’s native side PUBLISHES metrics, and there is no bridge here.`]},useWindowDimensions:{status:`partial`,tier:`P2`,gtk:`Gdk.Surface notify::width/height, Gtk.Window allocation`,reason:`The hook form of Dimensions, through useSyncExternalStore so a resize between render and commit cannot tear.`,limits:[`The NOTIFIER and the VALUE are different objects, and it is measured rather than chosen: Gtk.Widget installs no width or height property and emits no size-allocate signal (the wall <View onLayout> is refused against), while Gdk.Surface installs read-only width and height and notifies on them. So the surface says when and the window says what.`,`PRECONDITION NOT MEASURED: whether the window’s allocation is already updated inside that handler. A compositor-driven resize cannot be triggered from a probe — set_default_size on a mapped window is a no-op (measured) — so this is recorded as unknown rather than guessed.`,`Every Dimensions limit applies to the value itself.`]},Alert:{status:`partial`,tier:`P2`,gtk:`Adw.AlertDialog`,reason:`Direct counterpart, and buildable where Modal is not: Alert is a FUNCTION CALL, so no element is ever inserted into a widget. Measured on libadwaita 1.9.3 — present(null) from a plain function, with no parent and no window, returned with no diagnostic.`,limits:[`destructive maps to Adw.ResponseAppearance.DESTRUCTIVE and cancel becomes the dialog’s CLOSE RESPONSE, which is stronger than an appearance: it is what Escape and the compositor’s close both produce. The first non-cancel button becomes the default response, which is Adwaita’s convention and has no React Native counterpart.`,`Response IDs are positional (response-0, …) rather than derived from the label, so two buttons with the same text do not collide into one response.`,`prompt throws by name: it is iOS-only, and its contract (four overloads, a login/password variant, a callback whose arity depends on the type) is what makes it a refusal rather than a port. Adw.AlertDialog:extra-child is there if you want to build it.`]},Appearance:{status:`supported`,tier:`P2`,gtk:`Adw.StyleManager`,reason:`The imperative sibling of useColorScheme, over the SAME reader — getColorScheme reads Adw.StyleManager:dark (what the user is looking at) and setColorScheme writes :color-scheme (what the application asked for), which is exactly the split React Native’s getter and setter have.`},SafeAreaView:{status:`partial`,tier:`P2`,gtk:`Gtk.Box`,reason:`The INSET has no desktop meaning; the layout does. It is a View in every other respect, and it has to be a real export to be imported.`,limits:[`The safe-area insets are always zero, because a desktop window has none. What is a no-op is the inset — not the box, not the column, not the children: a component that rendered nothing would be a screen that silently disappeared.`,`It is a View, so every View limit applies (the absolute-child overlay switch, onLayout refused, pointerEvents auto/none only).`]},StatusBar:{status:`partial`,tier:`P2`,reason:`A desktop window has no status bar to configure, and <StatusBar/> is in the first ten lines of most React Native screens — so it renders NOTHING and says so, rather than failing to import.`,limits:[`The component renders null. Its declarative props (barStyle, hidden, backgroundColor, translucent, animated) are accepted and do nothing, which is what a declared no-op is.`,`Every imperative static REFUSES by name: setBarStyle, setHidden, setBackgroundColor, setTranslucent, setNetworkActivityIndicatorVisible, pushStackEntry, popStackEntry, replaceStackEntry. A setter that appears to work is indistinguishable from one that does.`,`currentHeight throws by name rather than answering 0: code reads it straight into a layout (paddingTop: StatusBar.currentHeight), and a number here would inset every ported screen by a bar that is not there.`]},KeyboardAvoidingView:{status:`partial`,tier:`P2`,gtk:`Gtk.Box`,reason:`No on-screen keyboard eats a desktop window layout, so the AVOIDING is the no-op. React Native’s KeyboardAvoidingView is a View that changes its own height; what is left here is the View.`,limits:[`behavior, keyboardVerticalOffset and enabled are declared no-ops: they describe the avoidance, which is already off.`,`contentContainerStyle is refused by name: it styles the inner view React Native adds to do the avoiding, and there is no second node here. Put it on style.`,`It is a View, so every View limit applies.`]},Keyboard:{status:`partial`,tier:`P2`,reason:`Its events are on-screen-keyboard events, which do not occur — so the questions with a correct answer get it and the ones whose answer would have to be invented refuse.`,limits:[`addListener REFUSES by name, for every event. A subscription that resolves and then never fires is the silent drop this layer exists to remove: a keyboardDidShow handler that never runs looks like a bug in your own code, for ever.`,`dismiss() and removeAllListeners() are no-ops — nothing was shown, so nothing has to be hidden, and nothing is registered to remove.`,`isVisible() answers false and metrics() answers undefined, which are React Native’s own answers for a keyboard that is not up.`,`scheduleLayoutAnimation throws by name: it is LayoutAnimation’s subsystem (tier P3), not a keyboard behaviour.`]},RefreshControl:{status:`refused`,reason:`GTK has no pull-to-refresh idiom and should not grow one. Give the desktop build a refresh action instead.`},AppState:{status:`planned`,tier:`P3`,gtk:`Gtk.Application / Gdk.Surface state`,reason:`active/background from window focus and visibility.`},PixelRatio:{status:`planned`,tier:`P3`,gtk:`Gdk.Surface.scale-factor`,reason:`The scale factor of the surface the widget is on.`},PlatformColor:{status:`planned`,tier:`P3`,gtk:`Adwaita named colours`,reason:`Maps unusually well — GTK’s palette is exactly this idea.`},AccessibilityInfo:{status:`planned`,tier:`P3`,gtk:`Gtk.Accessible / AT-SPI`,reason:`The highest-value P3 entry: GTK’s accessibility model is strong and the props map onto it well.`},Animated:{status:`partial`,tier:`P3`,gtk:`Adw.TimedAnimation, over Adw.CallbackAnimationTarget`,reason:`Value, timing and View — the three names a measured application uses, in one file of 28 routes. The rest of the subsystem is a graph evaluated per frame, and every other member refuses BY NAME.`,limits:["THE SUBSET IS: `new Animated.Value(n)` with setValue/__getValue/stopAnimation/resetAnimation, `Animated.timing(value, { toValue, duration, easing, useNativeDriver }).start(cb)` with stop() and reset(), and `<Animated.View style={{ opacity: value }}>`. Every other member of Animated — spring, decay, sequence, parallel, stagger, loop, delay, event, add/subtract/multiply/divide/modulo/diffClamp, Interpolation, Node, ValueXY, Color, createAnimatedComponent, and the Text/Image/ScrollView/FlatList/SectionList components — is a present function that THROWS with its own reason, so a reader learns the limit at the call instead of from `undefined is not a function`.","The only animatable style key is `opacity`, which is `Gtk.Widget:opacity` — a writable gdouble on every widget. `transform` (and translateX/Y, scale, rotate) is a Gsk render node rather than a widget property; `width`/`height` would animate `width-request`, which is a MINIMUM and not a size; colour is GTK CSS and has no property to drive. Each is refused by name at the element.","An animated `opacity` beside an authored one (`opacity-70`, `style={{ opacity }}`, `active:opacity-70`) is REFUSED: L1 partitions opacity into GTK CSS and the animation writes the widget property, which is two channels painting one appearance.","useNativeDriver is accepted and MEANINGLESS. It chooses whether the JS thread ships each frame over the bridge; there is no bridge here, `Adw.TimedAnimation` owns the frame clock either way, and React re-renders for a frame in neither case. Both values behave identically.","An animation whose widget is not realized SKIPS — measured on libadwaita 1.9.3: `play()` sets FINISHED, writes the end value and emits `done` synchronously. That is also what libadwaita does when the user has switched animations off, so a start before the window is mapped jumps to the end rather than running.","A run ends with `{ finished: false }` when every `<Animated.View>` bound to its value unmounts. `Adw.Animation` takes its frame clock from a widget, and MEASURED, destroying that widget makes the animation skip to its end and emit `done` — so without this the layer would report a completion nobody saw.","timing refuses `delay`, `iterations`, `isInteraction`, `onComplete`, `platformConfig` and `debugID` by name, and any other config key generically. `toValue` takes a number only: React Native also accepts a value, an {x, y} pair and a colour there."]},Easing:{status:`partial`,tier:`P3`,gtk:`AdwEasing, through Adw.TimedAnimation:easing`,reason:`Not arithmetic, which the planning entry called it: React Native’s easings are FUNCTIONS and AdwEasing is an ENUM with no callback form, so this is a name-to-enum mapping and every pair in it is measured.`,limits:["Eleven families map EXACTLY (deviation at or below float noise, sampled at 1 001 points against React Native 0.87.1’s own formulas): linear, ease, quad, cubic, poly(1…5), sin, circle, back at its default overshoot, and bounce — plus `in`/`out`/`inOut` over them. `exp` maps with a stated 9.77e-4 deviation, all of it at one endpoint (RN’s 2^(10(t−1)) is 1/1024 at t=0 where CSS’s expo is 0).","bounce is INVERTED between the two vocabularies: React Native’s `Easing.bounce` is the standard easeOutBounce, so `in(bounce)` is AdwEasing’s EASE_OUT_BOUNCE (deviation 0) and `out(bounce)` is EASE_IN_BOUNCE. Matching the names to each other instead is off by 8.1e-1.",`Three combinations have NO member and are refused with their measured deviation: inOut(ease) (nearest 1.20e-2), inOut(back) (6.62e-2 from EASE_IN_OUT_BACK) and inOut(bounce) (4.06e-1).`,"elastic, bezier, step0, step1, a `back(s)` with a non-default overshoot and a `poly(n)` outside 1…5 are refused by name — AdwEasing has no member for any of them, and elastic is 1.99e-1 from the nearest of all 35.","A function this layer did not mint is refused rather than sampled: `Adw.TimedAnimation:easing` names a member, and guessing which of the 35 a caller’s closure resembles is the approximation the whole table exists instead of.","React Native’s own `timing` default is `Easing.inOut(Easing.ease)`, which no member reproduces; the default here is EASE_IN_OUT, 2.86e-2 away from it."]},LayoutAnimation:{status:`planned`,tier:`P3`,reason:`Needs an animated layout pass, which is the same subsystem as Animated.`},InteractionManager:{status:`planned`,tier:`P3`,reason:`Deferring work until interactions settle; a main-loop idle source is the counterpart.`},useAnimatedValue:{status:`planned`,tier:`P3`,reason:`Part of the Animated subsystem.`},useAnimatedValueXY:{status:`planned`,tier:`P3`,reason:`Part of the Animated subsystem.`},useAnimatedColor:{status:`planned`,tier:`P3`,reason:`Part of the Animated subsystem.`},PanResponder:{status:`planned`,tier:`P3`,gtk:`Gtk.Gesture* controllers`,reason:`The controllers exist; the arbitration model is not React Native’s, so this is its own project.`},usePressability:{status:`planned`,tier:`P3`,reason:`The hook behind the Touchable family; it lands with the gesture work.`},DrawerLayoutAndroid:{status:`planned`,tier:`P3`,gtk:`Adw.OverlaySplitView`,reason:`The pattern survives on a desktop even though the component is Android-only.`},I18nManager:{status:`planned`,tier:`P3`,gtk:`Gtk.Widget.direction`,reason:`RTL is a widget-direction question on GTK.`},LogBox:{status:`no-desktop-meaning`,tier:`P3`,reason:`A development overlay for a phone; the console is the desktop equivalent.`},Systrace:{status:`no-desktop-meaning`,reason:`Android systrace has no desktop counterpart.`},Vibration:{status:`no-desktop-meaning`,reason:`A desktop machine does not vibrate.`},ToastAndroid:{status:`planned`,tier:`P3`,gtk:`Adw.Toast`,reason:`Android-only by name, and Adwaita has the exact widget.`},InputAccessoryView:{status:`no-desktop-meaning`,reason:`An iOS keyboard accessory bar; there is no keyboard to accessorise.`},TouchableNativeFeedback:{status:`planned`,tier:`P3`,gtk:`Gtk.Button`,reason:`Android-only ripple; shimmed to its portable sibling.`},ActionSheetIOS:{status:`planned`,tier:`P3`,gtk:`Adw.AlertDialog with responses`,reason:`iOS-only by name; the pattern is a dialog with choices.`},PushNotificationIOS:{status:`refused`,reason:`Platform notification plumbing. A desktop app uses Gio.Notification directly.`},PermissionsAndroid:{status:`refused`,reason:`Android runtime permissions have no desktop counterpart; portals are asked for at use time.`},Settings:{status:`refused`,reason:`An iOS user-defaults bridge. GSettings is the desktop answer and is not this API.`},Clipboard:{status:`planned`,tier:`P3`,gtk:`Gdk.Clipboard`,reason:`Deprecated upstream in favour of a community package, but trivial here.`},BackHandler:{status:`planned`,tier:`P3`,reason:'An Android hardware back button. Routing has landed and this did NOT arrive with it, which the earlier reason assumed it would: BackHandler INTERCEPTS a back press and consumes it, and MEASURED on libadwaita 1.9.3, Adw.NavigationView emits `popped` AFTER the fact and has no vetoable "about to pop" signal at all — its only prevention is Adw.NavigationPage:can-pop, a property rather than an event. The honest counterpart is usePreventRemove, which the routing layer does honour through its popped bridge; this name needs a key controller of its own on the window.'},DynamicColorIOS:{status:`planned`,tier:`P3`,reason:`A light/dark colour pair; the Adwaita scheme already provides the switch.`},processColor:{status:`planned`,tier:`P3`,reason:`Colour string to a platform value; a Gdk.RGBA on this side.`},UTFSequence:{status:`planned`,tier:`P3`,reason:`A table of unicode constants. Pure data, no platform in it.`},experimental_LayoutConformance:{status:`refused`,reason:`An experimental switch between two React Native layout implementations. Neither is used here.`},unstable_VirtualView:{status:`refused`,reason:`Unstable React Native internal.`},VirtualViewMode:{status:`refused`,reason:`Unstable React Native internal.`},unstable_NativeText:{status:`refused`,reason:`Unstable React Native internal.`},unstable_NativeView:{status:`refused`,reason:`Unstable React Native internal.`},unstable_TextAncestorContext:{status:`refused`,reason:`Unstable React Native internal.`},ReactNativeVersion:{status:`planned`,tier:`P3`,reason:`The version this layer targets, reported honestly rather than spoofed.`},DeviceInfo:{status:`refused`,reason:`A native module surface describing a phone.`},DevMenu:{status:`no-desktop-meaning`,reason:`The shake-to-open developer menu.`},DevSettings:{status:`no-desktop-meaning`,reason:`Development-client settings for a phone runtime.`},NativeModules:{status:`refused`,reason:`The native-module bridge. There is no bridge here; this layer renders in-process onto GTK.`},TurboModuleRegistry:{status:`refused`,reason:`The TurboModule lookup. Same reason as NativeModules.`},NativeComponentRegistry:{status:`refused`,reason:`Fabric component registration. The host owns widget creation.`},requireNativeComponent:{status:`refused`,reason:`Looks up a native view manager. Write a GTK widget descriptor instead.`},codegenNativeComponent:{status:`refused`,reason:`React Native codegen for Fabric components.`},codegenNativeCommands:{status:`refused`,reason:`React Native codegen for Fabric commands.`},UIManager:{status:`refused`,reason:`The legacy view-manager surface. The GTK host is the view manager here.`},findNodeHandle:{status:`refused`,reason:`Returns a native view tag. A ref here is the Gtk.Widget itself, which is more useful.`},registerCallableModule:{status:`refused`,reason:`Registers a module callable from the native side. There is no native side.`},Networking:{status:`refused`,reason:`React Native’s XHR internals. Use fetch, which gjsify provides.`},NativeDialogManagerAndroid:{status:`refused`,reason:`An Android dialog native module. Alert is the portable spelling.`},ProgressBarAndroid:{status:`planned`,tier:`P3`,gtk:`Gtk.ProgressBar`,reason:`Android-only by name; GTK has the widget.`},Touchable:{status:`refused`,reason:`The legacy mixin behind the Touchable family, not a public component.`},EventEmitter:{status:`supported`,reason:`Pure JavaScript; nothing in it touches a platform.`},NativeEventEmitter:{status:`planned`,tier:`P3`,reason:`It would construct and subscribe, but nothing native would ever emit into it — shipping that needs a decision, not a class.`},DeviceEventEmitter:{status:`planned`,tier:`P3`,reason:`The global emitter. Lands with NativeEventEmitter, and for the same reason.`},NativeAppEventEmitter:{status:`refused`,reason:`The legacy iOS app-event emitter.`},RootTagContext:{status:`refused`,reason:`A React Native surface identifier. This layer has one root per Adw window.`},unstable_batchedUpdates:{status:`supported`,reason:`React 19 batches automatically; this is the identity call it already is upstream.`}},n={router:{status:`partial`,tier:`P1`,gtk:`Adw.NavigationView (push/pop) via React Navigation’s StackActions`,reason:`push, back, replace, navigate and canGoBack. Every href-taking method accepts BOTH argument shapes — a path string and expo-router’s { pathname, params } object.`,limits:["ARGUMENT SHAPES, because naming only the methods is the half that let a defect through: push/navigate/replace take `string | { pathname, params }`; back() and canGoBack() take nothing. A params value is a string, a number or a boolean — anything structural is refused by name, because a URL segment is a string and useLocalSearchParams reads it back as one. Params the pattern has no slot for become a query string, which useLocalSearchParams also answers for, so the round trip is total.",'The object form used to be missing and it did NOT throw: it interpolated as "[object Object]", so the push succeeded, no route matched, and every parameterised navigation landed on +not-found — 10 call sites in one measured application. `hrefFrom` and `useLocalSearchParams` now share one definition of what a param is, so a drift between writing and reading is a defect the layer detects in itself.',`push falls back to NAVIGATE when the navigator that owns the target is not mounted yet. StackActions.push is dispatched at ONE navigator and an href can name a screen several navigators down; for an unmounted navigator, arriving there IS the new entry, so the fallback is correct rather than approximate — but a push into a mounted navigator that is not a stack cannot add an entry, because PUSH is the stack router’s action and no other router answers it.`,`back() THROWS when there is nothing to go back to, where expo-router and React Navigation both return quietly. A quiet return is a back button that does nothing with no message, which is the silent drop this layer refuses everywhere else. canGoBack() is the question that lets a caller avoid it, and it answers false before the container is ready — nothing has been navigated to yet, so there is genuinely nowhere to go back to.`,`setParams, dismiss, dismissAll and dismissTo are present functions that THROW with their reason. The dismiss family needs a modal stack this layer has no portal seam for (see Modal); setParams edits the current route’s params in place, so the URL would stop describing the screen and usePathname would answer for a path that is no longer the route’s — replace({ pathname, params }) changes both together.`,`A catch-all pathname ([...rest]) is refused, with the file-tree parser’s own reason: React Navigation’s path config has no multi-segment wildcard that also carries its parts as a param.`]},useLocalSearchParams:{status:`partial`,tier:`P1`,reason:`The current route’s params — the [param] values and the query string — read through React Navigation’s own useRoute().`,limits:[`Values are strings, because a URL segment is one. A number or a boolean that arrived through a dispatched param is stringified; anything structural (an object, an array) is left out, and a [param] cannot produce one. expo-router additionally returns string[] for a repeated query key, which this layer does not.`,`React Navigation’s seven nesting keys — screen, params, initial, state, path, pop, merge — are filtered out, so a route cannot use those seven as param names.`]},usePathname:{status:`partial`,tier:`P1`,reason:`The current URL without its query string, from React Navigation’s getPathFromState over the published root state.`,limits:[`On the +not-found route it reports "/+not-found" rather than the URL that missed. getPathFromState builds a path from the STATE, and the state records which screen matched, not the text that reached it.`,`It answers "/" before the navigation container is ready. That is not a placeholder — nothing has been navigated to yet — but a component that renders on the first commit and compares against a literal will see it.`]},Stack:{status:`partial`,tier:`P1`,gtk:`Adw.NavigationView + Adw.NavigationPage`,reason:`The stack navigator: React declares which pages exist, the widget owns their order, and the route key is the tag that joins the two.`,limits:[`A screen answers title, headerShown and animation. Every other expo-router / React Navigation stack option is refused BY NAME at the point of declaration, because an option that is accepted and ignored is invisible until someone looks at the window.`,`The header is an Adw.HeaderBar inside an Adw.ToolbarView, which grows its own back button and reads the page’s own title. A custom header component is not supported; headerShown={false} drops the bar, and with it the back affordance.`,`animation is "default" or "none" — Adw.NavigationView has one transition and a switch for it (animate-transitions), not a set of named ones.`,`Screen preloading is not implemented. React Navigation’s preloadedRoutes would need pages added to the widget’s pool without entering the stack, which is expressible and untested here.`]},Tabs:{status:`partial`,tier:`P1`,gtk:`Adw.ViewStack + Adw.ViewSwitcher`,reason:`The tab navigator. The switcher is driven by the stack’s own page model, so a route file adds a button with no tab-bar bookkeeping.`,limits:[`A tab answers title only. tabBarIcon is refused: in React Native it is a COMPONENT and Adwaita paints a switcher button from Adw.ViewStackPage:icon-name, an icon NAME on a page object the add returns — reachable through a ref, not through this declaration.`,`Every tab is mounted. React Native’s tab navigator is lazy because a phone cannot afford five screens; an Adw.ViewStack page that is not the visible child is not realised, and laziness would buy a flash on first switch.`,`The switcher sits in the header bar with policy WIDE (MEASURED: the default is NARROW, the phone-shaped one). A narrow-window breakpoint is the application’s to declare — Adw.ViewSwitcherBar is not wired here.`,`tabBarBadge, tabBarPosition and the rest of the tab-bar vocabulary are refused by name for the same reason as tabBarIcon: they describe a bar this layer does not draw.`]},Link:{status:`planned`,tier:`P2`,gtk:`Gtk.Button (flat) or Gtk.LinkButton`,reason:"An href as an element rather than a call. Cheap once `router` exists, and the honest widget question — button or link — is worth measuring first."},Redirect:{status:`planned`,tier:`P2`,reason:`A declarative navigate-on-render. It needs a rule for what happens when it redirects during the first commit, which is the commit that must not be empty.`},Slot:{status:`planned`,tier:`P2`,gtk:`Adw.Bin`,reason:`A layout that renders its child route with no navigator around it. It is the one layout shape that has no widget of its own.`},useRouter:{status:`planned`,tier:`P2`,reason:"The hook form of `router`. Identical behaviour, and it exists so a test can substitute the object — which is worth having once there is something to substitute."},useSegments:{status:`planned`,tier:`P2`,reason:`The current route split into segments. Derivable from the published root state, and unused in the measured application.`},useGlobalSearchParams:{status:`planned`,tier:`P2`,reason:`The params of the focused route anywhere in the tree, rather than of the calling screen. It re-renders on every navigation by design, which is why expo-router documents preferring the local form.`},useNavigation:{status:`planned`,tier:`P2`,reason:`React Navigation’s own hook, re-exported by expo-router. It works already through @react-navigation/core; exporting it from here is a decision about what this surface promises, not a build.`},useFocusEffect:{status:`planned`,tier:`P2`,reason:`As useNavigation: it is core’s, and it works. The open question is the same one.`},useRootNavigationState:{status:`planned`,tier:`P3`,reason:"The root state as a hook. The store `usePathname` reads is already there; this is a second selector over it."},Drawer:{status:`planned`,tier:`P3`,gtk:`Adw.OverlaySplitView`,reason:`A sidebar navigator. The pattern survives on a desktop better than it does on a phone, and Adwaita has the exact widget — it is a third navigator, not a variation on these two.`},withLayoutContext:{status:`planned`,tier:`P3`,reason:"The escape hatch that lets a third-party navigator take its screens from the file tree. It is exactly `useRouteNode` plus screen synthesis, made public — worth doing once a third navigator exists to prove the shape."},Navigator:{status:`planned`,tier:`P3`,reason:`expo-router’s low-level navigator primitive. It belongs with withLayoutContext and for the same reason.`},ErrorBoundary:{status:`planned`,tier:`P3`,gtk:`Adw.StatusPage`,reason:`A per-route error screen. React 19 routes an uncaught error to the root’s handler and @gjsify/gtk-host/react rethrows it from render() — deliberately, so a refusal is not swallowed — and a boundary here has to be reconciled with that rather than bolted beside it.`},ExpoRoot:{status:`refused`,reason:"It takes a Metro `require.context`, which does not exist in this build chain. `RouterRoot` takes the manifest a bundler plugin emits instead — the same job, with the one input that is available."},useUnstableGlobalHref:{status:`refused`,reason:`Unstable by its own name, and it answers the question usePathname already answers for the only surface this layer has.`},useNavigationContainerRef:{status:`refused`,reason:"The container ref is this layer’s own (one process routes one tree), and handing it out would let a consumer dispatch around the refusals `router` exists to give."},SplashScreen:{status:`refused`,reason:`A native splash screen belongs to a phone launcher. A GTK application maps its window when it is ready, which is the desktop equivalent and is Gio.Application’s job, not the router’s.`}},r={StatusBar:{status:`partial`,tier:`P1`,reason:"`react-native`’s own StatusBar, re-exported. A desktop window has no bar above it, so the component renders null and every imperative setter refuses by name.",limits:[`Every limit of react-native’s StatusBar applies, because it IS that component: the declarative props are accepted no-ops and currentHeight throws rather than answering 0.`,`expo-status-bar’s own extra props — style="auto"|"inverted", animated, translucent, hidden, backgroundColor, networkActivityIndicatorVisible, hideTransition — are accepted and do nothing, for the same reason.`]},setStatusBarStyle:{status:`refused`,reason:`Sets the bar’s contrast NOW. There is no bar, and a setter that appears to work is indistinguishable from one that does.`},setStatusBarHidden:{status:`refused`,reason:`As setStatusBarStyle: there is no bar to hide.`},setStatusBarBackgroundColor:{status:`refused`,reason:`Android-only even on a phone, and there is no bar here to paint.`},setStatusBarTranslucent:{status:`refused`,reason:`As setStatusBarBackgroundColor.`},setStatusBarNetworkActivityIndicatorVisible:{status:`refused`,reason:`An iOS spinner in the carrier bar. A desktop application shows progress in its own window.`}},i={useFonts:{status:`partial`,tier:`P1`,gtk:`Pango’s font map`,reason:`A desktop application does not load a font file per screen: fonts are INSTALLED and the platform’s font map discovers them, so the hook has nothing to wait for and reports ready on its first render.`,limits:["It answers [true, null] immediately and NEVER re-renders. That is the honest shape — there is no asynchronous load to finish — and it means a screen gated on `if (!loaded) return null` renders straight away instead of flashing.",'The map’s VALUES are ignored: a `require("./Inter.ttf")` id is an index into React Native’s asset registry, which ADR 0032 § 12 leaves to the consumer’s build chain, and this layer refuses one for `Image.source` for the same reason. Ship the face with the application and name the FAMILY in your styles: `gjsify.ship.fonts` stages it into `share/fonts/<appId>/`, and each OS reaches it differently (ADR 0038) — fontconfig scans that directory on Linux (measured), `ATSApplicationFontsPath` in the bundle’s Info.plist is documented to activate it on macOS (Apple’s key reference; unverified on hardware here), and on Windows nothing reaches it declaratively at all (measured on Windows 11: the default font map reads no fontconfig configuration, even an exclusive one), so the launcher exports GJSIFY_FONT_DIR and the app registers the faces itself by calling `initFonts()` from `@gjsify/gtk-host/fonts` at startup, which walks that directory into `PangoCairo.FontMap.get_default().add_font_file()` — measured to work there, on the same font map a widget renders through — and no-ops where the OS already activated them.',"It does not check that the families exist, deliberately: `isLoaded` does, and a hook that threw here would fail an application whose font is installed under a family name the map’s key does not spell."]},isLoaded:{status:`partial`,tier:`P2`,gtk:`PangoCairo.FontMap.list_families`,reason:`A real answer rather than a stub: whether Pango knows a family of that name on this machine.`,limits:[`The comparison is on the FAMILY name and is case-insensitive, which is what Pango matches on. A PostScript name or a file path answers false.`,"The font map is read once and cached. A font installed while the application is running is not seen — Pango’s own map is not reloaded either, and `Pango.FontMap.changed` is not wired here."]},isLoading:{status:`supported`,tier:`P2`,reason:`Always false. Nothing loads asynchronously, so nothing is ever loading — which is the same answer React Native gives once a font has arrived.`},loadAsync:{status:`refused`,reason:'Registers a font file with the runtime, and what it is HANDED is not a file: the argument is a `require("./Inter.ttf")` id into React Native’s asset registry, which ADR 0032 § 12 leaves to the consumer’s build chain — the same reason `useFonts` ignores its map’s values. So there is no path to register, and a promise that resolved would be claiming a font was installed when it was not. NOT because the call is missing: `pango_font_map_add_font_file()` is in the typelib since Pango 1.56 and `@gjsify/dom-elements` uses it for Canvas FontFace, but it answers G_IO_ERROR_NOT_SUPPORTED on the CoreText map, so it would work on Linux and Windows and lie on macOS. Install the face, or ship it with the application (`gjsify.ship.fonts`, ADR 0038).'},unloadAsync:{status:`refused`,reason:`The inverse of loadAsync, and it has the same answer.`},unloadAllAsync:{status:`refused`,reason:`As unloadAsync.`},FontDisplay:{status:`refused`,reason:"A web `font-display` strategy for a font that is still downloading. Nothing downloads here."}},a={openURL:{status:`partial`,tier:`P1`,gtk:`Gtk.UriLauncher`,reason:"`react-native`’s own Linking.openURL, re-exported — the same measured implementation, including the `can_launch` gate that stops a promise never settling.",limits:[`Every limit of react-native’s Linking.openURL applies; this is that function.`]},canOpenURL:{status:`partial`,tier:`P1`,gtk:`Gtk.UriLauncher.can_launch`,reason:`As openURL: react-native’s own.`,limits:[`Every limit of react-native’s Linking.canOpenURL applies.`]},getInitialURL:{status:`partial`,tier:`P1`,reason:`Always resolves null, which is also what React Native returns for a normal launch.`,limits:[`A desktop deep link arrives as Gio.Application::open AFTER startup, so there is no value to read before it.`]},useURL:{status:`partial`,tier:`P2`,reason:`The hook form of getInitialURL, and it answers null for the same reason.`,limits:["It never updates. A URL delivered while the application runs is `Gio.Application::open`, which is the application object’s own wiring (HANDLES_OPEN plus the signal) and above this layer — the same refusal Linking.addEventListener gives."]},parse:{status:`partial`,tier:`P2`,reason:"Pure URL parsing, so it is answerable with no platform at all: `WHATWG URL`, which gjsify provides, reshaped into expo-linking’s { scheme, hostname, path, queryParams }.",limits:["queryParams values are strings; expo-linking returns string[] for a repeated key and this does not, matching the same narrowing `useLocalSearchParams` already declares.","A custom-scheme URL with no `//` (`myapp:profile`) parses with a null hostname and the whole remainder as the path, which is what the URL standard says and not always what a phone deep link meant."]},createURL:{status:`refused`,reason:"Builds a URL from the application’s own scheme, which expo reads from `app.json`. There is no Expo config here; a desktop application’s identity is its Gio.Application id and its scheme is a desktop-entry declaration. Write the URL."},addEventListener:{status:`refused`,reason:`URL delivery is Gio.Application::open with HANDLES_OPEN in the application flags — the application object’s own wiring, above this layer. Same refusal as react-native’s Linking.`},openSettings:{status:`refused`,reason:`A phone OS per-app settings page. GNOME Settings has no per-application section a program can deep-link into.`},sendIntent:{status:`refused`,reason:`An Android Intent. Same refusal as react-native’s Linking.`}},o={openBrowserAsync:{status:`partial`,tier:`P1`,gtk:`Gtk.UriLauncher`,reason:`On a phone this opens an IN-APP browser; on a desktop the counterpart is the user’s own browser, which is what Linking.openURL already does.`,limits:[`It resolves { type: "opened" } as soon as the launch succeeds. It CANNOT report a dismissal: the page is in another application and this process is never told when the user closes it. React Native resolves on dismiss, so code that awaits this to know the user is back will continue early.`,`Every presentation option — toolbarColor, controlsColor, showTitle, enableBarCollapsing, presentationStyle — is ignored: they describe an in-app browser this layer does not draw.`]},WebBrowserResultType:{status:`supported`,tier:`P1`,reason:`The result constants, so a comparison against them resolves instead of failing to import.`},dismissBrowser:{status:`refused`,reason:`Closes the in-app browser. There is none: the page is in another application and closing someone else’s window is not this application’s to do.`},openAuthSessionAsync:{status:`refused`,reason:`Opens an in-app browser AND intercepts the redirect back to the app. The interception is the whole feature and it needs the in-app browser; with the system browser the redirect arrives as Gio.Application::open, which is the application’s own wiring.`},dismissAuthSession:{status:`refused`,reason:`As dismissBrowser.`},maybeCompleteAuthSession:{status:`refused`,reason:`Completes a web-popup auth flow, which is expo-web-browser’s browser-target behaviour. There is no popup here.`},warmUpAsync:{status:`refused`,reason:`Pre-warms Android’s Custom Tabs service. A refusal rather than a no-op, because a no-op here would be an optimisation hint that silently does nothing on every platform — and there is no service to warm.`},coolDownAsync:{status:`refused`,reason:`The inverse of warmUpAsync.`}},s={SafeAreaView:{status:`partial`,tier:`P1`,gtk:`Gtk.Box`,reason:"`react-native`’s own SafeAreaView, re-exported: the INSET has no desktop meaning, the layout does.",limits:[`Every limit of react-native’s SafeAreaView applies, and it is the same component.`,"The `edges` and `mode` props this package adds are accepted and do nothing: every inset is zero, so there is no edge to apply one to and no padding-versus-margin question to answer."]},SafeAreaProvider:{status:`partial`,tier:`P1`,gtk:`Gtk.Box`,reason:`It is a View that publishes the insets. The insets are zero and constant here, so what is left is the View — and it must render, because a provider that rendered nothing would delete the whole application below it.`,limits:["It is a View, so every View limit applies. `initialMetrics` is accepted and ignored: the metrics it would seed are the ones this layer already answers constantly."]},useSafeAreaInsets:{status:`partial`,tier:`P1`,reason:`Always { top: 0, right: 0, bottom: 0, left: 0 }.`,limits:[`It never changes, so it never re-renders. A desktop window has no notch, no home indicator and no carrier bar; the window manager’s decorations are OUTSIDE the surface this layer lays out.`,`It does NOT require a SafeAreaProvider above it, where the real package throws. A refusal there would be inventing a requirement this implementation does not have.`]},useSafeAreaFrame:{status:`partial`,tier:`P2`,gtk:`Gtk.Window allocation`,reason:"The frame is the window, so this is `useWindowDimensions` with an x/y of zero.",limits:[`Every limit of react-native’s useWindowDimensions applies to width and height; x and y are always 0.`]},initialWindowMetrics:{status:`partial`,tier:`P2`,reason:`Zero insets and a zero frame. React Native populates this from the native side BEFORE the first render so a screen can lay out without a flash; there is nothing to read before a GTK window exists.`,limits:['The frame is 0×0, not the window’s size: reading a window that has not been built yet is what `Dimensions.get("window")` refuses by name, and returning a plausible number here would be the same lie in a value nobody checks.']},SafeAreaInsetsContext:{status:`planned`,tier:`P3`,reason:"The context object behind the hook, used by class components. It is a `createContext` call with a constant in it, and it lands when something needs the class-component form."},SafeAreaFrameContext:{status:`planned`,tier:`P3`,reason:`As SafeAreaInsetsContext.`},withSafeAreaInsets:{status:`refused`,reason:`A higher-order component that injects the insets into a class component. The insets are constant zero; write them.`},SafeAreaConsumer:{status:`refused`,reason:`The deprecated render-prop form, superseded upstream by the hook.`}},c={GestureHandlerRootView:{status:`partial`,tier:`P1`,gtk:`Gtk.Box`,reason:`The root every gesture-handler application wraps itself in. It exists to host the library’s native touch arbitration, and there is none here — so what is left is the View, and it has to render or the application below it disappears.`,limits:["It is a View, so every View limit applies. It arbitrates nothing: GTK gesture controllers have their own conflict model (claim/deny on a `Gtk.GestureGroup`) and it is not React Native’s."]},Gesture:{status:`not-reachable`,reason:`The gesture builder’s handlers are WORKLETS, compiled by a Babel plugin that is not in this build chain (ADR 0032’s own Consequences). This is not a scheduling statement.`},GestureDetector:{status:`not-reachable`,reason:"It runs `Gesture`’s worklets. Same answer."},PanGestureHandler:{status:`planned`,tier:`P3`,gtk:`Gtk.GestureDrag`,reason:"The legacy handler components do not need worklets, and GTK has the controllers — `Gtk.GestureDrag`, `Gtk.GestureClick`, `Gtk.GestureZoom`. What they need is an arbitration model, which is `PanResponder`’s own project in the react-native table."},TapGestureHandler:{status:`planned`,tier:`P3`,gtk:`Gtk.GestureClick`,reason:`As PanGestureHandler.`},LongPressGestureHandler:{status:`planned`,tier:`P3`,gtk:`Gtk.GestureLongPress`,reason:`As PanGestureHandler.`},PinchGestureHandler:{status:`planned`,tier:`P3`,gtk:`Gtk.GestureZoom`,reason:`As PanGestureHandler.`},Swipeable:{status:`refused`,reason:`A row that reveals actions when dragged. Adwaita’s answer to the same idea is a different interaction entirely, and reproducing a phone one on a desktop is the approximation this layer refuses.`},ScrollView:{status:`refused`,reason:`gesture-handler’s re-wrapped ScrollView exists to cooperate with its own touch arbitration. Import ScrollView from react-native.`},Directions:{status:`refused`,reason:`Direction constants for the worklet gesture API.`},State:{status:`refused`,reason:`The gesture state machine’s constants, for the same API.`}},l={default:{status:`partial`,tier:`P1`,gtk:`Gio.File in GLib.get_user_data_dir()`,reason:`A REAL store, not a stub: one JSON document in the application’s own data directory, read once and rewritten atomically on every mutation.`,limits:[`The whole store is rewritten on every write. React Native’s Android implementation is SQLite and does not; this is a document, so a hot write loop over a large store is O(store) per call. It is sized for what AsyncStorage is documented for — preferences, a session token, a small cache — and not for a database.`,"A write is `Gio.File.replace_contents` with REPLACE_DESTINATION, which is a write-to-temp-and-rename. A torn file is therefore not reachable through this API; a file corrupted by something else is, and it is reported by name on the first read rather than silently starting from empty.","Nothing is encrypted, which is also React Native’s own contract. A secret belongs in the keyring, which is `Secret.Service` and not this API.",'GLib.KeyFile was the obvious desktop shape and is NOT used, MEASURED: `g_key_file_set_string` with a key containing "=" prints a GLib-CRITICAL and DROPS the write, returning normally — and AsyncStorage keys are arbitrary strings ("@app:token", "persist:root"). A store that silently loses a key is the exact failure this layer exists against.',"The store’s path needs the application id, which comes from `Gio.Application.get_default()` or `GLib.get_prgname()`. Before a Gio.Application exists — a read at module scope in a script — it throws by name rather than writing to a directory named after the interpreter."]},useAsyncStorage:{status:`partial`,tier:`P2`,reason:`The per-key handle: getItem/setItem/mergeItem/removeItem bound to one key. Pure composition over the default export.`,limits:[`Every limit of the default export applies. It is not reactive: it returns callbacks, not a value, which is upstream’s own shape.`]}},u={Ionicons:{status:`partial`,tier:`P1`,gtk:`Gtk.Image with a symbolic icon-name`,reason:`A declared mapping from Ionicons’ names onto the icon theme’s symbolic names, with every TARGET held against the installed theme by the spec.`,limits:["An unmapped Ionicons name is a NAMED REFUSAL listing what is mapped, and that is the whole design. GTK’s answer to an icon it does not have is `image-missing` drawn silently — the exit-0 failure mode — so a mapping table without a refusal would put a broken-image glyph in a shipped application.","The mapping’s KEY SET is declared rather than read from a glyph map: `@expo/vector-icons` is not a dependency here. A key that does not exist upstream is a dead row and costs nothing; a key that is missing is a refusal naming what to do. The GTK half is measured — every target is asserted present in the installed theme.",`Several Ionicons names map to ONE symbolic icon (chevron-forward and arrow-forward are both go-next-symbolic), because the icon theme draws the distinction the desktop makes rather than the one iOS does.`,"Filled and outline variants mostly collapse: the Adwaita symbolic set is one weight. A name whose only difference is `-outline` maps to the same icon, and where the theme really has both (starred/non-starred) the pair is kept.","size becomes `Gtk.Image:pixel-size` verbatim. color is a GTK CSS `color` on the generated class, which is how a symbolic icon is recoloured; a non-token colour goes through the same partition as any other style value."]},MaterialIcons:{status:`planned`,tier:`P3`,reason:`A second glyph vocabulary over the same mechanism — a table and its measurement, not new code. It lands when an application measured here uses one.`},MaterialCommunityIcons:{status:`planned`,tier:`P3`,reason:`As MaterialIcons.`},FontAwesome:{status:`planned`,tier:`P3`,reason:`As MaterialIcons.`},Feather:{status:`planned`,tier:`P3`,reason:`As MaterialIcons.`},AntDesign:{status:`planned`,tier:`P3`,reason:`As MaterialIcons.`},Entypo:{status:`planned`,tier:`P3`,reason:`As MaterialIcons.`},Octicons:{status:`planned`,tier:`P3`,reason:`As MaterialIcons.`},SimpleLineIcons:{status:`planned`,tier:`P3`,reason:`As MaterialIcons.`},createIconSet:{status:`refused`,reason:`Builds an icon component from a glyph map and a FONT FILE, rendering a codepoint as text. A GTK symbolic icon is an SVG the theme owns, addressed by name — so there is no font to hand in and no codepoint to render.`},createIconSetFromFontello:{status:`refused`,reason:`As createIconSet.`},createIconSetFromIcoMoon:{status:`refused`,reason:`As createIconSet.`}},d={Image:{status:`planned`,tier:`P2`,gtk:`Gtk.Picture`,reason:`The same widget react-native’s Image already uses, plus caching, transitions and blurhash. The widget half is answered; the rest is a decoding-and-cache pipeline this layer does not own yet. Import Image from react-native for the widget half.`},ImageBackground:{status:`planned`,tier:`P2`,gtk:`Gtk.Picture in a Gtk.Overlay`,reason:`As Image.`},useImage:{status:`planned`,tier:`P3`,reason:`Loads a source into an image object ahead of render. It needs the pipeline Image needs.`}},f={useAudioPlayer:{status:`planned`,tier:`P3`,gtk:`Gtk.MediaFile`,reason:`Playback is a MEDIA question rather than a view-vocabulary one: GTK has Gtk.MediaFile and Gtk.MediaStream, and which package owns them is its own decision with its own measurement (ADR 0036, "What this does not decide").`},useAudioRecorder:{status:`planned`,tier:`P3`,reason:`Recording is GStreamer rather than GTK, and it is the same open decision as playback.`},AudioModule:{status:`planned`,tier:`P3`,reason:`The module surface behind the hooks. Same track.`},setAudioModeAsync:{status:`planned`,tier:`P3`,reason:`Session policy for a phone’s audio focus. Same track.`}},p={VideoView:{status:`planned`,tier:`P3`,gtk:`Gtk.Video`,reason:`GTK has the widget. Which package owns media is the open decision expo-audio names; it is not the view vocabulary’s.`},useVideoPlayer:{status:`planned`,tier:`P3`,gtk:`Gtk.MediaFile`,reason:`As VideoView.`},VideoContentFit:{status:`planned`,tier:`P3`,reason:`The fit constants; they land with the widget.`}},m={WebView:{status:`planned`,tier:`P3`,gtk:`WebKitGTK’s WebKit.WebView`,reason:`A real widget with a real answer, and its platform story is its own: WebKit’s availability differs per OS (ADR 0022) and it is the heaviest dependency any of these surfaces would add. It belongs to the webkit track.`},default:{status:`planned`,tier:`P3`,reason:`The default export is WebView; it has the same answer.`}},h={cssInterop:{status:`refused`,reason:"ADR 0032 § 12 already decided this surface: the class VOCABULARY is consumed and none of its toolchain is. `className` works on every primitive here with no runtime — resolving this would pull bindings to React Native’s StyleSheet, Appearance, Dimensions and PixelRatio into the critical path, which is the two-lossy-mappings-stacked shape that rules out react-native-web."},remapProps:{status:`refused`,reason:`As cssInterop.`},styled:{status:`refused`,reason:"As cssInterop. Write `className` on the primitive."},vars:{status:`refused`,reason:"CSS variables at runtime. GTK CSS has its own (`@define-color` and the Adwaita palette), and they are set through the application stylesheet rather than through a prop."},useColorScheme:{status:`refused`,reason:"Its own hook over React Native’s Appearance. `useColorScheme` from react-native is answered here and reads Adw.StyleManager:dark, which is what the user is actually looking at."}},g={default:{status:`refused`,reason:'The Expo config object — `expoConfig`, `appOwnership`, `executionEnvironment`, `manifest`, `sessionId`. A desktop application’s identity is its Gio.Application id and its metadata is its desktop entry; there is no manifest here to read, and a shape that answered with plausible nulls would be read as "not configured" rather than "does not apply".'},ExecutionEnvironment:{status:`refused`,reason:`Whether the app runs in Expo Go, a dev client or a standalone build. None of the three exists here.`},AppOwnership:{status:`refused`,reason:`As ExecutionEnvironment.`}},_={setBackgroundColorAsync:{status:`refused`,reason:`Paints the window’s root view behind React. On GTK that is the application stylesheet’s job and Adwaita already answers it per colour scheme — a per-call override would fight the theme and win only until the scheme changes.`},getBackgroundColorAsync:{status:`refused`,reason:`Reads back what setBackgroundColorAsync wrote. Nothing wrote it.`}},v={preventAutoHideAsync:{status:`refused`,reason:`Holds a native splash screen up while the app loads. A GTK application MAPS ITS WINDOW when it is ready, which is the desktop equivalent and is Gio.Application’s own job — the same refusal the router table gives expo-router’s SplashScreen.`},hideAsync:{status:`refused`,reason:`Hides a splash screen that was never shown.`},hide:{status:`refused`,reason:`The synchronous form, and it has the same answer.`},preventAutoHide:{status:`refused`,reason:`The synchronous form of preventAutoHideAsync.`},setOptions:{status:`refused`,reason:`Configures the fade of a screen that does not exist.`}},y=`@gjsify/react-native`,b=`is not a React Native export this layer knows about. If the installed react-native really exports it, the support table is out of date — run scripts/check-rn-surface.mjs, which compares the two.`,DECLARED_SURFACE=e=>`is not a name this layer's ${e} surface declares. That key set is DECLARED rather than read from an installed ${e} (it is not a dependency here), so a missing name means nobody has decided about it yet — open an issue naming it, or import the name from react-native if it has one there.`,x=[{module:`react-native`,target:y,label:`React Native`,declaration:`SUPPORT_TABLE`,table:t,unknown:b},{module:`expo-router`,target:`${y}/router`,label:`expo-router`,declaration:`ROUTER_SUPPORT_TABLE`,table:n,unknown:DECLARED_SURFACE(`expo-router`)},{module:`expo-status-bar`,target:`${y}/expo-status-bar`,label:`expo-status-bar`,declaration:`EXPO_STATUS_BAR_TABLE`,table:r,unknown:DECLARED_SURFACE(`expo-status-bar`)},{module:`expo-font`,target:`${y}/expo-font`,label:`expo-font`,declaration:`EXPO_FONT_TABLE`,table:i,unknown:DECLARED_SURFACE(`expo-font`)},{module:`expo-linking`,target:`${y}/expo-linking`,label:`expo-linking`,declaration:`EXPO_LINKING_TABLE`,table:a,unknown:DECLARED_SURFACE(`expo-linking`)},{module:`expo-web-browser`,target:`${y}/expo-web-browser`,label:`expo-web-browser`,declaration:`EXPO_WEB_BROWSER_TABLE`,table:o,unknown:DECLARED_SURFACE(`expo-web-browser`)},{module:`react-native-safe-area-context`,target:`${y}/react-native-safe-area-context`,label:`react-native-safe-area-context`,declaration:`SAFE_AREA_CONTEXT_TABLE`,table:s,unknown:DECLARED_SURFACE(`react-native-safe-area-context`)},{module:`react-native-gesture-handler`,target:`${y}/react-native-gesture-handler`,label:`react-native-gesture-handler`,declaration:`GESTURE_HANDLER_TABLE`,table:c,unknown:DECLARED_SURFACE(`react-native-gesture-handler`)},{module:`@react-native-async-storage/async-storage`,target:`${y}/async-storage`,label:`@react-native-async-storage/async-storage`,declaration:`ASYNC_STORAGE_TABLE`,table:l,unknown:DECLARED_SURFACE(`@react-native-async-storage/async-storage`)},{module:`@expo/vector-icons`,target:`${y}/vector-icons`,label:`@expo/vector-icons`,declaration:`VECTOR_ICONS_TABLE`,table:u,unknown:DECLARED_SURFACE(`@expo/vector-icons`)},{module:`expo-image`,target:`${y}/expo-image`,label:`expo-image`,declaration:`EXPO_IMAGE_TABLE`,table:d,unknown:DECLARED_SURFACE(`expo-image`)},{module:`expo-constants`,target:`${y}/expo-constants`,label:`expo-constants`,declaration:`EXPO_CONSTANTS_TABLE`,table:g,unknown:DECLARED_SURFACE(`expo-constants`)},{module:`expo-system-ui`,target:`${y}/expo-system-ui`,label:`expo-system-ui`,declaration:`EXPO_SYSTEM_UI_TABLE`,table:_,unknown:DECLARED_SURFACE(`expo-system-ui`)},{module:`expo-splash-screen`,target:`${y}/expo-splash-screen`,label:`expo-splash-screen`,declaration:`EXPO_SPLASH_SCREEN_TABLE`,table:v,unknown:DECLARED_SURFACE(`expo-splash-screen`)},{module:`expo-audio`,target:`${y}/expo-audio`,label:`expo-audio`,declaration:`EXPO_AUDIO_TABLE`,table:f,unknown:DECLARED_SURFACE(`expo-audio`)},{module:`expo-video`,target:`${y}/expo-video`,label:`expo-video`,declaration:`EXPO_VIDEO_TABLE`,table:p,unknown:DECLARED_SURFACE(`expo-video`)},{module:`react-native-webview`,target:`${y}/react-native-webview`,label:`react-native-webview`,declaration:`WEBVIEW_TABLE`,table:m,unknown:DECLARED_SURFACE(`react-native-webview`)},{module:`nativewind`,target:`${y}/nativewind`,label:`nativewind`,declaration:`NATIVEWIND_TABLE`,table:h,unknown:DECLARED_SURFACE(`nativewind`)}],S=Object.keys(t),C=Object.keys(n),w=new Set([`supported`,`partial`]),surfaceFor=e=>x.find(t=>t.module===e||t.target===e),lookup=(e,t)=>{if(t!==void 0){let n=surfaceFor(t);if(n===void 0)return;let r=n.table[e];return r===void 0?{surface:n}:{surface:n,entry:r}}for(let t of x){let n=t.table[e];if(n!==void 0)return{surface:t,entry:n}}},T=new Set(e),isOwnExport=e=>T.has(e),isImportable=(e,t)=>{let n=lookup(e,t);if(n?.entry!==void 0)return w.has(n.entry.status);if(t!==void 0){let t=n?.surface;return t===void 0?!1:t.target===y&&isOwnExport(e)}return isOwnExport(e)},specifiers=e=>`${e.module} → ${e.target}`;function explainUnsupported(e,t){let n=lookup(e,t);if(n===void 0)return t===void 0&&isOwnExport(e)?`${y}: "${e}" is this layer's own export rather than a React Native name, and it is available.`:t===void 0?`${y}: "${e}" ${b}`:`${y}: "${t}" is not a surface this layer declares, so it has nothing to say about "${e}". The declared surfaces are: ${x.map(e=>e.module).join(`, `)}.`;let{surface:r,entry:i}=n;if(i===void 0)return r.target===y&&isOwnExport(e)?`${y}: "${e}" is this layer's own export rather than a React Native name, and it is available.`:`${specifiers(r)}: "${e}" ${r.unknown}`;let a=specifiers(r),o=i.tier?` (tier ${i.tier})`:``,s=i.gtk?` The GTK counterpart is ${i.gtk}.`:``;switch(i.status){case`supported`:case`partial`:return`${a}: "${e}" is available.`;case`planned`:return`${a}: "${e}" is not implemented yet${o}. ${i.reason}${s}`;case`refused`:return`${a}: "${e}" will not be implemented. ${i.reason}`;case`no-desktop-meaning`:return`${a}: "${e}" has no meaning on a desktop window${o}. ${i.reason}`;case`not-reachable`:return`${a}: "${e}" cannot be implemented in this build chain. ${i.reason}`}}export{l as ASYNC_STORAGE_TABLE,f as EXPO_AUDIO_TABLE,g as EXPO_CONSTANTS_TABLE,i as EXPO_FONT_TABLE,d as EXPO_IMAGE_TABLE,a as EXPO_LINKING_TABLE,v as EXPO_SPLASH_SCREEN_TABLE,r as EXPO_STATUS_BAR_TABLE,_ as EXPO_SYSTEM_UI_TABLE,p as EXPO_VIDEO_TABLE,o as EXPO_WEB_BROWSER_TABLE,c as GESTURE_HANDLER_TABLE,h as NATIVEWIND_TABLE,e as OWN_EXPORT_NAMES,C as ROUTER_NAMES,n as ROUTER_SUPPORT_TABLE,s as SAFE_AREA_CONTEXT_TABLE,S as SUPPORTED_NAMES,t as SUPPORT_TABLE,x as SURFACES,u as VECTOR_ICONS_TABLE,m as WEBVIEW_TABLE,explainUnsupported,isImportable,isOwnExport,surfaceFor};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{PrimitiveError as e}from"../primitives/errors.js";import"../generated/unsupported-async-storage.js";import t from"gi://Gio?version=2.0";import n from"gi://GLib?version=2.0";const r=`async-storage.json`,i=new TextDecoder,a=new TextEncoder;let o=null,s=null;function storeFile(){if(s!==null)return s;let i=t.Application.get_default()?.applicationId??null;if(i===null||i===``)throw new e(`AsyncStorage`,`the store’s location`,"needs the application id, and there is no Gio.Application yet. `GLib.get_prgname()` would name the INTERPRETER, so the store would land in a directory called after gjs or node and a later run under the real application would find it empty. Build the application first — `registerRootComponent(App, { applicationId })` does — or read this from a component rather than at module scope");return s=t.File.new_for_path(n.build_filenamev([n.get_user_data_dir(),i,r])),s}function load(){if(o!==null)return o;let t=storeFile(),n=new Map,a=null;if(t.query_exists(null))try{let[,e]=t.load_contents(null);a=e}catch(n){throw new e(`AsyncStorage`,`reading ${t.get_path()??r}`,`failed: ${n instanceof Error?n.message:String(n)}. Starting from an empty store would look like a first launch, so this is loud instead`)}if(a!==null){let o=i.decode(a),s;try{s=JSON.parse(o)}catch(n){throw new e(`AsyncStorage`,`parsing ${t.get_path()??r}`,`failed: ${n instanceof Error?n.message:String(n)}. The file is not this store’s JSON any more. Move it aside to start over — deleting it silently is not this layer’s decision to make`)}if(typeof s!=`object`||!s||Array.isArray(s))throw new e(`AsyncStorage`,`reading ${t.get_path()??r}`,`found ${Array.isArray(s)?`an array`:typeof s} where this store keeps a JSON object of string values`);for(let[e,t]of Object.entries(s))typeof t==`string`&&n.set(e,t)}return o=n,n}function flush(){let n=storeFile(),r=n.get_parent();if(r!==null&&!r.query_exists(null))try{r.make_directory_with_parents(null)}catch(t){throw new e(`AsyncStorage`,`creating ${r.get_path()??`<data dir>`}`,`failed: ${t instanceof Error?t.message:String(t)}`)}let i={};for(let[e,t]of load())i[e]=t;n.replace_contents(a.encode(JSON.stringify(i,null,2)),null,!1,t.FileCreateFlags.REPLACE_DESTINATION,null)}const requireKey=(t,n)=>{if(typeof n!=`string`)throw new e(`AsyncStorage`,t,`takes a string key, and received ${typeof n}`);return n},requireValue=(t,n)=>{if(typeof n!=`string`)throw new e(`AsyncStorage`,t,`takes a string value — AsyncStorage stores strings, which is upstream’s own contract — and received ${typeof n}. Use JSON.stringify`);return n},c={async getItem(e){return load().get(requireKey(`getItem`,e))??null},async setItem(e,t){load().set(requireKey(`setItem`,e),requireValue(`setItem`,t)),flush()},async removeItem(e){load().delete(requireKey(`removeItem`,e)),flush()},async mergeItem(e,t){let n=requireKey(`mergeItem`,e),r=parseObject(`mergeItem`,requireValue(`mergeItem`,t)),i=load().get(n),a=i===void 0?r:{...parseObject(`mergeItem`,i),...r};load().set(n,JSON.stringify(a)),flush()},async clear(){load().clear(),flush()},async getAllKeys(){return[...load().keys()]},async multiGet(e){let t=load();return e.map(e=>[requireKey(`multiGet`,e),t.get(e)??null])},async multiSet(e){let t=load();for(let[n,r]of e)t.set(requireKey(`multiSet`,n),requireValue(`multiSet`,r));flush()},async multiRemove(e){let t=load();for(let n of e)t.delete(requireKey(`multiRemove`,n));flush()},async multiMerge(e){let t=load();for(let[n,r]of e){let e=requireKey(`multiMerge`,n),i=parseObject(`multiMerge`,requireValue(`multiMerge`,r)),a=t.get(e),o=a===void 0?i:{...parseObject(`multiMerge`,a),...i};t.set(e,JSON.stringify(o))}flush()},async flushGetRequests(){}};function parseObject(t,n){let r;try{r=JSON.parse(n)}catch(n){throw new e(`AsyncStorage`,t,`needs both sides to be JSON objects, and one of them does not parse: ${n instanceof Error?n.message:String(n)}`)}if(typeof r!=`object`||!r||Array.isArray(r))throw new e(`AsyncStorage`,t,`merges JSON OBJECTS, and found ${Array.isArray(r)?`an array`:typeof r}. Overwriting instead would be silent data loss`);return r}function useAsyncStorage(e){return{getItem:()=>c.getItem(e),setItem:t=>c.setItem(e,t),mergeItem:t=>c.mergeItem(e,t),removeItem:()=>c.removeItem(e)}}const resetAsyncStorage=()=>{o=null,s=null},useStoreFile=e=>{s=t.File.new_for_path(e),o=null};export{c as AsyncStorage,c as default,resetAsyncStorage,useAsyncStorage,useStoreFile};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{AudioModule as e,setAudioModeAsync as t,useAudioPlayer as n,useAudioRecorder as r}from"../generated/unsupported-expo-audio.js";export{e as AudioModule,t as setAudioModeAsync,n as useAudioPlayer,r as useAudioRecorder};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{unsupported as e}from"../unsupported.js";import{AppOwnership as t,ExecutionEnvironment as n}from"../generated/unsupported-expo-constants.js";var r=e(`default`,`expo-constants`);export{t as AppOwnership,n as ExecutionEnvironment,r as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{FontDisplay as e,loadAsync as t,unloadAllAsync as n,unloadAsync as r}from"../generated/unsupported-expo-font.js";import i from"gi://PangoCairo?version=1.0";let a=null;const knownFamilies=()=>{if(a!==null)return a;let e=new Set;for(let t of i.FontMap.get_default().list_families())e.add(t.get_name().toLowerCase());return a=e,e},resetFontCache=()=>{a=null};function isLoaded(e){return knownFamilies().has(e.toLowerCase())}function isLoading(){return!1}function useFonts(e){return[!0,null]}export{e as FontDisplay,isLoaded,isLoading,t as loadAsync,resetFontCache,n as unloadAllAsync,r as unloadAsync,useFonts};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Image as e,ImageBackground as t,useImage as n}from"../generated/unsupported-expo-image.js";export{e as Image,t as ImageBackground,n as useImage};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{Linking as e}from"../apis/linking.js";import"../apis/index.js";import{addEventListener as t,createURL as n,openSettings as r,sendIntent as i}from"../generated/unsupported-expo-linking.js";const openURL=t=>e.openURL(t),canOpenURL=t=>e.canOpenURL(t),getInitialURL=()=>e.getInitialURL();function useURL(){return null}function parse(e){let t;try{t=new URL(e)}catch{return{scheme:null,hostname:null,path:null,queryParams:null}}let n={},r=!1;for(let[e,i]of t.searchParams)n[e]=i,r=!0;return{scheme:t.protocol===``?null:t.protocol.replace(/:$/,``),hostname:t.hostname===``?null:t.hostname,path:t.pathname===``?null:t.pathname.replace(/^\//,``),queryParams:r?n:null}}export{t as addEventListener,canOpenURL,n as createURL,getInitialURL,r as openSettings,openURL,parse,i as sendIntent,useURL};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{hide as e,hideAsync as t,preventAutoHide as n,preventAutoHideAsync as r,setOptions as i}from"../generated/unsupported-expo-splash-screen.js";export{e as hide,t as hideAsync,n as preventAutoHide,r as preventAutoHideAsync,i as setOptions};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{StatusBar as e}from"../components.js";import{setStatusBarBackgroundColor as t,setStatusBarHidden as n,setStatusBarNetworkActivityIndicatorVisible as r,setStatusBarStyle as i,setStatusBarTranslucent as a}from"../generated/unsupported-expo-status-bar.js";const o=e;export{o as StatusBar,t as setStatusBarBackgroundColor,n as setStatusBarHidden,r as setStatusBarNetworkActivityIndicatorVisible,i as setStatusBarStyle,a as setStatusBarTranslucent};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getBackgroundColorAsync as e,setBackgroundColorAsync as t}from"../generated/unsupported-expo-system-ui.js";export{e as getBackgroundColorAsync,t as setBackgroundColorAsync};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{VideoContentFit as e,VideoView as t,useVideoPlayer as n}from"../generated/unsupported-expo-video.js";export{e as VideoContentFit,t as VideoView,n as useVideoPlayer};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{Linking as e}from"../apis/linking.js";import"../apis/index.js";import{coolDownAsync as t,dismissAuthSession as n,dismissBrowser as r,maybeCompleteAuthSession as i,openAuthSessionAsync as a,warmUpAsync as o}from"../generated/unsupported-expo-web-browser.js";const s={cancel:`cancel`,dismiss:`dismiss`,opened:`opened`,locked:`locked`};async function openBrowserAsync(t,n){return await e.openURL(t),{type:s.opened}}export{s as WebBrowserResultType,t as coolDownAsync,n as dismissAuthSession,r as dismissBrowser,i as maybeCompleteAuthSession,a as openAuthSessionAsync,openBrowserAsync,o as warmUpAsync};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{PrimitiveError as e}from"../primitives/errors.js";const t={home:`go-home-symbolic`,search:`system-search-symbolic`,settings:`emblem-system-symbolic`,"settings-outline":`preferences-system-symbolic`,close:`window-close-symbolic`,"close-circle":`process-stop-symbolic`,"chevron-forward":`go-next-symbolic`,"chevron-back":`go-previous-symbolic`,"chevron-up":`go-up-symbolic`,"chevron-down":`go-down-symbolic`,"caret-down":`pan-down-symbolic`,"caret-up":`pan-up-symbolic`,"caret-forward":`pan-end-symbolic`,"caret-back":`pan-start-symbolic`,"arrow-forward":`go-next-symbolic`,"arrow-back":`go-previous-symbolic`,"arrow-up":`go-up-symbolic`,"arrow-down":`go-down-symbolic`,add:`list-add-symbolic`,remove:`list-remove-symbolic`,play:`media-playback-start-symbolic`,pause:`media-playback-pause-symbolic`,stop:`media-playback-stop-symbolic`,"play-skip-forward":`media-skip-forward-symbolic`,"play-skip-back":`media-skip-backward-symbolic`,"play-forward":`media-seek-forward-symbolic`,"play-back":`media-seek-backward-symbolic`,heart:`emote-love-symbolic`,star:`starred-symbolic`,"star-outline":`non-starred-symbolic`,"share-outline":`send-to-symbolic`,trash:`user-trash-symbolic`,"trash-outline":`user-trash-symbolic`,checkmark:`object-select-symbolic`,"checkmark-circle":`object-select-symbolic`,"information-circle":`dialog-information-symbolic`,"help-circle":`help-about-symbolic`,warning:`dialog-warning-symbolic`,alert:`dialog-warning-symbolic`,menu:`open-menu-symbolic`,person:`avatar-default-symbolic`,"person-circle":`avatar-default-symbolic`,people:`system-users-symbolic`,mail:`mail-unread-symbolic`,"mail-outline":`mail-unread-symbolic`,send:`mail-send-symbolic`,calendar:`x-office-calendar-symbolic`,"document-text":`x-office-document-symbolic`,document:`text-x-generic-symbolic`,image:`image-x-generic-symbolic`,camera:`camera-photo-symbolic`,videocam:`camera-video-symbolic`,mic:`audio-input-microphone-symbolic`,"mic-off":`microphone-sensitivity-muted-symbolic`,"volume-high":`audio-volume-high-symbolic`,"volume-medium":`audio-volume-medium-symbolic`,"volume-low":`audio-volume-low-symbolic`,"volume-mute":`audio-volume-muted-symbolic`,refresh:`view-refresh-symbolic`,sync:`view-refresh-symbolic`,download:`folder-download-symbolic`,"cloud-download":`folder-download-symbolic`,"cloud-upload":`send-to-symbolic`,link:`insert-link-symbolic`,"lock-closed":`changes-prevent-symbolic`,"lock-open":`changes-allow-symbolic`,eye:`view-reveal-symbolic`,"eye-off":`view-conceal-symbolic`,list:`view-list-symbolic`,grid:`view-grid-symbolic`,notifications:`preferences-system-notifications-symbolic`,bookmark:`user-bookmarks-symbolic`,"ellipsis-horizontal":`view-more-symbolic`,"ellipsis-vertical":`view-more-symbolic`,time:`preferences-system-time-symbolic`,globe:`network-workgroup-symbolic`,earth:`network-workgroup-symbolic`,location:`mark-location-symbolic`,navigate:`find-location-symbolic`,call:`call-start-symbolic`,chatbubble:`user-available-symbolic`,"log-out":`system-log-out-symbolic`,"log-in":`system-users-symbolic`,expand:`view-fullscreen-symbolic`,contract:`view-restore-symbolic`,sunny:`weather-clear-symbolic`,moon:`weather-clear-night-symbolic`,wifi:`network-wireless-signal-excellent-symbolic`,"battery-full":`battery-full-symbolic`,print:`printer-symbolic`,open:`document-open-symbolic`,pencil:`document-edit-symbolic`,copy:`edit-copy-symbolic`,save:`document-save-symbolic`,folder:`folder-symbolic`,"folder-open":`folder-open-symbolic`,"musical-notes":`audio-x-generic-symbolic`,headset:`audio-headphones-symbolic`,film:`video-x-generic-symbolic`,"swap-vertical":`view-sort-descending-symbolic`,terminal:`utilities-terminal-symbolic`,"radio-button-on":`radio-checked-symbolic`,"radio-button-off":`radio-symbolic`,square:`checkbox-symbolic`,"checkbox-outline":`checkbox-symbolic`,options:`view-more-horizontal-symbolic`,"color-palette":`preferences-desktop-appearance-symbolic`,power:`system-shutdown-symbolic`,ban:`action-unavailable-symbolic`,exit:`system-log-out-symbolic`},n=Object.keys(t),r=[...new Set(Object.values(t))];function ioniconName(r){if(typeof r!=`string`)throw new e(`Ionicons`,`name`,`takes an Ionicons name, and received ${r===null?`null`:typeof r}`);let i=t[r];if(i!==void 0)return i;throw new e(`Ionicons`,`name="${r}"`,`has no icon in the theme’s vocabulary. A GTK icon is addressed by NAME and GTK draws \`image-missing\` for one it does not have, silently — so an unmapped name is a refusal rather than a glyph nobody notices. Mapped: ${n.join(`, `)}. Add a row to \`surfaces/icon-map.ts\` if the theme has a counterpart, or render \`<Icon name="…-symbolic">\` with the theme’s own name`)}export{t as IONICONS,n as IONICONS_NAMES,r as IONICONS_TARGETS,ioniconName};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cssInterop as e,remapProps as t,styled as n,useColorScheme as r,vars as i}from"../generated/unsupported-nativewind.js";export{e as cssInterop,t as remapProps,n as styled,r as useColorScheme,i as vars};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{View as e}from"../components.js";import{Directions as t,Gesture as n,GestureDetector as r,LongPressGestureHandler as i,PanGestureHandler as a,PinchGestureHandler as o,ScrollView as s,State as c,Swipeable as l,TapGestureHandler as u}from"../generated/unsupported-react-native-gesture-handler.js";import{createElement as d}from"react";function GestureHandlerRootView(t){return d(e,t)}export{t as Directions,n as Gesture,r as GestureDetector,GestureHandlerRootView,i as LongPressGestureHandler,a as PanGestureHandler,o as PinchGestureHandler,s as ScrollView,c as State,l as Swipeable,u as TapGestureHandler};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{SafeAreaView as e,View as t}from"../components.js";import{SafeAreaConsumer as n,SafeAreaFrameContext as r,SafeAreaInsetsContext as i,withSafeAreaInsets as a}from"../generated/unsupported-react-native-safe-area-context.js";import{useWindowDimensions as o}from"../hooks.js";import{createElement as s}from"react";const c={top:0,right:0,bottom:0,left:0},l=e;function SafeAreaProvider({initialMetrics:e,...n}){return s(t,n)}function useSafeAreaInsets(){return c}function useSafeAreaFrame(){let e=o();return{x:0,y:0,width:e.width,height:e.height}}const u={insets:c,frame:{x:0,y:0,width:0,height:0}};export{n as SafeAreaConsumer,r as SafeAreaFrameContext,i as SafeAreaInsetsContext,SafeAreaProvider,l as SafeAreaView,u as initialWindowMetrics,useSafeAreaFrame,useSafeAreaInsets,a as withSafeAreaInsets};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{unsupported as e}from"../unsupported.js";import{WebView as t}from"../generated/unsupported-react-native-webview.js";var n=e(`default`,`react-native-webview`);export{t as WebView,n as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{Icon as e}from"../components.js";import{AntDesign as t,Entypo as n,Feather as r,FontAwesome as i,MaterialCommunityIcons as a,MaterialIcons as o,Octicons as s,SimpleLineIcons as c,createIconSet as l,createIconSetFromFontello as u,createIconSetFromIcoMoon as d}from"../generated/unsupported-vector-icons.js";import{ioniconName as f}from"./icon-map.js";import{createElement as p}from"react";function Ionicons({name:t,...n}){return p(e,{...n,name:f(t)})}export{t as AntDesign,n as Entypo,r as Feather,i as FontAwesome,Ionicons,a as MaterialCommunityIcons,o as MaterialIcons,s as Octicons,c as SimpleLineIcons,l as createIconSet,u as createIconSetFromFontello,d as createIconSetFromIcoMoon};
|
package/lib/esm/unsupported.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{explainUnsupported as e}from"./support-table.js";var UnsupportedError=class extends Error{constructor(t){super(e(t)),this.name=`UnsupportedError`,this.export=t}};function unsupported(e){let refuse=()=>{throw new UnsupportedError(e)};function constructible(){return refuse()}return new Proxy(constructible,{apply:refuse,construct:refuse,get(
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{explainUnsupported as e}from"./support-table.js";var UnsupportedError=class extends Error{constructor(t,n){super(e(t,n)),this.name=`UnsupportedError`,this.export=t,this.module=n}};function unsupported(e,t){let refuse=()=>{throw new UnsupportedError(e,t)};function constructible(){return refuse()}return new Proxy(constructible,{apply:refuse,construct:refuse,get(n,r){if(r===`name`||r===`displayName`||r===Symbol.toStringTag)return e;if(r!==`$$typeof`&&r!==`then`){if(r===`prototype`)return Reflect.get(n,r);throw new UnsupportedError(e,t)}},set(){throw new UnsupportedError(e,t)}})}export{UnsupportedError,unsupported};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `max-length` → `maxLength`: the spelling GJS installs the JS accessor under.
|
|
3
|
+
*
|
|
4
|
+
* Its own module because THREE things need it and two of them may not import the
|
|
5
|
+
* third: the React components read an event's `read` property off a widget,
|
|
6
|
+
* `announce.ts` reads a live region's message off one, and neither may pull the
|
|
7
|
+
* other's dependencies — `announce.ts` must stay free of React so the Solid binding
|
|
8
|
+
* can use it, and `components.ts` is React by definition.
|
|
9
|
+
*/
|
|
10
|
+
export declare const accessor: (name: string) => string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** The brand key. On the class, and read by L2 without importing it. */
|
|
2
|
+
export declare const ANIMATED_VALUE: unique symbol;
|
|
3
|
+
/** The shape a brand reader can rely on. `AnimatedValue` implements it. */
|
|
4
|
+
export interface AnimatedValueLike {
|
|
5
|
+
readonly [ANIMATED_VALUE]: true;
|
|
6
|
+
}
|
|
7
|
+
/** Is this an `Animated.Value`? */
|
|
8
|
+
export declare function isAnimatedValue(candidate: unknown): candidate is AnimatedValueLike;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import Adw from 'gi://Adw?version=1';
|
|
2
|
+
/** React Native's easing shape: progress in, progress out. */
|
|
3
|
+
export type EasingFunction = (t: number) => number;
|
|
4
|
+
/** The three directions React Native's combinators produce. */
|
|
5
|
+
export type EasingDirection = 'in' | 'out' | 'inOut';
|
|
6
|
+
/**
|
|
7
|
+
* One `AdwEasing` member name.
|
|
8
|
+
*
|
|
9
|
+
* `$gtype` is excluded because `@girs`' enum object carries it alongside the 35
|
|
10
|
+
* members, so a bare `keyof` makes every indexed read `Easing | GType<Easing>`.
|
|
11
|
+
*/
|
|
12
|
+
export type AdwEasingName = Exclude<keyof typeof Adw.Easing, '$gtype'>;
|
|
13
|
+
/** `Adw.Easing[name]`, narrowed past the `$gtype` key the type above excludes. */
|
|
14
|
+
export declare const adwEasing: (name: AdwEasingName) => Adw.Easing;
|
|
15
|
+
/**
|
|
16
|
+
* A family's three directions, `null` where `AdwEasing` has no matching curve.
|
|
17
|
+
*
|
|
18
|
+
* `null` is a REFUSAL and not "use the nearest": the deviations for the three holes
|
|
19
|
+
* are 1.20e-2, 6.62e-2 and 4.06e-1, and a styling layer that silently substituted
|
|
20
|
+
* the last one would animate a bounce as something else entirely.
|
|
21
|
+
*/
|
|
22
|
+
interface FamilyTriple {
|
|
23
|
+
readonly in: AdwEasingName | null;
|
|
24
|
+
readonly out: AdwEasingName | null;
|
|
25
|
+
readonly inOut: AdwEasingName | null;
|
|
26
|
+
/** What the refusal says when a direction is `null`. */
|
|
27
|
+
readonly hole: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The `AdwEasing` member a token names, or a refusal.
|
|
31
|
+
*
|
|
32
|
+
* `timing.ts`'s only entry point into this module. A function this module did not
|
|
33
|
+
* mint is refused BY NAME rather than sampled: sampling a caller's closure to guess
|
|
34
|
+
* which of the 35 members it resembles is exactly the approximation the table above
|
|
35
|
+
* exists to avoid, and it would silently pick a curve for a `bezier` nobody can
|
|
36
|
+
* express.
|
|
37
|
+
*/
|
|
38
|
+
export declare function easingMember(easing: unknown, subject: string): AdwEasingName;
|
|
39
|
+
/**
|
|
40
|
+
* React Native's `Easing`, as far as `AdwEasing` can answer for it.
|
|
41
|
+
*
|
|
42
|
+
* `in` is React Native's own identity (`in(easing) { return easing; }`), so it is
|
|
43
|
+
* spelled that way here too and a token keeps its family through it.
|
|
44
|
+
*/
|
|
45
|
+
export declare const Easing: {
|
|
46
|
+
readonly linear: EasingFunction;
|
|
47
|
+
readonly ease: EasingFunction;
|
|
48
|
+
readonly quad: EasingFunction;
|
|
49
|
+
readonly cubic: EasingFunction;
|
|
50
|
+
readonly sin: EasingFunction;
|
|
51
|
+
readonly circle: EasingFunction;
|
|
52
|
+
readonly exp: EasingFunction;
|
|
53
|
+
readonly bounce: EasingFunction;
|
|
54
|
+
/** `poly(2)` is `quad`, `poly(3)` is `cubic`; AdwEasing stops at quint. */
|
|
55
|
+
readonly poly: (n: number) => EasingFunction;
|
|
56
|
+
/** The DEFAULT overshoot only: AdwEasing's back curve has a fixed one. */
|
|
57
|
+
readonly back: (s?: number) => EasingFunction;
|
|
58
|
+
readonly elastic: (bounciness?: number) => EasingFunction;
|
|
59
|
+
readonly bezier: (x1: number, y1: number, x2: number, y2: number) => EasingFunction;
|
|
60
|
+
readonly step0: (_n: number) => number;
|
|
61
|
+
readonly step1: (_n: number) => number;
|
|
62
|
+
readonly in: (easing: EasingFunction) => EasingFunction;
|
|
63
|
+
readonly out: (easing: EasingFunction) => EasingFunction;
|
|
64
|
+
readonly inOut: (easing: EasingFunction) => EasingFunction;
|
|
65
|
+
};
|
|
66
|
+
/** The family names this module mints tokens for. Read by `easing.spec.ts`. */
|
|
67
|
+
export declare const EASING_FAMILIES: readonly string[];
|
|
68
|
+
/** One family's measured triple, for the spec that re-derives it. */
|
|
69
|
+
export declare const easingTriple: (name: string) => FamilyTriple | undefined;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { AnimatedView } from '../components.js';
|
|
2
|
+
import { timing } from './timing.js';
|
|
3
|
+
import { AnimatedValue } from './value.js';
|
|
4
|
+
export { Easing } from './easing.js';
|
|
5
|
+
export type { AdwEasingName, EasingDirection, EasingFunction } from './easing.js';
|
|
6
|
+
export { timing } from './timing.js';
|
|
7
|
+
export type { CompositeAnimation, EndCallback, TimingConfig } from './timing.js';
|
|
8
|
+
export { AnimatedValue } from './value.js';
|
|
9
|
+
export type { ValueRun, ValueSink } from './value.js';
|
|
10
|
+
export { ANIMATED_VALUE, isAnimatedValue } from './brand.js';
|
|
11
|
+
export type { AnimatedValueLike } from './brand.js';
|
|
12
|
+
export { ANIMATED_PROPERTIES } from './properties.js';
|
|
13
|
+
export type { AnimatedPropertySpec } from './properties.js';
|
|
14
|
+
/**
|
|
15
|
+
* React Native's `Animated`, as far as this layer answers for it.
|
|
16
|
+
*
|
|
17
|
+
* A plain object and not a class, which is what React Native's own is
|
|
18
|
+
* (`AnimatedExports.js` spreads `AnimatedImplementation` into an object literal).
|
|
19
|
+
*/
|
|
20
|
+
export declare const Animated: {
|
|
21
|
+
/** The number. `value.ts` holds the design and why the VALUE is the source of truth. */
|
|
22
|
+
readonly Value: typeof AnimatedValue;
|
|
23
|
+
/** One number to another over a duration. */
|
|
24
|
+
readonly timing: typeof timing;
|
|
25
|
+
/** A `View` whose animated style entries drive widget properties instead of re-rendering. */
|
|
26
|
+
readonly View: typeof AnimatedView;
|
|
27
|
+
readonly Text: (...args: unknown[]) => never;
|
|
28
|
+
readonly Image: (...args: unknown[]) => never;
|
|
29
|
+
readonly ScrollView: (...args: unknown[]) => never;
|
|
30
|
+
readonly FlatList: (...args: unknown[]) => never;
|
|
31
|
+
readonly SectionList: (...args: unknown[]) => never;
|
|
32
|
+
readonly createAnimatedComponent: (...args: unknown[]) => never;
|
|
33
|
+
readonly ValueXY: (...args: unknown[]) => never;
|
|
34
|
+
readonly Color: (...args: unknown[]) => never;
|
|
35
|
+
readonly Interpolation: (...args: unknown[]) => never;
|
|
36
|
+
readonly Node: (...args: unknown[]) => never;
|
|
37
|
+
readonly add: (...args: unknown[]) => never;
|
|
38
|
+
readonly subtract: (...args: unknown[]) => never;
|
|
39
|
+
readonly divide: (...args: unknown[]) => never;
|
|
40
|
+
readonly multiply: (...args: unknown[]) => never;
|
|
41
|
+
readonly modulo: (...args: unknown[]) => never;
|
|
42
|
+
readonly diffClamp: (...args: unknown[]) => never;
|
|
43
|
+
readonly spring: (...args: unknown[]) => never;
|
|
44
|
+
readonly decay: (...args: unknown[]) => never;
|
|
45
|
+
readonly sequence: (...args: unknown[]) => never;
|
|
46
|
+
readonly parallel: (...args: unknown[]) => never;
|
|
47
|
+
readonly stagger: (...args: unknown[]) => never;
|
|
48
|
+
readonly loop: (...args: unknown[]) => never;
|
|
49
|
+
readonly delay: (...args: unknown[]) => never;
|
|
50
|
+
readonly event: (...args: unknown[]) => never;
|
|
51
|
+
readonly Event: (...args: unknown[]) => never;
|
|
52
|
+
readonly attachNativeEvent: (...args: unknown[]) => never;
|
|
53
|
+
readonly forkEvent: (...args: unknown[]) => never;
|
|
54
|
+
readonly unforkEvent: (...args: unknown[]) => never;
|
|
55
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { StyleTokens } from '@gjsify/gtk-host/style';
|
|
2
|
+
import { type StyleAuthored } from '../primitives/style.js';
|
|
3
|
+
/** One animatable style key. */
|
|
4
|
+
export interface AnimatedPropertySpec {
|
|
5
|
+
/** The GTK widget property the number is written to, in GTK's kebab spelling. */
|
|
6
|
+
readonly property: string;
|
|
7
|
+
/** The GTK CSS property the STATIC form of this key becomes, for the clash check. */
|
|
8
|
+
readonly css: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The style keys `Animated.View` answers for.
|
|
12
|
+
*
|
|
13
|
+
* `opacity` is a `gdouble` on `Gtk.Widget` and therefore on every widget a primitive
|
|
14
|
+
* can become — measured: `GtkBox` installs 41 properties, `opacity` among them, and
|
|
15
|
+
* `GtkOverlay` has it too, so the `View` overlay switch does not change the answer.
|
|
16
|
+
*/
|
|
17
|
+
export declare const ANIMATED_PROPERTIES: Readonly<Record<string, AnimatedPropertySpec>>;
|
|
18
|
+
/** The animatable key `key` names, or a named refusal. */
|
|
19
|
+
export declare function animatedProperty(primitive: string, key: string): AnimatedPropertySpec;
|
|
20
|
+
/**
|
|
21
|
+
* Refuse when the element also AUTHORS one of the properties it animates.
|
|
22
|
+
*
|
|
23
|
+
* `authored` is the PLAIN half — the style with the animated entries already taken
|
|
24
|
+
* out — because `normalise` refuses a style value that is not a string or a number,
|
|
25
|
+
* which is exactly what an `Animated.Value` is.
|
|
26
|
+
*
|
|
27
|
+
* The check runs the real partition rather than looking for the literal utility, for
|
|
28
|
+
* the reason `declaresAbsolute` does: `opacity` reaches GTK CSS from a class
|
|
29
|
+
* (`opacity-70`), from a style object (`style={{ opacity: 0.7 }}`) and from a variant
|
|
30
|
+
* (`active:opacity-70`), and a syntactic test would be exact only while that stays
|
|
31
|
+
* three spellings.
|
|
32
|
+
*/
|
|
33
|
+
export declare function assertNoStaticClash(primitive: string, authored: StyleAuthored, animatedKeys: readonly string[], tokens: StyleTokens): void;
|