@gjsify/react-native 0.47.0 → 0.49.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 +319 -92
- package/README.md +112 -0
- package/SUPPORT.md +14 -9
- package/lib/esm/accessibility.js +1 -0
- package/lib/esm/apis/alert.js +1 -1
- package/lib/esm/app-registry.js +1 -1
- package/lib/esm/child-facts.js +1 -0
- package/lib/esm/components.js +1 -1
- package/lib/esm/generated/own-exports.js +1 -1
- package/lib/esm/generated/unsupported-react-native.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/lists/controller.js +1 -1
- package/lib/esm/primitives/accessibility.js +1 -0
- package/lib/esm/primitives/answers.js +1 -1
- package/lib/esm/primitives/defaults.js +1 -1
- package/lib/esm/primitives/errors.js +1 -1
- package/lib/esm/primitives/index.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 -1
- package/lib/esm/router/chrome.js +1 -0
- package/lib/esm/router/navigation.js +1 -1
- package/lib/esm/router/per-route-cache.js +1 -0
- package/lib/esm/router/stack.js +1 -1
- package/lib/esm/router/tabs.js +1 -1
- package/lib/esm/solid/index.js +1 -1
- package/lib/esm/support-table.js +1 -1
- package/lib/esm/window-chrome.js +1 -0
- package/lib/types/accessibility.d.ts +10 -0
- package/lib/types/app-registry.d.ts +95 -5
- package/lib/types/app-registry.spec.d.ts +2 -0
- package/lib/types/child-facts.d.ts +45 -0
- package/lib/types/child-facts.spec.d.ts +2 -0
- package/lib/types/components.d.ts +43 -1
- package/lib/types/generated/unsupported-react-native.d.ts +8 -4
- package/lib/types/index.d.ts +3 -3
- package/lib/types/primitives/accessibility.d.ts +112 -0
- package/lib/types/primitives/answers.d.ts +18 -0
- package/lib/types/primitives/errors.d.ts +9 -0
- package/lib/types/primitives/resolve.d.ts +10 -0
- package/lib/types/primitives/style.d.ts +23 -0
- package/lib/types/primitives/table.d.ts +13 -1
- package/lib/types/primitives/text-metrics.spec.d.ts +2 -0
- package/lib/types/prop-table.d.ts +29 -0
- package/lib/types/router/chrome.d.ts +106 -0
- package/lib/types/router/errors.d.ts +3 -1
- package/lib/types/router/per-route-cache.d.ts +21 -0
- package/lib/types/router/stack.d.ts +6 -1
- package/lib/types/router/tabs.d.ts +47 -2
- package/lib/types/solid/index.d.ts +2 -1
- package/lib/types/support-table.d.ts +1 -1
- package/lib/types/window-chrome.d.ts +39 -0
- package/package.json +7 -7
- package/react-native-surface.json +18 -9
package/README.md
CHANGED
|
@@ -32,6 +32,24 @@ a real `react-native` install when one is resolvable — and it prints which of
|
|
|
32
32
|
it did, because a gate that silently degrades to the weaker half is worse than one
|
|
33
33
|
that has only the weaker half.
|
|
34
34
|
|
|
35
|
+
### The names this layer ADDS are DERIVED, not table rows
|
|
36
|
+
|
|
37
|
+
The support table answers for *React Native's* names. The ones this layer adds on top —
|
|
38
|
+
`configureStyle`, `primitives`, the table's own readers — may not be table keys at all, and
|
|
39
|
+
the gate refused the package's own API until they had a home. They do: `src/generated/own-exports.ts`,
|
|
40
|
+
derived from `src/index.ts` rather than hand-listed.
|
|
41
|
+
|
|
42
|
+
An unimplemented name is a generated **refusing export**, never an absent one. The difference is
|
|
43
|
+
the diagnostic: `MISSING_EXPORT` says the name is unknown, whereas the table says it is P2 over
|
|
44
|
+
`Gtk.ListView`. Read the TABLE for any question about coverage — a list written into prose drifted
|
|
45
|
+
once already, omitting the whole list family, the bindings and routing.
|
|
46
|
+
|
|
47
|
+
Two constraints fall out of the generator and are easy to trip:
|
|
48
|
+
|
|
49
|
+
- **`src/primitives/table.ts` and `src/primitives/answers.ts` may hold NO relative value import.**
|
|
50
|
+
The generator imports them under Node's type stripping, and Node does not rewrite `./x.js` to `./x.ts`.
|
|
51
|
+
- **A new `ref` handle is a table row**, never something a binding assembles.
|
|
52
|
+
|
|
35
53
|
## The PROP surface is a contract too, and it is published
|
|
36
54
|
|
|
37
55
|
The support table answers "may this application import this name". One grain finer
|
|
@@ -86,6 +104,40 @@ Native: `AppRegistry.runApplication` there is handed a root tag by a host that
|
|
|
86
104
|
already exists, while on a desktop **the application is the host**. That limit is in
|
|
87
105
|
the table rather than only here.
|
|
88
106
|
|
|
107
|
+
Because the application is the host, this layer hands it back (ADR 0043). Two shapes,
|
|
108
|
+
split by question:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
// 1. Anything that has to happen at a lifecycle moment travels as an option — the
|
|
112
|
+
// whole option set of `@gjsify/adwaita-app` is available here, `createWindow`
|
|
113
|
+
// excepted, because that is what renders your component.
|
|
114
|
+
await registerRootComponent(App, {
|
|
115
|
+
applicationId: 'org.example.App',
|
|
116
|
+
devtools: true, // or { extend, address, instance } — see @gjsify/devtools
|
|
117
|
+
onStartup: (app) => app.set_accels_for_action('app.quit', ['<primary>q']),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// 2. "Which application am I in" is an accessor, readable from anywhere in the tree.
|
|
121
|
+
// Both answer from the first render onwards — before the window maps — and `null`
|
|
122
|
+
// outside the loop.
|
|
123
|
+
AppRegistry.getApplication(); // Adw.Application | null
|
|
124
|
+
AppRegistry.getWindow(); // Gtk.Window | null
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Those two, and deliberately not the React root or the container widget it renders
|
|
128
|
+
into. Both of those are the bootstrap's own working state — a `render()` from
|
|
129
|
+
outside replaces the tree this layer mounted, an `unmount()` leaves `getWindow()`
|
|
130
|
+
answering with a window whose content is gone — and an accessor that can be put
|
|
131
|
+
into a lying state is worse than one that does not exist. Adding one later is
|
|
132
|
+
additive; removing one from a published API is not.
|
|
133
|
+
|
|
134
|
+
`devtools` is the one worth knowing about: with it (or `GJSIFY_DEVTOOLS=1`) the running
|
|
135
|
+
application answers `DumpTree`, `GetProperty`, `FindWidget`, `ActivateWidget`, `SendKey`
|
|
136
|
+
and `Screenshot` over DBus, so its screens can be driven and photographed by something
|
|
137
|
+
other than itself. On macOS and Windows there is no session bus, and `devtools.address`
|
|
138
|
+
is how the bus-less peer transport gets pinned — which is the reason the option set is
|
|
139
|
+
forwarded whole rather than field by field.
|
|
140
|
+
|
|
89
141
|
## Three layers, and where each one lives
|
|
90
142
|
|
|
91
143
|
| layer | where | knows about |
|
|
@@ -97,6 +149,34 @@ the table rather than only here.
|
|
|
97
149
|
L2 is exported (`import { primitives } from '@gjsify/react-native'`) so any binding
|
|
98
150
|
can render the same vocabulary without going through the React components.
|
|
99
151
|
|
|
152
|
+
### What a parent asks about its children, and what stays transparent
|
|
153
|
+
|
|
154
|
+
A few decisions cannot be taken by the element that authored them. `position: absolute`
|
|
155
|
+
is the clearest: it positions the element on top of its parent, so the **parent** has
|
|
156
|
+
to be a `Gtk.Overlay` — and a `View` becomes one as soon as one of its children asks.
|
|
157
|
+
The same shape decides whether a text child competes with a prop for a widget's text
|
|
158
|
+
sink, and `justify-between` is refused on a child count.
|
|
159
|
+
|
|
160
|
+
React's parent renders before its children exist, so it reads their **descriptors**.
|
|
161
|
+
Three things are therefore transparent to that read, and each is transparent because
|
|
162
|
+
an application writes it without meaning to change anything:
|
|
163
|
+
|
|
164
|
+
- **a Fragment.** `<>…</>` is transparent to layout in React, so it is transparent
|
|
165
|
+
here: it is expanded away before anything is counted, its children keeping their own
|
|
166
|
+
keys composed behind its own. A card whose `overlay={<>…</>}` holds the absolutely
|
|
167
|
+
positioned child gets the overlay it asked for.
|
|
168
|
+
- **an array**, which is the same statement in a different spelling.
|
|
169
|
+
- **an `<Animated.View>`.** Its style carries `Animated.Value`s, which is exactly what
|
|
170
|
+
the style partition refuses on a plain element — so a parent reads it through the
|
|
171
|
+
same split the component itself uses. An animated fade and an `absolute` compose.
|
|
172
|
+
|
|
173
|
+
What is NOT transparent is a foreign composite component: `<MyCard className="…">` may
|
|
174
|
+
carry any vocabulary at all, and a parent must not throw for one it cannot route, so it
|
|
175
|
+
answers "no" and the child — if it ever reaches L2 — is refused by name. That boundary
|
|
176
|
+
is enumerated in `src/child-facts.spec.ts` as every fact a parent reads × every wrapper
|
|
177
|
+
it can arrive in, with the fact list derived from the record itself: a new fact has no
|
|
178
|
+
row until someone adds one, and the suite says so.
|
|
179
|
+
|
|
100
180
|
### The split is measured, not asserted
|
|
101
181
|
|
|
102
182
|
`@gjsify/react-native/solid` exports the same seven primitives as SolidJS components
|
|
@@ -222,6 +302,38 @@ The conventions are parsed **in this package, not in the plugin**, so a consumer
|
|
|
222
302
|
another bundler — or one writing the nine-line manifest by hand — gets the same
|
|
223
303
|
refusals. The plugin walks a directory and emits what it found.
|
|
224
304
|
|
|
305
|
+
### One header bar per window, owned by the outermost navigator
|
|
306
|
+
|
|
307
|
+
An `Adw.NavigationPage` carries its own `Adw.HeaderBar`, so a `_layout` inside a
|
|
308
|
+
`_layout` describes a header bar inside a header bar. Measured on a five-tab
|
|
309
|
+
application entered at its index route, that drew **three** bars with **three close
|
|
310
|
+
buttons**, only one of which closed the window (#1460). Nothing in a file-system route
|
|
311
|
+
tree says which level owns the chrome, so this package decides it:
|
|
312
|
+
|
|
313
|
+
- The **outermost navigator owns the window's chrome** while it has a header bar on
|
|
314
|
+
screen. It claims the bar `AppRegistry` puts in the window; the window takes it back
|
|
315
|
+
when the root unmounts, and when the screen on top asks for none — an `Adw.Window`
|
|
316
|
+
carries no titlebar of its own, so a `headerShown: false` screen that also took the
|
|
317
|
+
window's bar away would be a window with nothing to close or move it with. For
|
|
318
|
+
`<Stack>` ownership means the pages carry the chrome, which is Adwaita's own
|
|
319
|
+
composition and the only one where the back button and the page title appear at all.
|
|
320
|
+
- An **inner `<Tabs>` contributes its `Adw.ViewSwitcher`** to the enclosing page's
|
|
321
|
+
header bar title, where a hand-written Adwaita application puts it, instead of
|
|
322
|
+
building a second bar. `headerShown: false` on the enclosing screen leaves no bar to
|
|
323
|
+
contribute to, and the tab level then renders its own.
|
|
324
|
+
- **The window controls go on the outermost bar of each path.** An inner `<Stack>`'s
|
|
325
|
+
pages still need their own back buttons, so their bars stay — without window
|
|
326
|
+
controls. `Adw.NavigationSplitView` splits the same decoration across its two
|
|
327
|
+
visible bars, which is why the rule that holds this is *one set of window controls
|
|
328
|
+
per side*, not *one header bar*.
|
|
329
|
+
|
|
330
|
+
That rule is machine-checked from outside, over the widgets that actually DRAW:
|
|
331
|
+
`windowChromeProblems()` in `@gjsify/gtk-host/conformance` counts mapped, non-empty
|
|
332
|
+
`GtkWindowControls` per side of a presented window and names every duplicate — and
|
|
333
|
+
also refuses a window whose chrome draws nothing at all, which is the failure the fix
|
|
334
|
+
above can overshoot into. `headerRight`, `headerLeft` and a custom header component
|
|
335
|
+
are still not answered for; the support table says so by name.
|
|
336
|
+
|
|
225
337
|
## Support
|
|
226
338
|
|
|
227
339
|
See **[SUPPORT.md](SUPPORT.md)** — one section per declared surface, generated from
|
package/SUPPORT.md
CHANGED
|
@@ -20,9 +20,9 @@ Imported from `react-native`; answered by `@gjsify/react-native`.
|
|
|
20
20
|
| `useColorScheme` | P1 | Adw.StyleManager.dark | 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. |
|
|
21
21
|
| `Appearance` | P2 | Adw.StyleManager | 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. |
|
|
22
22
|
| `EventEmitter` | — | — | Pure JavaScript; nothing in it touches a platform. |
|
|
23
|
-
| `unstable_batchedUpdates` | — | — | React 19 batches automatically; this is the identity call it already is upstream. |
|
|
23
|
+
| `unstable_batchedUpdates` | — | — | React 19 batches automatically; this is the identity call it already is upstream — literally so since 0.86, where the getter became a method whose body is `fn(bookkeeping)`. |
|
|
24
24
|
|
|
25
|
-
### Supported, with named limits (
|
|
25
|
+
### Supported, with named limits (32)
|
|
26
26
|
|
|
27
27
|
| export | tier | GTK | why |
|
|
28
28
|
|---|---|---|---|
|
|
@@ -35,6 +35,7 @@ Imported from `react-native`; answered by `@gjsify/react-native`.
|
|
|
35
35
|
| `Linking` | P1 | Gtk.UriLauncher | openURL and canOpenURL only. |
|
|
36
36
|
| `Switch` | P1 | Gtk.Switch | Direct counterpart. |
|
|
37
37
|
| `Platform` | P1 | — | OS is "linux" \| "macos" \| "windows"; select() picks the default branch. |
|
|
38
|
+
| `Modal` | P1 | Adw.Dialog | A PORTAL: the element’s host node is not its parent node. An Adw.Dialog is PRESENTED against a parent and never parented by it — MEASURED on libadwaita 1.9.3 / GTK 4.22.4, box.append(dialog) with the box ROOTED IN A WINDOW is g_error() (SIGABRT, exit 134, a core dump), while a detached box takes the same append in silence, which is how a re-test on a bare box appears to disprove it. So @gjsify/gtk-host grew a placement axis (ADR 0045) and AdwDialog declares present/force_close on it; nothing is appended and the abort is unreachable. |
|
|
38
39
|
| `Share` | P1 | Gdk.Clipboard | No desktop share sheet worth pretending about; copying the link is the honest mapping. |
|
|
39
40
|
| `AppRegistry` | P1 | Adw.Application + Adw.ApplicationWindow | The entry point. Nothing renders without a window, so this is P1 despite being a shim. |
|
|
40
41
|
| `StyleSheet` | P1 | Gdk.Monitor.scale for hairlineWidth | create/flatten/compose/hairlineWidth/absoluteFill. Style objects go through the same partition as classes (ADR 0032 § 4), which is why create can be identity. |
|
|
@@ -50,7 +51,7 @@ Imported from `react-native`; answered by `@gjsify/react-native`.
|
|
|
50
51
|
| `Button` | P2 | Gtk.Button | The one component whose React Native styling story is "you cannot", which GTK agrees with. title, onPress and disabled. |
|
|
51
52
|
| `Dimensions` | P2 | Gtk.Window allocation, Gdk.Monitor geometry | 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. |
|
|
52
53
|
| `useWindowDimensions` | P2 | Gdk.Surface notify::width/height, Gtk.Window allocation | The hook form of Dimensions, through useSyncExternalStore so a resize between render and commit cannot tear. |
|
|
53
|
-
| `Alert` | P2 | Adw.AlertDialog | Direct counterpart, and
|
|
54
|
+
| `Alert` | P2 | Adw.AlertDialog | Direct counterpart, and it needed no placement seam to be one: Alert is a FUNCTION CALL, so no element is ever inserted into a widget (Modal is the same widget family as an ELEMENT, and reaches the same call through the host portal placement of ADR 0045). Measured on libadwaita 1.9.3 — present(null) from a plain function, with no parent and no window, returned with no diagnostic. |
|
|
54
55
|
| `SafeAreaView` | P2 | Gtk.Box | 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. |
|
|
55
56
|
| `StatusBar` | P2 | — | 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. |
|
|
56
57
|
| `KeyboardAvoidingView` | P2 | Gtk.Box | 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. |
|
|
@@ -58,17 +59,15 @@ Imported from `react-native`; answered by `@gjsify/react-native`.
|
|
|
58
59
|
| `Animated` | P3 | Adw.TimedAnimation, over Adw.CallbackAnimationTarget | 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. |
|
|
59
60
|
| `Easing` | P3 | AdwEasing, through Adw.TimedAnimation:easing | 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. |
|
|
60
61
|
|
|
61
|
-
### Planned (
|
|
62
|
+
### Planned (32)
|
|
62
63
|
|
|
63
64
|
| export | tier | GTK | why |
|
|
64
65
|
|---|---|---|---|
|
|
65
|
-
| `Modal` | P1 | Adw.Dialog | 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. |
|
|
66
66
|
| `AppState` | P3 | Gtk.Application / Gdk.Surface state | active/background from window focus and visibility. |
|
|
67
67
|
| `PixelRatio` | P3 | Gdk.Surface.scale-factor | The scale factor of the surface the widget is on. |
|
|
68
68
|
| `PlatformColor` | P3 | Adwaita named colours | Maps unusually well — GTK’s palette is exactly this idea. |
|
|
69
69
|
| `AccessibilityInfo` | P3 | Gtk.Accessible / AT-SPI | The highest-value P3 entry: GTK’s accessibility model is strong and the props map onto it well. |
|
|
70
70
|
| `LayoutAnimation` | P3 | — | Needs an animated layout pass, which is the same subsystem as Animated. |
|
|
71
|
-
| `InteractionManager` | P3 | — | Deferring work until interactions settle; a main-loop idle source is the counterpart. |
|
|
72
71
|
| `useAnimatedValue` | P3 | — | Part of the Animated subsystem. |
|
|
73
72
|
| `useAnimatedValueXY` | P3 | — | Part of the Animated subsystem. |
|
|
74
73
|
| `useAnimatedColor` | P3 | — | Part of the Animated subsystem. |
|
|
@@ -88,6 +87,14 @@ Imported from `react-native`; answered by `@gjsify/react-native`.
|
|
|
88
87
|
| `ProgressBarAndroid` | P3 | Gtk.ProgressBar | Android-only by name; GTK has the widget. |
|
|
89
88
|
| `NativeEventEmitter` | P3 | — | It would construct and subscribe, but nothing native would ever emit into it — shipping that needs a decision, not a class. |
|
|
90
89
|
| `DeviceEventEmitter` | P3 | — | The global emitter. Lands with NativeEventEmitter, and for the same reason. |
|
|
90
|
+
| `AssetRegistry` | P3 | the bundler’s own asset map | undefined |
|
|
91
|
+
| `unstable_VirtualArray` | P3 | Gio.ListStore | The array-backed implementation of the `VirtualCollection` interface — `size` plus `at(index)`. Its own doc warns it is not for large arrays, because the constructor copies the input; the LAZY case is the interface, not this class. `Gio.ListStore` is the same array-backed shape, and a Gio.ListModel of one\u2019s own is the lazy one. |
|
|
92
|
+
| `unstable_createVirtualCollectionView` | P3 | Gtk.ListView / Gtk.GridView | Builds a view component from a layout component and a generator. The per-item render is the returned component\u2019s `children` render prop — which is what `Gtk.SignalListItemFactory` answers; the generator is a different thing (see below). |
|
|
93
|
+
| `unstable_VirtualColumn` | P3 | Gtk.ListView (vertical) | The collection view built over the column generator. Its layout component renders children plus a spacer and nothing else — the AXIS is in the generator\u2019s spacer style, not in the layout. |
|
|
94
|
+
| `unstable_VirtualColumnGenerator` | P3 | Gtk.ListView\u2019s own recycling window | NOT per item: `{ initial: { itemCount, spacerStyle }, next(event) }` \u2014 how many items to render and how tall the spacer is, recomputed on a mode change. It never sees an item. GTK computes the same thing itself from the viewport. |
|
|
95
|
+
| `unstable_VirtualRow` | P3 | Gtk.ListView (horizontal) | The row twin of the column view. Its layout component is identical to the column\u2019s; on GTK the pair is one view with its orientation set. Upstream exports no row GENERATOR, so only one half of the pair is configurable from outside. |
|
|
96
|
+
| `unstable_getScrollParent` | P3 | the enclosing Gtk.ScrolledWindow | The nearest scrollable ancestor of a node. GTK answers it by walking parents to a Gtk.ScrolledWindow, and returns nothing at the root for the same reason React Native does. |
|
|
97
|
+
| `unstable_DEFAULT_INITIAL_NUM_TO_RENDER` | P3 | — | The constant 7, upstream’s initial window size. GTK sizes its own recycling window from the viewport, so this is a number to expose rather than to obey. |
|
|
91
98
|
|
|
92
99
|
### No meaning on a desktop window (6)
|
|
93
100
|
|
|
@@ -100,7 +107,7 @@ Imported from `react-native`; answered by `@gjsify/react-native`.
|
|
|
100
107
|
| `DevMenu` | — | — | The shake-to-open developer menu. |
|
|
101
108
|
| `DevSettings` | — | — | Development-client settings for a phone runtime. |
|
|
102
109
|
|
|
103
|
-
### Refused (
|
|
110
|
+
### Refused (23)
|
|
104
111
|
|
|
105
112
|
| export | tier | GTK | why |
|
|
106
113
|
|---|---|---|---|
|
|
@@ -125,8 +132,6 @@ Imported from `react-native`; answered by `@gjsify/react-native`.
|
|
|
125
132
|
| `findNodeHandle` | — | — | Returns a native view tag. A ref here is the Gtk.Widget itself, which is more useful. |
|
|
126
133
|
| `registerCallableModule` | — | — | Registers a module callable from the native side. There is no native side. |
|
|
127
134
|
| `Networking` | — | — | React Native’s XHR internals. Use fetch, which gjsify provides. |
|
|
128
|
-
| `NativeDialogManagerAndroid` | — | — | An Android dialog native module. Alert is the portable spelling. |
|
|
129
|
-
| `Touchable` | — | — | The legacy mixin behind the Touchable family, not a public component. |
|
|
130
135
|
| `NativeAppEventEmitter` | — | — | The legacy iOS app-event emitter. |
|
|
131
136
|
| `RootTagContext` | — | — | A React Native surface identifier. This layer has one root per Adw window. |
|
|
132
137
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import e from"gi://GObject?version=2.0";import t from"gi://Gtk?version=4.0";function member(e,t){return e[t.toUpperCase().replace(/-/g,`_`)]}const n=t.AccessibleProperty,r=t.AccessibleState;function valueFor(t){let n=new e.Value;return typeof t==`string`?(n.init(e.TYPE_STRING),n.set_string(t),n):typeof t==`boolean`?(n.init(e.TYPE_BOOLEAN),n.set_boolean(t),n):(n.init(e.TYPE_INT),n.set_int(t),n)}const unknownAttribute=e=>Error(`@gjsify/react-native: the prop "${e.prop}" is routed to the GTK accessible ${e.set} "${e.name}", which Gtk.Accessible${e.set===`property`?`Property`:`State`} does not carry. The table is wrong, not the call`);function applyAccessibility(e,t){let i=[],a=[],o=[],s=[];for(let e of t){let t=e.set===`property`,c=member(t?n:r,e.name);if(c===void 0)throw unknownAttribute(e);(t?i:o).push(c),(t?a:s).push(valueFor(e.value))}return i.length>0&&e.update_property(i,a),o.length>0&&e.update_state(o,s),()=>{for(let t of i)e.reset_property(t);for(let t of o)e.reset_state(t)}}export{applyAccessibility};
|
package/lib/esm/apis/alert.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{PrimitiveError as e}from"../primitives/errors.js";import t from"gi://
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{PrimitiveError as e}from"../primitives/errors.js";import t from"gi://Gtk?version=4.0";import n from"gi://Adw?version=1";function anchor(){let e=t.Window.get_toplevels();for(let t=0;t<e.get_n_items();t++){let n=e.get_item(t);if(n!==null&&n.get_mapped())return n}return null}const appearanceOf=e=>e===`destructive`?n.ResponseAppearance.DESTRUCTIVE:n.ResponseAppearance.DEFAULT,r={alert(e,t,r,i){let a=new n.AlertDialog({heading:e,...t===void 0?{}:{body:t}});i?.cancelable===!1&&(a.canClose=!1);let o=r===void 0||r.length===0?[{text:`OK`}]:r,s=new Map,c=null;o.forEach((e,t)=>{let n=`response-${t}`;a.add_response(n,e.text??`Button ${t+1}`),a.set_response_appearance(n,appearanceOf(e.style)),e.onPress!==void 0&&s.set(n,e.onPress),e.style===`cancel`?a.set_close_response(n):c??=n}),c!==null&&a.set_default_response(c);let l=a.connect(`response`,(e,t)=>{a.disconnect(l),s.get(t)?.()});if(i?.onDismiss!==void 0){let e=a.connect(`closed`,()=>{a.disconnect(e),i.onDismiss?.()})}a.present(anchor())},prompt(){throw new e(`Alert`,`prompt`,"is iOS-only in React Native, and its contract — four overloads, a login/password variant, and a callback whose arity depends on the type — is what makes it a refusal rather than a port. `Adw.AlertDialog:extra-child` holds a `Gtk.Entry`, so build the dialog you actually want")}};export{r as Alert};
|
package/lib/esm/app-registry.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{UnsupportedError as e}from"./unsupported.js";import t from"gi://Adw?version=1";import{createElement as
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{UnsupportedError as e}from"./unsupported.js";import{buildWindowShell as t,provideWindowChrome as n}from"./window-chrome.js";import r from"gi://Adw?version=1";import i from"gi://GLib?version=2.0";import{createElement as a}from"react";import{runAdwaitaApp as o}from"@gjsify/adwaita-app";import{registerBuiltinWidgets as s}from"@gjsify/gtk-host";import{windowChromeProblems as c}from"@gjsify/gtk-host/conformance";import{createRoot as l}from"@gjsify/gtk-host/react";const u=new Map;let d=null,f=null,p=[],m=0;const lastWindowChromeProblems=()=>p,windowChromeChecks=()=>m;function checkWindowChrome(e){let t=e.connect(`map`,()=>{e.disconnect(t),i.idle_add(i.PRIORITY_DEFAULT_IDLE,()=>{if(!e.get_mapped())return i.SOURCE_REMOVE;p=c(e),m++;for(let e of p)console.warn(`@gjsify/react-native: ${e}`);return i.SOURCE_REMOVE})})}function toShellOptions(e,t){return{...e,createWindow:t}}function buildWindow(e,n,i){let a=new r.ApplicationWindow({application:e,title:i.title??n,defaultWidth:i.defaultWidth??900,defaultHeight:i.defaultHeight??700}),o=t();return a.set_content(o.root),{window:a,content:o.content,chrome:o.chrome}}function mountApplicationRoot(e,t,r,i){let{window:o,content:s,chrome:c}=buildWindow(e,t,r),u=i(),f=l(s);return d={app:e,window:o,content:s,root:f},f.render(n(c,a(u,r.initialProps??{}))),checkWindowChrome(o),o}async function ownTheApplication(e,t){if(f!==null)throw Error(`@gjsify/react-native: AppRegistry.runApplication("${e}") was called while "${f}" is still running. One process is one GApplication here — this layer CREATES the application, which is the declared divergence from React Native — so a second call has no window of its own to build and would take the first one’s handle away from it. Await the first call, or render both trees under one root component.`);f=e;try{return await t()}finally{let e=d;d=null,f=null,e?.root.unmount()}}const h={registerComponent(e,t){return u.set(e,{provider:t}),e},getAppKeys(){return[...u.keys()]},getRunnable(e){return u.get(e)},getApplication(){return d?.app??null},getWindow(){return d?.window??null},async runApplication(e,t){let n=u.get(e);if(n===void 0){let t=[...u.keys()];throw Error(`@gjsify/react-native: no component is registered as "${e}". `+(t.length>0?`Registered: ${t.join(`, `)}.`:`Nothing is registered — call AppRegistry.registerComponent(key, () => Component) first.`))}return s(),ownTheApplication(e,()=>o(toShellOptions(t,r=>mountApplicationRoot(r,e,t,n.provider))))},unmountApplicationComponentAtRootTag(){throw new e(`AppRegistry`)}};function registerRootComponent(e,t){return h.registerComponent(`main`,()=>e),h.runApplication(`main`,t)}export{h as AppRegistry,lastWindowChromeProblems,mountApplicationRoot,ownTheApplication,registerRootComponent,toShellOptions,windowChromeChecks};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{splitAnimatedStyle as e}from"./primitives/style.js";import{declaresAbsolute as t}from"./primitives/resolve.js";import{Children as n,Fragment as r,cloneElement as i,isValidElement as a}from"react";const isTextNode=e=>typeof e==`string`||typeof e==`number`,isFragment=e=>a(e)&&e.type===r;function childNodes(e){return expand(n.toArray(e))}function expand(e){if(!e.some(isFragment))return e;let t=[];for(let r of e){if(!isFragment(r)){t.push(r);continue}let e=r.key??``;for(let o of expand(n.toArray(r.props.children))){if(!a(o)){t.push(o);continue}t.push(i(o,{key:`${e}:${o.key??``}`}))}}return t}function readableProps(t){let n=t.props;if(n.style===void 0)return n;let{plain:r,animated:i}=e(n.style);return Object.keys(i).length===0?n:{...n,style:r}}function isAbsoluteChild(e,n){if(!a(e))return!1;try{return t(readableProps(e),n)}catch{return!1}}function childFacts(e,t){let n=0,r=!1;for(let i of e)isTextNode(i)?r=!0:isAbsoluteChild(i,t)&&n++;return{absolute:n,count:e.length,text:r}}export{childFacts,childNodes,isAbsoluteChild,isTextNode,readableProps};
|
package/lib/esm/components.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{applyAccessibility as e}from"./accessibility.js";import{accessor as t}from"./accessor.js";import{PrimitiveError as n}from"./primitives/errors.js";import{onLiveRegion as r}from"./announce.js";import{splitAnimatedStyle as i}from"./primitives/style.js";import{resolvePrimitive as a}from"./primitives/resolve.js";import{childFacts as o,childNodes as s,isAbsoluteChild as c,isTextNode as l}from"./child-facts.js";import{ParentContext as u,ParentProvider as d}from"./parent-context.js";import{onGesture as f,onPressStateChange as p}from"./press.js";import{createHandle as m}from"./primitives/handles.js";import{animatedProperty as h,assertNoStaticClash as g}from"./animated/properties.js";import{styleConfig as _}from"./style-config.js";import v from"gi://GObject?version=2.0";import y from"gi://Gtk?version=4.0";import b from"gi://Gio?version=2.0";import x from"gi://GLib?version=2.0";import{createElement as S,useCallback as C,useContext as w,useEffect as T,useMemo as E,useRef as D,useState as O}from"react";function useSignals(e,n){let r=D(null),i=D(n);return i.current=n,{props:E(()=>{let n={};for(let a of e)n[`on:${a.signal}`]=()=>{let e=i.current[a.prop];if(typeof e!=`function`)return;if(a.read===null){e();return}let n=r.current;e(n===null?void 0:n[t(a.read)])};return n},[e.map(e=>`${e.prop}>${e.signal}>${e.read??``}`).join(`|`)]),widgetRef:r}}function nodeProps(e,t,n){let r={...t,...e.props,...n};return e.cssClasses.length>0&&(r[`css-classes`]=[...e.cssClasses]),r}function usePlan(e,t){let r=t,i=w(u),c=_(),l=s(r.children),d=a(e,r,{tokens:c.tokens,sheet:c.sheet,...i===null?{}:{parent:i},children:o(l,c.tokens)}),f=Object.keys(d.intent);if(f.length>0)throw new n(e,f.join(`, `),"carries layout that cannot be resolved at this position. These need a parent to resolve against — `flex-1` and `self-*` need the parent orientation, `absolute` needs the parent to be an overlay — and this element is the root of its tree, or its parent is not a box. Wrap it in a <View>, or move the utility to a child.");let p=useSignals(d.events,r),h=r.ref,g=d.handle,v=d.node.tag,y=E(()=>e=>{p.widgetRef.current=e;let t=e==null?e:m(g,e,v);typeof h==`function`?h(t):h!=null&&(h.current=t)},[h,p.widgetRef,g,v]);useGestures(d.gestures,r,p.widgetRef),useLiveRegions(d.announcements,p.widgetRef),useAccessibility(d.accessibility,p.widgetRef);let b=useFiles(d.files),x={...p.props,ref:y,...b.outer};d.slot!==null&&(x.slot=d.slot);let S={...b.content};d.contentSlot!==null&&(S.slot=d.contentSlot);let C={...b.backdrop};d.backdropSlot!==null&&(C.slot=d.backdropSlot);let T=E(()=>d.childContext,[JSON.stringify(d.childContext),d.childContext]);return{plan:d,children:l,inherited:i?.props??{},extra:x,contentExtra:S,backdropExtra:C,published:T,tokens:c.tokens,widgetRef:p.widgetRef}}function useFiles(e){return E(()=>{let t={outer:{},content:{},backdrop:{}};for(let n of e)t[n.on][n.property]=n.kind===`path`?b.File.new_for_path(n.value):b.File.new_for_uri(n.value);return t},[e.map(e=>`${e.on}>${e.property}>${e.kind}>${e.value}`).join(`|`)])}function useGestures(e,t,n){let r=D(t);r.current=t;let i=e.map(e=>`${e.prop}>${e.signal}`).join(`|`);T(()=>{let e=n.current;if(i===``||e==null)return;let t=i.split(`|`).map(t=>{let[n,i]=t.split(`>`);return f(e,i,()=>{let e=r.current[n];typeof e==`function`&&e()})});return()=>{for(let e of t)e()}},[i,n])}function useLiveRegions(e,t){let n=e.map(e=>`${e.signal}>${e.read}>${e.priority}`).join(`|`);T(()=>{let e=t.current;if(n===``||e==null)return;let i=n.split(`|`).map(t=>{let[n,i,a]=t.split(`>`);return r(e,{prop:`accessibilityLiveRegion`,signal:n,read:i,priority:a})});return()=>{for(let e of i)e()}},[n,t])}function useAccessibility(t,n){let r=t.length===0?``:JSON.stringify(t);T(()=>{let t=n.current;if(!(r===``||t==null))return e(t,JSON.parse(r))},[r,n])}function render(e){let{plan:t,children:n,inherited:r,extra:i,contentExtra:a,backdropExtra:o,published:s,tokens:u}=e,wrap=e=>S(d,{value:s},...e);if(t.content===null){let e=n.some(l)?n:[wrap(n)];return S(t.node.tag,nodeProps(t.node,r,i),...e)}let f=t.absoluteSlot===null?[]:n.filter(e=>c(e,u)),p=t.absoluteSlot===null?n:n.filter(e=>!c(e,u)),m=S(t.content.tag,nodeProps(t.content,{},a),wrap(p)),h=t.backdrop===null?[]:[S(t.backdrop.tag,nodeProps(t.backdrop,{},o))];return S(t.node.tag,nodeProps(t.node,r,i),...h,m,...f.length===0?[]:[wrap(f)])}function View(e){return render(usePlan(`View`,e))}function Text(e){return render(usePlan(`Text`,e))}function Pressable(e){let t=typeof e.children==`function`?e.children:null,[n,r]=O(!1),i=usePlan(`Pressable`,t===null?e:{...e,children:t({pressed:n})}),a=i.widgetRef;return T(()=>{if(t===null)return;let e=a.current;if(e!=null)return p(e,r)},[t===null,a]),render(i)}const k=v.registerClass({GTypeName:`GjsifyReactNativeRailLayout`},class RailLayout extends y.BoxLayout{vfunc_measure(e,t,n){let plain=n=>super.vfunc_measure(e,t,n);if(t!==y.Orientation.VERTICAL||n>=0||this.get_orientation()!==y.Orientation.HORIZONTAL)return plain(n);let r=super.vfunc_measure(e,y.Orientation.HORIZONTAL,-1)[0],i=e.get_ancestor(y.ScrolledWindow.$gtype),a=i===null?0:Math.round(i.get_hadjustment().get_page_size()),o=Math.max(a,r);if(o<=0)return plain(n);let[,s,,c]=super.vfunc_measure(e,y.Orientation.VERTICAL,o);return[s,s,c,c]}});let A=0;const railWatchCount=()=>A;function useIntrinsicContentHeight(e){let t=D(null),n=D(null);return C(r=>{let i=t.current;i!==null&&(i.adjustment.disconnect(i.id),t.current=null,--A),n.current!==null&&(x.source_remove(n.current),n.current=null);let a=r??null;if(a===null||!e)return;let o=a.get_layout_manager();if(!(o instanceof k)){let e=new k({orientation:y.Orientation.HORIZONTAL});o instanceof y.BoxLayout&&e.set_spacing(o.get_spacing()),a.set_layout_manager(e)}let s=a.get_ancestor(y.ScrolledWindow.$gtype);if(s===null)return;let c=s.get_hadjustment(),l=c.connect(`notify::page-size`,()=>{n.current===null&&(n.current=x.idle_add(x.PRIORITY_DEFAULT_IDLE,()=>(n.current=null,a.queue_resize(),x.SOURCE_REMOVE)))});t.current={adjustment:c,id:l},A+=1},[e])}function ScrollView(e){let t=usePlan(`ScrollView`,e),n=useIntrinsicContentHeight(e.horizontal===!0);return render({...t,contentExtra:{...t.contentExtra,ref:n}})}function ActivityIndicator(e){return render(usePlan(`ActivityIndicator`,e))}function TextInput(e){return render(usePlan(`TextInput`,e))}function Switch(e){return render(usePlan(`Switch`,e))}function Image(e){return render(usePlan(`Image`,e))}function ImageBackground(e){return render(usePlan(`ImageBackground`,e))}function TouchableOpacity(e){return render(usePlan(`TouchableOpacity`,e))}function TouchableHighlight(e){return render(usePlan(`TouchableHighlight`,e))}function TouchableWithoutFeedback(e){return render(usePlan(`TouchableWithoutFeedback`,e))}function Button(e){return render(usePlan(`Button`,e))}function SafeAreaView(e){return render(usePlan(`SafeAreaView`,e))}function Modal(e){let t=usePlan(`Modal`,e);return e.visible===!1?null:render(t)}function KeyboardAvoidingView(e){return render(usePlan(`KeyboardAvoidingView`,e))}function StatusBar(e){return null}const j="configures the status bar above a phone screen, and a desktop window has none — the space above it belongs to the compositor and the header bar inside it is `Adw.HeaderBar`, an ordinary widget you render. This refuses rather than accepting the call, because a setter that appears to work is indistinguishable from one that does";Object.defineProperties(StatusBar,Object.getOwnPropertyDescriptors({setBarStyle:()=>{throw new n(`StatusBar`,`setBarStyle`,j)},setHidden:()=>{throw new n(`StatusBar`,`setHidden`,j)},setBackgroundColor:()=>{throw new n(`StatusBar`,`setBackgroundColor`,j)},setTranslucent:()=>{throw new n(`StatusBar`,`setTranslucent`,j)},setNetworkActivityIndicatorVisible:()=>{throw new n(`StatusBar`,`setNetworkActivityIndicatorVisible`,j)},pushStackEntry:()=>{throw new n(`StatusBar`,`pushStackEntry`,j)},popStackEntry:()=>{throw new n(`StatusBar`,`popStackEntry`,j)},replaceStackEntry:()=>{throw new n(`StatusBar`,`replaceStackEntry`,j)},get currentHeight(){throw new n(`StatusBar`,`currentHeight`,"is the height of a phone’s status bar, and code reads it straight into a layout (`paddingTop: StatusBar.currentHeight`). A desktop window has no such bar, so any number here would inset every ported screen by a bar that is not there. Use 0 explicitly if that is what you mean")}}));function animatedBindings(e,t){let{plain:n,animated:r}=i(t),a=[];for(let[t,n]of Object.entries(r))h(e,t),a.push({key:t,value:n});return{plain:n,bindings:a}}function AnimatedView(e){let n=_(),{plain:r,bindings:i}=animatedBindings(`Animated.View`,e.style),a={...e,style:r};g(`Animated.View`,a,i.map(e=>e.key),n.tokens);let o=usePlan(`View`,a),s=o.widgetRef,c=i.map(e=>`${e.key}#${e.value.id}`).join(`|`),l=D(i);l.current=i,T(()=>{let e=s.current;if(c===``||e==null)return;let n=e,r=l.current.map(r=>{let i=t(h(`Animated.View`,r.key).property);return r.value.__attach({widget:e,write:e=>{n[i]=e}})});return()=>{for(let e of r)e()}},[c,s]);let u={};for(let e of i)u[t(h(`Animated.View`,e.key).property)]=e.value.__getValue();return render({...o,extra:{...o.extra,...u}})}function Icon(e){return render(usePlan(`Icon`,e))}export{ActivityIndicator,AnimatedView,Button,Icon,Image,ImageBackground,KeyboardAvoidingView,Modal,Pressable,SafeAreaView,ScrollView,StatusBar,Switch,Text,TextInput,TouchableHighlight,TouchableOpacity,TouchableWithoutFeedback,View,nodeProps,railWatchCount,usePlan};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=[`OWN_EXPORT_NAMES`,`PRIMITIVE_VARIANTS`,`PrimitiveError`,`SUPPORTED_NAMES`,`SUPPORT_TABLE`,`UnsupportedError`,`acceptsProp`,`configureStyle`,`explainProp`,`explainUnsupported`,`isImportable`,`isOwnExport`,`primitives`,`propAnswer`,`propNames`,`propTable`,`registerRootComponent`,`resetStyleConfig`,`styleConfig`];export{e as OWN_EXPORT_NAMES};
|
|
1
|
+
const e=[`OWN_EXPORT_NAMES`,`PRIMITIVE_VARIANTS`,`PrimitiveError`,`SUPPORTED_NAMES`,`SUPPORT_TABLE`,`UnsupportedError`,`acceptsProp`,`configureStyle`,`explainProp`,`explainUnsupported`,`isImportable`,`isOwnExport`,`lastWindowChromeProblems`,`primitives`,`propAnswer`,`propNames`,`propTable`,`registerRootComponent`,`resetStyleConfig`,`styleConfig`];export{e as OWN_EXPORT_NAMES};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{unsupported as e}from"../unsupported.js";const t=e(`
|
|
1
|
+
import{unsupported as e}from"../unsupported.js";const t=e(`RefreshControl`,`react-native`),n=e(`AppState`,`react-native`),r=e(`PixelRatio`,`react-native`),i=e(`PlatformColor`,`react-native`),a=e(`AccessibilityInfo`,`react-native`),o=e(`LayoutAnimation`,`react-native`),s=e(`useAnimatedValue`,`react-native`),c=e(`useAnimatedValueXY`,`react-native`),l=e(`useAnimatedColor`,`react-native`),u=e(`PanResponder`,`react-native`),d=e(`usePressability`,`react-native`),f=e(`DrawerLayoutAndroid`,`react-native`),p=e(`I18nManager`,`react-native`),m=e(`LogBox`,`react-native`),h=e(`Systrace`,`react-native`),g=e(`Vibration`,`react-native`),_=e(`ToastAndroid`,`react-native`),v=e(`InputAccessoryView`,`react-native`),y=e(`TouchableNativeFeedback`,`react-native`),b=e(`ActionSheetIOS`,`react-native`),x=e(`PushNotificationIOS`,`react-native`),S=e(`PermissionsAndroid`,`react-native`),C=e(`Settings`,`react-native`),w=e(`Clipboard`,`react-native`),T=e(`BackHandler`,`react-native`),E=e(`DynamicColorIOS`,`react-native`),D=e(`processColor`,`react-native`),O=e(`UTFSequence`,`react-native`),k=e(`experimental_LayoutConformance`,`react-native`),A=e(`unstable_VirtualView`,`react-native`),j=e(`VirtualViewMode`,`react-native`),M=e(`unstable_NativeText`,`react-native`),N=e(`unstable_NativeView`,`react-native`),P=e(`unstable_TextAncestorContext`,`react-native`),F=e(`ReactNativeVersion`,`react-native`),I=e(`DeviceInfo`,`react-native`),L=e(`DevMenu`,`react-native`),R=e(`DevSettings`,`react-native`),z=e(`NativeModules`,`react-native`),B=e(`TurboModuleRegistry`,`react-native`),V=e(`NativeComponentRegistry`,`react-native`),H=e(`requireNativeComponent`,`react-native`),U=e(`codegenNativeComponent`,`react-native`),W=e(`codegenNativeCommands`,`react-native`),G=e(`UIManager`,`react-native`),K=e(`findNodeHandle`,`react-native`),q=e(`registerCallableModule`,`react-native`),J=e(`Networking`,`react-native`),Y=e(`ProgressBarAndroid`,`react-native`),X=e(`NativeEventEmitter`,`react-native`),Z=e(`DeviceEventEmitter`,`react-native`),Q=e(`NativeAppEventEmitter`,`react-native`),$=e(`RootTagContext`,`react-native`),ee=e(`AssetRegistry`,`react-native`),te=e(`unstable_VirtualArray`,`react-native`),ne=e(`unstable_createVirtualCollectionView`,`react-native`),re=e(`unstable_VirtualColumn`,`react-native`),ie=e(`unstable_VirtualColumnGenerator`,`react-native`),ae=e(`unstable_VirtualRow`,`react-native`),oe=e(`unstable_getScrollParent`,`react-native`),se=e(`unstable_DEFAULT_INITIAL_NUM_TO_RENDER`,`react-native`);export{a as AccessibilityInfo,b as ActionSheetIOS,n as AppState,ee as AssetRegistry,T as BackHandler,w as Clipboard,L as DevMenu,R as DevSettings,Z as DeviceEventEmitter,I as DeviceInfo,f as DrawerLayoutAndroid,E as DynamicColorIOS,p as I18nManager,v as InputAccessoryView,o as LayoutAnimation,m as LogBox,Q as NativeAppEventEmitter,V as NativeComponentRegistry,X as NativeEventEmitter,z as NativeModules,J as Networking,u as PanResponder,S as PermissionsAndroid,r as PixelRatio,i as PlatformColor,Y as ProgressBarAndroid,x as PushNotificationIOS,F as ReactNativeVersion,t as RefreshControl,$ as RootTagContext,C as Settings,h as Systrace,_ as ToastAndroid,y as TouchableNativeFeedback,B as TurboModuleRegistry,G as UIManager,O as UTFSequence,g as Vibration,j as VirtualViewMode,W as codegenNativeCommands,U as codegenNativeComponent,k as experimental_LayoutConformance,K as findNodeHandle,D as processColor,q as registerCallableModule,H as requireNativeComponent,se as unstable_DEFAULT_INITIAL_NUM_TO_RENDER,M as unstable_NativeText,N as unstable_NativeView,P as unstable_TextAncestorContext,te as unstable_VirtualArray,re as unstable_VirtualColumn,ie as unstable_VirtualColumnGenerator,ae as unstable_VirtualRow,A as unstable_VirtualView,ne as unstable_createVirtualCollectionView,oe as unstable_getScrollParent,l as useAnimatedColor,s as useAnimatedValue,c as useAnimatedValueXY,d as usePressability};
|
package/lib/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./_virtual/_rolldown/runtime.js";import{PrimitiveError as e}from"./primitives/errors.js";import{Easing as t}from"./animated/easing.js";import{configureStyle as n,resetStyleConfig as r,styleConfig as i}from"./style-config.js";import{ActivityIndicator as a,Button as o,Image as s,ImageBackground as c,KeyboardAvoidingView as l,
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{PrimitiveError as e}from"./primitives/errors.js";import{Easing as t}from"./animated/easing.js";import{configureStyle as n,resetStyleConfig as r,styleConfig as i}from"./style-config.js";import{ActivityIndicator as a,Button as o,Image as s,ImageBackground as c,KeyboardAvoidingView as l,Modal as u,Pressable as d,SafeAreaView as f,ScrollView as p,StatusBar as m,Switch as h,Text as g,TextInput as _,TouchableHighlight as v,TouchableOpacity as y,TouchableWithoutFeedback as b,View as x}from"./components.js";import{Animated as S}from"./animated/index.js";import{Alert as C}from"./apis/alert.js";import{Appearance as w}from"./apis/appearance.js";import{Dimensions as T}from"./apis/dimensions.js";import{Keyboard as E}from"./apis/keyboard.js";import{Linking as D}from"./apis/linking.js";import{Platform as O}from"./apis/platform.js";import{Share as k}from"./apis/share.js";import"./apis/index.js";import{OWN_EXPORT_NAMES as A}from"./generated/own-exports.js";import{SUPPORTED_NAMES as j,SUPPORT_TABLE as M,explainUnsupported as N,isImportable as P,isOwnExport as F}from"./support-table.js";import{UnsupportedError as I}from"./unsupported.js";import{AppRegistry as L,lastWindowChromeProblems as R,registerRootComponent as z}from"./app-registry.js";import{EventEmitter as B}from"./event-emitter.js";import{AccessibilityInfo as V,ActionSheetIOS as H,AppState as U,AssetRegistry as W,BackHandler as G,Clipboard as K,DevMenu as q,DevSettings as J,DeviceEventEmitter as Y,DeviceInfo as X,DrawerLayoutAndroid as Z,DynamicColorIOS as Q,I18nManager as $,InputAccessoryView as ee,LayoutAnimation as te,LogBox as ne,NativeAppEventEmitter as re,NativeComponentRegistry as ie,NativeEventEmitter as ae,NativeModules as oe,Networking as se,PanResponder as ce,PermissionsAndroid as le,PixelRatio as ue,PlatformColor as de,ProgressBarAndroid as fe,PushNotificationIOS as pe,ReactNativeVersion as me,RefreshControl as he,RootTagContext as ge,Settings as _e,Systrace as ve,ToastAndroid as ye,TouchableNativeFeedback as be,TurboModuleRegistry as xe,UIManager as Se,UTFSequence as Ce,Vibration as we,VirtualViewMode as Te,codegenNativeCommands as Ee,codegenNativeComponent as De,experimental_LayoutConformance as Oe,findNodeHandle as ke,processColor as Ae,registerCallableModule as je,requireNativeComponent as Me,unstable_DEFAULT_INITIAL_NUM_TO_RENDER as Ne,unstable_NativeText as Pe,unstable_NativeView as Fe,unstable_TextAncestorContext as Ie,unstable_VirtualArray as Le,unstable_VirtualColumn as Re,unstable_VirtualColumnGenerator as ze,unstable_VirtualRow as Be,unstable_VirtualView as Ve,unstable_createVirtualCollectionView as He,unstable_getScrollParent as Ue,useAnimatedColor as We,useAnimatedValue as Ge,useAnimatedValueXY as Ke,usePressability as qe}from"./generated/unsupported-react-native.js";import{useColorScheme as Je,useWindowDimensions as Ye}from"./hooks.js";import{FlatList as Xe,SectionList as Ze,VirtualizedList as Qe,VirtualizedSectionList as $e}from"./lists/components.js";import{StyleSheet as et}from"./stylesheet.js";import{primitives_exports as tt}from"./primitives/index.js";import{PRIMITIVE_VARIANTS as nt,acceptsProp as rt,explainProp as it,propAnswer as at,propNames as ot,propTable as st}from"./prop-table.js";function unstable_batchedUpdates(e,t){return e(t)}export{V as AccessibilityInfo,H as ActionSheetIOS,a as ActivityIndicator,C as Alert,S as Animated,L as AppRegistry,U as AppState,w as Appearance,W as AssetRegistry,G as BackHandler,o as Button,K as Clipboard,q as DevMenu,J as DevSettings,Y as DeviceEventEmitter,X as DeviceInfo,T as Dimensions,Z as DrawerLayoutAndroid,Q as DynamicColorIOS,t as Easing,B as EventEmitter,Xe as FlatList,$ as I18nManager,s as Image,c as ImageBackground,ee as InputAccessoryView,E as Keyboard,l as KeyboardAvoidingView,te as LayoutAnimation,D as Linking,ne as LogBox,u as Modal,re as NativeAppEventEmitter,ie as NativeComponentRegistry,ae as NativeEventEmitter,oe as NativeModules,se as Networking,A as OWN_EXPORT_NAMES,nt as PRIMITIVE_VARIANTS,ce as PanResponder,le as PermissionsAndroid,ue as PixelRatio,O as Platform,de as PlatformColor,d as Pressable,e as PrimitiveError,fe as ProgressBarAndroid,pe as PushNotificationIOS,me as ReactNativeVersion,he as RefreshControl,ge as RootTagContext,j as SUPPORTED_NAMES,M as SUPPORT_TABLE,f as SafeAreaView,p as ScrollView,Ze as SectionList,_e as Settings,k as Share,m as StatusBar,et as StyleSheet,h as Switch,ve as Systrace,g as Text,_ as TextInput,ye as ToastAndroid,v as TouchableHighlight,be as TouchableNativeFeedback,y as TouchableOpacity,b as TouchableWithoutFeedback,xe as TurboModuleRegistry,Se as UIManager,Ce as UTFSequence,I as UnsupportedError,we as Vibration,x as View,Te as VirtualViewMode,Qe as VirtualizedList,$e as VirtualizedSectionList,rt as acceptsProp,Ee as codegenNativeCommands,De as codegenNativeComponent,n as configureStyle,Oe as experimental_LayoutConformance,it as explainProp,N as explainUnsupported,ke as findNodeHandle,P as isImportable,F as isOwnExport,R as lastWindowChromeProblems,tt as primitives,Ae as processColor,at as propAnswer,ot as propNames,st as propTable,je as registerCallableModule,z as registerRootComponent,Me as requireNativeComponent,r as resetStyleConfig,i as styleConfig,Ne as unstable_DEFAULT_INITIAL_NUM_TO_RENDER,Pe as unstable_NativeText,Fe as unstable_NativeView,Ie as unstable_TextAncestorContext,Le as unstable_VirtualArray,Re as unstable_VirtualColumn,ze as unstable_VirtualColumnGenerator,Be as unstable_VirtualRow,Ve as unstable_VirtualView,unstable_batchedUpdates,He as unstable_createVirtualCollectionView,Ue as unstable_getScrollParent,We as useAnimatedColor,Ge as useAnimatedValue,Ke as useAnimatedValueXY,Je as useColorScheme,qe as usePressability,Ye as useWindowDimensions};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{ParentProvider as e}from"../parent-context.js";import{createElement as t}from"react";import{
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{ParentProvider as e}from"../parent-context.js";import{createElement as t}from"react";import{adopt as n,createElement as r,insert as i,widgetOf as a}from"@gjsify/gtk-host";import{createRoot as o}from"@gjsify/gtk-host/react";import{ListController as s,onScrollNearEnd as c}from"@gjsify/gtk-host/list";const l={orientation:`vertical`,props:{},overlay:!1},RowBody=({row:e})=>e.render();function reactRows(s){let c=new Map,u=[],d=!1,schedule=()=>{d||(d=!0,queueMicrotask(()=>{d=!1;let e=[...c];c.clear();for(let[t,n]of e)t.render(n);let t=u.splice(0,u.length);for(let e of t)e.unmount()}))};return{mountRow(e){let t=r(`GtkBox`,{orientation:`vertical`});i(t,n(e));let c=s.onRowError;return o(a(t),c===void 0?{}:{onUncaughtError:c})},showRow(n,r){c.set(n,r===null?null:t(e,{value:l},t(RowBody,{row:r}))),schedule()},disposeRow(e){c.delete(e),u.push(e),schedule()}}}function createListController(e={}){return new s(reactRows(e))}function rowKey(e,t,n){if(n!==void 0)return n(e,t);if(typeof e==`object`&&e){let t=e;if(typeof t.key==`string`)return t.key;if(typeof t.id==`string`||typeof t.id==`number`)return String(t.id)}return String(t)}export{createListController,c as onScrollNearEnd,rowKey};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";const e={false:0,true:1,mixed:2};function coerceAttribute(t,n){switch(t.as){case`string`:return typeof n==`string`?n:null;case`boolean`:return typeof n==`boolean`?n:null;case`tristate`:return typeof n==`boolean`?n?e.true:e.false:n===`mixed`?e.mixed:null}}const t={string:`a string`,boolean:`true or false`,tristate:`true, false or "mixed" — GTK reads it as a Gtk.AccessibleTristate`};function resolveAccessible(e,n,r){if(e.from===`value`){let i=coerceAttribute(e.attribute,r);return i===null?{entries:[],problem:`writes the GTK accessible ${e.attribute.set} "${e.attribute.name}" and needs ${t[e.attribute.as]}`}:{entries:[{prop:n,set:e.attribute.set,name:e.attribute.name,value:i}],problem:null}}if(typeof r!=`object`||!r||Array.isArray(r))return{entries:[],problem:`is a record of accessibility states and needs an object — its keys are ${Object.keys(e.members).sort().join(`, `)}`};let i=[];for(let[a,o]of Object.entries(r)){if(o===void 0)continue;let r=e.refuses[a];if(r!==void 0)return{entries:[],problem:`carries "${a}", which ${r}`};let s=e.members[a];if(s===void 0)return{entries:[],problem:`carries "${a}", which is not a state this layer answers for. It takes: ${Object.keys(e.members).sort().join(`, `)}`};let c=coerceAttribute(s,o);if(c===null)return{entries:[],problem:`carries "${a}", which needs ${t[s.as]}`};i.push({prop:n,set:s.set,name:s.name,value:c})}return{entries:i,problem:null}}export{resolveAccessible};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";const isAccepted=e=>e!==`refused`&&e!==`unknown`,unknownPropDetail=e=>`is not a prop this primitive answers for. It takes: ${Object.keys(e.props).sort().join(`, `)}. An unlisted prop is refused rather than dropped: a prop that silently does nothing is indistinguishable from a bug in the application, forever`,unknownPrimitiveDetail=e=>`is not a primitive this layer answers for. Known: ${[...e].sort().join(`, `)}
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";function accessibleReach(e){let call=e=>e===`property`?`Gtk.Accessible.update_property()`:`Gtk.Accessible.update_state()`;return e.from===`value`?[`${call(e.attribute.set)}: ${e.attribute.name}`]:Object.keys(e.members).sort().map(t=>{let n=e.members[t];return`${t} → ${call(n.set)}: ${n.name}`})}const isAccepted=e=>e!==`refused`&&e!==`unknown`,unknownPropDetail=e=>`is not a prop this primitive answers for. It takes: ${Object.keys(e.props).sort().join(`, `)}. An unlisted prop is refused rather than dropped: a prop that silently does nothing is indistinguishable from a bug in the application, forever`,unknownPrimitiveDetail=e=>`is not a primitive this layer answers for. Known: ${[...e].sort().join(`, `)}`,e={};function answerForRoute(t){switch(t.to){case`property`:return{status:`property`,why:``,gtk:t.names,refuses:t.refuses??e};case`style-property`:return{status:`style`,why:``,gtk:[`style: ${t.name}`],refuses:e};case`event`:return{status:`event`,why:``,gtk:[t.signal],refuses:e};case`file`:return{status:`file`,why:``,gtk:[t.property],refuses:e};case`gesture`:return{status:`gesture`,why:``,gtk:[`Gtk.GestureClick::${t.signal}`],refuses:e};case`announce`:return{status:`announcement`,why:``,gtk:[t.signal,`Gtk.Accessible.announce()`],refuses:e};case`accessible`:return{status:`accessible`,why:``,gtk:accessibleReach(t),refuses:t.from===`members`?t.refuses:e};case`ignored`:return{status:`ignored`,why:t.why,gtk:[],refuses:e};case`refused`:return{status:`refused`,why:t.why,gtk:[],refuses:e}}}function answerFor(t,n,r,i){if(n.refusesStyle!==void 0&&(r===`style`||r===`className`))return{primitive:t,prop:r,status:`refused`,why:n.refusesStyle,gtk:[],refuses:e};if(i.has(r))return{primitive:t,prop:r,status:`framework`,why:``,gtk:[],refuses:e};let a=n.props[r];if(a===void 0)return{primitive:t,prop:r,status:`unknown`,why:unknownPropDetail(n),gtk:[],refuses:e};let o=(Array.isArray(a)?a:[a]).map(answerForRoute),s=o[0];return{primitive:t,prop:r,status:s.status,why:s.why,gtk:o.flatMap(e=>e.gtk),refuses:Object.assign({},...o.map(e=>e.refuses))}}function propNamesOf(e){return Object.keys(e.props).sort()}export{answerFor,isAccepted,propNamesOf,unknownPrimitiveDetail,unknownPropDetail};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";const e=[{gtype:`GtkBox`,property:`orientation`,gtk:`horizontal`,reactNative:`column`,source:"Yoga’s own default — `ReactCommon/yoga/yoga/style/Style.h`: `FlexDirection::Column`. CSS defaults to `row`; React Native deliberately does not.",verdict:`normalised`,normalisedTo:`vertical`,reason:`The first inversion this layer met, and the loudest: a screen written as a column would have come out as a row.`},{gtype:`GtkBox`,property:`spacing`,gtk:0,reactNative:"0 (`gap` is unset)",source:`Yoga: an unset gap is 0.`,verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkBox`,property:`homogeneous`,gtk:!1,reactNative:`no counterpart — children are sized by flex`,source:`Yoga has no "all children equal" mode.`,verdict:`agrees`,reason:"GTK’s `false` is what a flex container does, so the absent concept and the default coincide."},{gtype:`GtkLabel`,property:`wrap`,gtk:!1,reactNative:`text wraps`,source:"React Native’s `<Text>` wraps unless `numberOfLines` says otherwise.",verdict:`normalised`,normalisedTo:!0,reason:`Without it a long line forces the window wider instead of wrapping — which reads as a layout bug anywhere but here.`},{gtype:`GtkLabel`,property:`xalign`,gtk:.5,reactNative:`the script’s natural alignment — start, i.e. left in LTR`,source:'`ReactCommon/react/renderer/attributedstring/TextAttributes.h`: `std::optional<TextAlignment> alignment{}` is UNSET by default, and `primitives.h` documents `TextAlignment::Natural` as "the default alignment for script". Observed in a 25-route port: every string on every screen rendered centred.',verdict:`normalised`,normalisedTo:0,reason:"MEASURED as a position, not as a property: a `Gtk.Label` allocated 400×100 reports `get_layout_offsets()` = (193, 41) with GTK’s defaults and (0, 0) with xalign/yalign 0. Nothing anywhere reports the difference."},{gtype:`GtkLabel`,property:`yalign`,gtk:.5,reactNative:`the top of the text’s box`,source:"The same unset `alignment`; vertical centring is `textAlignVertical`/`verticalAlign`, which is also unset. Same layout-offset measurement as `xalign` — the 41 in (193, 41) is this one.",verdict:`normalised`,normalisedTo:0,reason:"Only visible when the label is given more height than its text — a `flex-1` or an explicit height — which is exactly when it is hardest to attribute."},{gtype:`GtkLabel`,property:`justify`,gtk:`left`,reactNative:`natural, i.e. left in LTR`,source:"As `xalign`: unset means natural.",verdict:`agrees`,reason:"GTK’s enum default already is the LTR answer. It is `xalign` that positions the BLOCK and this that positions the lines within it, which is why only one of the pair was wrong."},{gtype:`GtkLabel`,property:`ellipsize`,gtk:`none`,reactNative:"no truncation until `numberOfLines` is set",source:"React Native applies `ellipsizeMode` only together with `numberOfLines`.",verdict:`agrees`,reason:`Both truncate nothing until asked.`},{gtype:`GtkLabel`,property:`selectable`,gtk:!1,reactNative:"`selectable` defaults to false",source:"React Native’s `TextProps`.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkTextView`,property:`wrap-mode`,gtk:`none`,reactNative:`a multiline input wraps`,source:"React Native’s multiline `TextInput` wraps, as `<Text>` does.",verdict:`normalised`,normalisedTo:`word-char`,reason:"The same disagreement as `Gtk.Label:wrap`, one widget over: without it the field scrolls sideways for ever."},{gtype:`GtkTextView`,property:`editable`,gtk:!0,reactNative:"`editable` defaults to true",source:"React Native’s `TextInputProps`.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkPicture`,property:`content-fit`,gtk:`contain`,reactNative:`cover`,source:"React Native’s `Image` defaults `resizeMode` to `cover`.",verdict:`normalised`,normalisedTo:`cover`,reason:`Inverted between the two platforms, and an image that fits where it should fill looks deliberate.`},{gtype:`GtkScrolledWindow`,property:`hscrollbar-policy`,gtk:`automatic`,reactNative:"vertical only — `horizontal` defaults to false",source:"React Native’s `ScrollViewProps`.",verdict:`normalised`,normalisedTo:`never`,reason:`GTK would scroll sideways as well, which is a second scroll axis the author did not ask for.`},{gtype:`GtkScrolledWindow`,property:`vexpand`,gtk:!1,reactNative:"`flexGrow` 0, as for any widget",source:"Yoga: an unset `flexGrow` is 0.",verdict:`primitive`,reason:"`FlatList` writes it on its scroller, and it is a layout decision rather than a default: the scroller is one of up to three children of the outer box and it is the one that takes the leftover space, because a header and a footer are their own natural height."},{gtype:`GtkScrolledWindow`,property:`hexpand`,gtk:!1,reactNative:"`flexGrow` 0, as for any widget",source:"Yoga: an unset `flexGrow` is 0.",verdict:`primitive`,reason:"As `vexpand`, one axis over — `FlatList`’s scroller fills its box."},{gtype:`GtkScrolledWindow`,property:`kinetic-scrolling`,gtk:!0,reactNative:`no counterpart on a desktop`,source:`—`,verdict:`kept`,reason:`Touch-and-flick scrolling is GTK’s own behaviour on a touchscreen and costs nothing with a mouse. Turning it off would remove a desktop affordance to match a phone API that does not describe it.`},{gtype:`GtkEntry`,property:`has-frame`,gtk:!0,reactNative:`unstyled — a bare text field with no border`,source:"React Native’s `TextInput` draws no chrome of its own on either platform.",verdict:`kept`,reason:`DELIBERATE, and the one row here that is a design choice rather than a match: an Adwaita entry without its frame is not a text field a desktop user recognises. The divergence is visible, which is what separates it from the silent ones — an author sees the frame immediately and can remove it from the stylesheet.`},{gtype:`GtkEntry`,property:`visibility`,gtk:!0,reactNative:"`secureTextEntry` defaults to false",source:"React Native’s `TextInputProps`.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkSwitch`,property:`active`,gtk:!1,reactNative:"`value` defaults to false",source:"React Native’s `SwitchProps`.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkWidget`,property:`halign`,gtk:`fill`,reactNative:`stretch`,source:"Yoga’s own default — `ReactCommon/yoga/yoga/style/Style.h`: `Align alignItems_ = Align::Stretch`.",verdict:`agrees`,reason:"GTK’s `fill` and CSS’s `stretch` are the same instruction under different words — `intents.ts` maps them to each other for the explicit case too."},{gtype:`GtkWidget`,property:`hexpand`,gtk:!1,reactNative:"`flexGrow` 0",source:"Yoga: an unset `flexGrow` is 0.",verdict:`agrees`,reason:"Neither grows until asked. `flex-1` is what asks, and `intents.ts` resolves it against the PARENT’s axis."},{gtype:`GtkWidget`,property:`opacity`,gtk:1,reactNative:`1`,source:`React Native’s style default.`,verdict:`agrees`,reason:"Nothing to do. `Animated.View` writes this property, which is why it is worth having checked."},{gtype:`GtkWidget`,property:`overflow`,gtk:`visible`,reactNative:`visible`,source:"React Native’s `overflow` style default.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkWidget`,property:`can-target`,gtk:!0,reactNative:"`pointerEvents` defaults to `auto`",source:"React Native’s `ViewProps`.",verdict:`agrees`,reason:`Nothing to do.`}],t=e.filter(e=>e.verdict===`normalised`),defaultRowFor=(t,n)=>e.find(e=>e.gtype===t&&e.property===n)??e.find(e=>e.gtype===`GtkWidget`&&e.property===n);export{e as DEFAULT_ROWS,t as NORMALISED_DEFAULTS,defaultRowFor};
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";const e=[{gtype:`GtkBox`,property:`orientation`,gtk:`horizontal`,reactNative:`column`,source:"Yoga’s own default — `ReactCommon/yoga/yoga/style/Style.h`: `FlexDirection::Column`. CSS defaults to `row`; React Native deliberately does not.",verdict:`normalised`,normalisedTo:`vertical`,reason:`The first inversion this layer met, and the loudest: a screen written as a column would have come out as a row.`},{gtype:`GtkBox`,property:`spacing`,gtk:0,reactNative:"0 (`gap` is unset)",source:`Yoga: an unset gap is 0.`,verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkBox`,property:`homogeneous`,gtk:!1,reactNative:`no counterpart — children are sized by flex`,source:`Yoga has no "all children equal" mode.`,verdict:`agrees`,reason:"GTK’s `false` is what a flex container does, so the absent concept and the default coincide."},{gtype:`GtkLabel`,property:`wrap`,gtk:!1,reactNative:`text wraps`,source:"React Native’s `<Text>` wraps unless `numberOfLines` says otherwise.",verdict:`normalised`,normalisedTo:!0,reason:`Without it a long line forces the window wider instead of wrapping — which reads as a layout bug anywhere but here.`},{gtype:`GtkLabel`,property:`xalign`,gtk:.5,reactNative:`the script’s natural alignment — start, i.e. left in LTR`,source:'`ReactCommon/react/renderer/attributedstring/TextAttributes.h`: `std::optional<TextAlignment> alignment{}` is UNSET by default, and `primitives.h` documents `TextAlignment::Natural` as "the default alignment for script". Observed in a 25-route port: every string on every screen rendered centred.',verdict:`normalised`,normalisedTo:0,reason:"MEASURED as a position, not as a property: a `Gtk.Label` allocated 400×100 reports `get_layout_offsets()` = (193, 41) with GTK’s defaults and (0, 0) with xalign/yalign 0. Nothing anywhere reports the difference."},{gtype:`GtkLabel`,property:`yalign`,gtk:.5,reactNative:`the top of the text’s box`,source:"The same unset `alignment`; vertical centring is `textAlignVertical`/`verticalAlign`, which is also unset. Same layout-offset measurement as `xalign` — the 41 in (193, 41) is this one.",verdict:`normalised`,normalisedTo:0,reason:"Only visible when the label is given more height than its text — a `flex-1` or an explicit height — which is exactly when it is hardest to attribute."},{gtype:`GtkLabel`,property:`justify`,gtk:`left`,reactNative:`natural, i.e. left in LTR`,source:"As `xalign`: unset means natural.",verdict:`agrees`,reason:"GTK’s enum default already is the LTR answer. It is `xalign` that positions the BLOCK and this that positions the lines within it, which is why only one of the pair was wrong."},{gtype:`GtkLabel`,property:`ellipsize`,gtk:`none`,reactNative:"no truncation until `numberOfLines` is set",source:"React Native applies `ellipsizeMode` only together with `numberOfLines`.",verdict:`agrees`,reason:`Both truncate nothing until asked.`},{gtype:`GtkLabel`,property:`selectable`,gtk:!1,reactNative:"`selectable` defaults to false",source:"React Native’s `TextProps`.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkTextView`,property:`wrap-mode`,gtk:`none`,reactNative:`a multiline input wraps`,source:"React Native’s multiline `TextInput` wraps, as `<Text>` does.",verdict:`normalised`,normalisedTo:`word-char`,reason:"The same disagreement as `Gtk.Label:wrap`, one widget over: without it the field scrolls sideways for ever."},{gtype:`GtkTextView`,property:`editable`,gtk:!0,reactNative:"`editable` defaults to true",source:"React Native’s `TextInputProps`.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkPicture`,property:`content-fit`,gtk:`contain`,reactNative:`cover`,source:"React Native’s `Image` defaults `resizeMode` to `cover`.",verdict:`normalised`,normalisedTo:`cover`,reason:`Inverted between the two platforms, and an image that fits where it should fill looks deliberate.`},{gtype:`GtkScrolledWindow`,property:`hscrollbar-policy`,gtk:`automatic`,reactNative:"vertical only — `horizontal` defaults to false",source:"React Native’s `ScrollViewProps`.",verdict:`normalised`,normalisedTo:`never`,reason:`GTK would scroll sideways as well, which is a second scroll axis the author did not ask for.`},{gtype:`GtkScrolledWindow`,property:`vexpand`,gtk:!1,reactNative:"`flexGrow` 0, as for any widget",source:"Yoga: an unset `flexGrow` is 0.",verdict:`primitive`,reason:"`FlatList` writes it on its scroller, and it is a layout decision rather than a default: the scroller is one of up to three children of the outer box and it is the one that takes the leftover space, because a header and a footer are their own natural height."},{gtype:`GtkScrolledWindow`,property:`hexpand`,gtk:!1,reactNative:"`flexGrow` 0, as for any widget",source:"Yoga: an unset `flexGrow` is 0.",verdict:`primitive`,reason:"As `vexpand`, one axis over — `FlatList`’s scroller fills its box."},{gtype:`GtkScrolledWindow`,property:`kinetic-scrolling`,gtk:!0,reactNative:`no counterpart on a desktop`,source:`—`,verdict:`kept`,reason:`Touch-and-flick scrolling is GTK’s own behaviour on a touchscreen and costs nothing with a mouse. Turning it off would remove a desktop affordance to match a phone API that does not describe it.`},{gtype:`GtkEntry`,property:`has-frame`,gtk:!0,reactNative:`unstyled — a bare text field with no border`,source:"React Native’s `TextInput` draws no chrome of its own on either platform.",verdict:`kept`,reason:`DELIBERATE, and the one row here that is a design choice rather than a match: an Adwaita entry without its frame is not a text field a desktop user recognises. The divergence is visible, which is what separates it from the silent ones — an author sees the frame immediately and can remove it from the stylesheet.`},{gtype:`GtkEntry`,property:`visibility`,gtk:!0,reactNative:"`secureTextEntry` defaults to false",source:"React Native’s `TextInputProps`.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkSwitch`,property:`active`,gtk:!1,reactNative:"`value` defaults to false",source:"React Native’s `SwitchProps`.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkWidget`,property:`halign`,gtk:`fill`,reactNative:`stretch`,source:"Yoga’s own default — `ReactCommon/yoga/yoga/style/Style.h`: `Align alignItems_ = Align::Stretch`.",verdict:`agrees`,reason:"GTK’s `fill` and CSS’s `stretch` are the same instruction under different words — `intents.ts` maps them to each other for the explicit case too."},{gtype:`GtkWidget`,property:`hexpand`,gtk:!1,reactNative:"`flexGrow` 0",source:"Yoga: an unset `flexGrow` is 0.",verdict:`agrees`,reason:"Neither grows until asked. `flex-1` is what asks, and `intents.ts` resolves it against the PARENT’s axis."},{gtype:`AdwDialog`,property:`can-close`,gtk:!0,reactNative:"a modal is dismissed by its `visible` prop and by nothing else",source:"React Native’s `Modal`: `visible` is the only thing that shows or hides it, and `onRequestClose` is documented as required on Android and tvOS precisely because the modal does not dismiss itself.",verdict:`primitive`,reason:"Not a default divergence but the contract that makes the two models agree. A dialog left able to close itself would take the sheet down on Escape while the element stayed mounted with `visible` still true — nothing on screen, and no prop change left to re-present it. With `can-close: false` the user’s dismissal arrives as `close-attempt` (that is `onRequestClose`) and only unrendering the element closes the dialog, through the portal placement’s `force_close`."},{gtype:`GtkWidget`,property:`opacity`,gtk:1,reactNative:`1`,source:`React Native’s style default.`,verdict:`agrees`,reason:"Nothing to do. `Animated.View` writes this property, which is why it is worth having checked."},{gtype:`GtkWidget`,property:`overflow`,gtk:`visible`,reactNative:`visible`,source:"React Native’s `overflow` style default.",verdict:`agrees`,reason:`Nothing to do.`},{gtype:`GtkWidget`,property:`can-target`,gtk:!0,reactNative:"`pointerEvents` defaults to `auto`",source:"React Native’s `ViewProps`.",verdict:`agrees`,reason:`Nothing to do.`}],t=e.filter(e=>e.verdict===`normalised`),defaultRowFor=(t,n)=>e.find(e=>e.gtype===t&&e.property===n)??e.find(e=>e.gtype===`GtkWidget`&&e.property===n);export{e as DEFAULT_ROWS,t as NORMALISED_DEFAULTS,defaultRowFor};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";const primitiveErrorMessage=(e,t,n)=>`@gjsify/react-native: <${e}>${t===``?``:` ${t}`} — ${n}
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";const primitiveErrorMessage=(e,t,n)=>`@gjsify/react-native: <${e}>${t===``?``:` ${t}`} — ${n}`,describeValue=e=>typeof e==`string`?`"${e}"`:typeof e==`object`&&e?Object.prototype.toString.call(e):String(e);var PrimitiveError=class extends Error{constructor(e,t,n){super(primitiveErrorMessage(e,t,n)),this.name=`PrimitiveError`,this.primitive=e,this.subject=t}};export{PrimitiveError,describeValue,primitiveErrorMessage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{__exportAll as e}from"../_virtual/_rolldown/runtime.js";import{PrimitiveError as t}from"./errors.js";import{
|
|
1
|
+
import{__exportAll as e}from"../_virtual/_rolldown/runtime.js";import{PrimitiveError as t}from"./errors.js";import{answerFor as n,isAccepted as r,propNamesOf as i,unknownPrimitiveDetail as a,unknownPropDetail as o}from"./answers.js";import{resolveIntent as s}from"./intents.js";import{splitVariants as c}from"./classes.js";import{flattenStyle as l,mintClass as u,normalise as d,variantDeclarations as f}from"./style.js";import{FRAMEWORK_PROPS as p,PRIMITIVES as m,PRIMITIVE_NAMES as h}from"./table.js";import{declaresAbsolute as g,resolvePrimitive as _}from"./resolve.js";import{createHandle as v}from"./handles.js";import{DEFAULT_ROWS as y,NORMALISED_DEFAULTS as b,defaultRowFor as x}from"./defaults.js";var S=e({DEFAULT_ROWS:()=>y,FRAMEWORK_PROPS:()=>p,NORMALISED_DEFAULTS:()=>b,PRIMITIVES:()=>m,PRIMITIVE_NAMES:()=>h,PrimitiveError:()=>t,answerFor:()=>n,createHandle:()=>v,declaresAbsolute:()=>g,defaultRowFor:()=>x,flattenStyle:()=>l,isAccepted:()=>r,mintClass:()=>u,normalise:()=>d,propNamesOf:()=>i,resolveIntent:()=>s,resolvePrimitive:()=>_,splitVariants:()=>c,unknownPrimitiveDetail:()=>a,unknownPropDetail:()=>o,variantDeclarations:()=>f});export{y as DEFAULT_ROWS,p as FRAMEWORK_PROPS,b as NORMALISED_DEFAULTS,m as PRIMITIVES,h as PRIMITIVE_NAMES,t as PrimitiveError,n as answerFor,v as createHandle,g as declaresAbsolute,x as defaultRowFor,l as flattenStyle,r as isAccepted,u as mintClass,d as normalise,S as primitives_exports,i as propNamesOf,s as resolveIntent,_ as resolvePrimitive,c as splitVariants,a as unknownPrimitiveDetail,o as unknownPropDetail,f as variantDeclarations};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{PrimitiveError as e}from"./errors.js";import{unknownPrimitiveDetail as
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{PrimitiveError as e,describeValue as t}from"./errors.js";import{resolveAccessible as n}from"./accessibility.js";import{unknownPrimitiveDetail as r,unknownPropDetail as i}from"./answers.js";import{resolveIntent as a}from"./intents.js";import{mintClass as o,normalise as s,partition as c,variantDeclarations as l}from"./style.js";import{FRAMEWORK_PROPS as u,PRIMITIVES as d,PRIMITIVE_NAMES as f}from"./table.js";const p=[`orientation`,`spacing`],withOrientationClass=(e,t)=>{if(t.length===0)return t;let n=e.orientation;return typeof n==`string`?[n,...t]:t},wrapped=(e,t,n)=>{if(n===null)return{tag:e,props:t};let{spacing:r,...i}=t;return{tag:n.tag,props:{...i,...n.props}}};function declaresAbsolute(e,t,n=`View`){let{props:r}=s(e,t,n);return c(r).intent.overlay?.role===`child`}function resolvePrimitive(t,n,m){let h=d[t];if(h===void 0)throw new e(t,``,r(f));let g=h.switchOn!==void 0&&n[h.switchOn.prop]===!0?h.switchOn.whenTrue:h,_=g.content,v={...g.widgetProps},y={..._?.widgetProps},b={...g.backdrop?.widgetProps},x={},S=[],C=[],w=[],T=[],E=[],D=new Set([_?.styleProp,_?.classNameProp,g.backdrop?.styleProp,g.backdrop?.classNameProp].filter(e=>typeof e==`string`));if(g.refusesStyle!==void 0&&(n.className!==void 0||n.style!==void 0))throw new e(t,n.className===void 0?`prop "style"`:`prop "className"`,g.refusesStyle);for(let r of Object.keys(n)){if(u.has(r)||D.has(r))continue;let a=n[r];if(a===void 0)continue;let o=g.props[r];if(o===void 0)throw new e(t,`prop "${r}"`,i(g));for(let e of Array.isArray(o)?o:[o])applyRoute(e,r,a,{primitive:t,spec:g,outerProps:v,contentProps:y,backdropProps:b,styleExtra:x,events:S,files:C,gestures:w,announcements:T,accessibility:E})}let O=s(n,m.tokens,t),k=c({...O.props,...x}),A=orientationOf(k.props.orientation??v.orientation,g.orientation),j=_===void 0?A:orientationOf(y.orientation,_.orientation),M=a({primitive:t,intent:k.intent,orientation:j,widget:g.widget,...m.parent===void 0?{}:{parent:m.parent},...m.children===void 0?{}:{children:m.children},emittedProps:k.props}),N=o(m.sheet,[...k.css,...M.css],l(O.groups,m.tokens,t));Object.assign(v,k.props,M.props),assertOneTextAuthority(t,g,v,m.children);let P=[...g.cssClasses,...N===null?[]:[N]],F=g.overlayOnAbsoluteChild;if(F!==void 0&&(m.children?.absolute??0)>0){let e={...g.widgetProps};for(let t of p)v[t]!==void 0&&(e[t]=v[t],delete v[t]);let n=wrapped(g.tag,e,M.wrapping);return{primitive:t,node:{tag:F.tag,props:v,cssClasses:withOrientationClass(v,P)},content:{tag:n.tag,props:n.props,cssClasses:[]},backdrop:null,backdropSlot:null,contentSlot:null,slot:M.slot,absoluteSlot:F.slot,events:S,files:C,gestures:w,announcements:T,accessibility:E,handle:g.handle??null,textSink:g.textSink,childContext:{...M.childContext,orientation:j,overlay:!0},intent:M.remaining}}let I=_===void 0?null:resolveNode(_,n,y,m,t),L=g.backdrop===void 0?null:resolveNode(g.backdrop,n,b,m,t),R=wrapped(g.tag,v,M.wrapping);return{primitive:t,node:{tag:R.tag,props:R.props,cssClasses:withOrientationClass(R.props,P)},content:I===null?null:I.node,backdrop:L===null?null:L.node,backdropSlot:g.backdrop?.slot??null,contentSlot:_?.slot??null,slot:M.slot,absoluteSlot:null,events:S,files:C,gestures:w,announcements:T,accessibility:E,handle:g.handle??null,textSink:g.textSink,childContext:I===null?{...M.childContext,overlay:!1}:{...I.childContext,...I.childContext.textAlign===void 0&&M.childContext.textAlign!==void 0?{textAlign:M.childContext.textAlign}:{},overlay:!1},intent:M.remaining}}function resolveNode(e,t,n,r,i){let u=`${i} ${e.styleProp??`content`}`,d=s({...e.classNameProp===null?{}:{className:t[e.classNameProp]},...e.styleProp===null?{}:{style:t[e.styleProp]}},r.tokens,u),f=c(d.props),p=orientationOf(f.props.orientation??n.orientation,e.orientation),m=a({primitive:u,intent:f.intent,orientation:p,widget:e.widget,parent:{orientation:p,props:{},overlay:!1},emittedProps:f.props}),h=o(r.sheet,[...f.css,...m.css],l(d.groups,r.tokens,u));Object.assign(n,f.props,m.props);let g=wrapped(e.tag,n,m.wrapping);return{node:{tag:g.tag,props:g.props,cssClasses:withOrientationClass(g.props,h===null?[]:[h])},childContext:{...m.childContext,orientation:p}}}function applyRoute(r,i,a,o){switch(r.to){case`refused`:throw new e(o.primitive,`prop "${i}"`,r.why);case`ignored`:return;case`style-property`:o.styleExtra[r.name]=a;return;case`event`:if(typeof a!=`function`)throw new e(o.primitive,`prop "${i}"`,`binds the GTK signal "${r.signal}" and needs a function; got ${t(a)}`);o.events.push({prop:i,signal:r.signal,read:r.read??null});return;case`file`:o.files.push({on:nodeOf(r.on,o,i),property:r.property,...normaliseSource(o.primitive,i,a)});return;case`gesture`:if(typeof a!=`function`)throw new e(o.primitive,`prop "${i}"`,`binds a Gtk.GestureClick's "${r.signal}" and needs a function; got ${t(a)}`);o.gestures.push({prop:i,signal:r.signal});return;case`announce`:{let n=r.map[String(a)];if(n===void 0)throw new e(o.primitive,`prop "${i}"`,`has no GTK equivalent for ${t(a)}. Known: ${Object.keys(r.map).sort().join(`, `)}. A value absent from that list is absent because GTK has no member for it, not because the table is short`);if(n===null)return;o.announcements.push({prop:i,signal:r.signal,read:r.read,priority:n});return}case`accessible`:{let{entries:s,problem:c}=n(r,i,a);if(c!==null)throw new e(o.primitive,`prop "${i}"`,`${c}; got ${t(a)}`);o.accessibility.push(...s);return}case`property`:{let e=nodeOf(r.on,o,i),t=e===`content`?o.contentProps:e===`backdrop`?o.backdropProps:o.outerProps,n=coerce(r,i,a,o.primitive);for(let e of r.names)t[e]=n;r.also!==void 0&&Object.assign(t,r.also);return}}}function nodeOf(t,n,r){if(t===`content`&&n.spec.content===void 0)throw new e(n.primitive,`prop "${r}"`,`is routed to a content node this primitive does not declare — the table is wrong, not the call`);if(t===`backdrop`&&n.spec.backdrop===void 0)throw new e(n.primitive,`prop "${r}"`,`is routed to a backdrop node this primitive does not declare — the table is wrong, not the call`);return t??`outer`}function normaliseSource(n,r,i){let refuse=t=>{throw new e(n,`prop "${r}"`,t)};if(typeof i==`number`)return refuse("is a number, which is what `require('./image.png')` returns: an opaque id into React Native’s own asset registry. This build chain has no such registry (ADR 0032 § 12 leaves the build to the consumer), so there is nothing to resolve it against. Use `{ uri: '/path/to/image.png' }`, or ship the image in a GResource and use `{ uri: 'resource:///…' }`");if(Array.isArray(i))return refuse("is an array, which is React Native’s per-device-scale picker (`@2x`, `@3x`). GTK draws ONE texture and scales it by the surface’s own scale factor, so there is no candidate to choose between. Give one source");if(typeof i==`string`)return refuse("is a bare string. React Native’s own type is `{ uri }`, and accepting both spellings here would make one string ambiguous between a path and a URI at exactly the layer that has to decide. Write `{ uri: … }`");if(typeof i!=`object`||!i)return refuse(`expects { uri }; got ${t(i)}`);let a=i,o=Object.keys(a).filter(e=>e!==`uri`);if(o.length>0)return refuse(`carries ${o.join(`, `)} beside \`uri\`. Those describe a remote image React Native measures before it arrives (\`width\`/\`height\`) or fetches with headers, and neither reaches a \`Gtk.Picture\` — it takes a file and draws it. Keep \`uri\` alone`);let s=a.uri;if(typeof s!=`string`||s===``)return refuse(`expects { uri: string }; got uri = ${t(s)}`);let c=/^([a-zA-Z][a-zA-Z0-9+.-]+):/.exec(s)?.[1]?.toLowerCase();return c===void 0?{kind:`path`,value:s}:c===`file`||c===`resource`?{kind:`uri`,value:s}:refuse(c===`http`||c===`https`||c===`data`?`is a \`${c}:\` URI, and loading one needs a fetch, a decoder and a cache — an asynchronous pipeline this layer does not own. Handing a non-native \`Gio.File\` to \`Gtk.Picture:file\` would decode on the main loop instead. Fetch the bytes yourself, build a \`Gdk.Texture\`, and set \`paintable\` through a ref`:`is a \`${c}:\` URI, and this layer only opens what GTK can read synchronously: a local path, \`file:\` and \`resource:\` (measured). Anything else needs a loader that is not here`)}function coerce(n,r,i,a){let bad=n=>{throw new e(a,`prop "${r}"`,`expects ${n}; got ${t(i)}`)};switch(n.as){case`string`:return typeof i==`string`?i:typeof i==`number`||typeof i==`boolean`?String(i):bad(`a string`);case`boolean`:return typeof i==`boolean`?i:bad(`a boolean`);case`not`:return typeof i==`boolean`?!i:bad(`a boolean`);case`int`:return typeof i==`number`&&Number.isFinite(i)?Math.trunc(i):bad(`a number`);case`map`:return lookup(n,r,i,a);case`pixels-or-map`:return typeof i==`number`&&Number.isFinite(i)?Math.trunc(i):lookup(n,r,i,a)}}function lookup(n,r,i,a){let o=n.map??{},s=o[String(i)];if(s!==void 0)return s;let c=n.refuses?.[String(i)];throw c===void 0?new e(a,`prop "${r}"`,`has no GTK equivalent for ${t(i)}. Known: ${Object.keys(o).sort().join(`, `)}. A value absent from that list is absent because GTK has no member for it, not because the table is short`):new e(a,`prop "${r}" = ${t(i)}`,c)}function assertOneTextAuthority(t,n,r,i){if(!(n.textSink===null||i?.text!==!0)&&r[n.textSink]!==void 0)throw new e(t,`prop → "${n.textSink}"`,`is the same widget property a text CHILD writes, and both were given. Whichever the reconciler applied last would win, possibly differently on a first render and on an update — so it is refused. Keep one`)}const orientationOf=(e,t)=>e===`horizontal`||e===`vertical`?e:t;export{declaresAbsolute,resolvePrimitive};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../_virtual/_rolldown/runtime.js";import{isAnimatedValue as e}from"../animated/brand.js";import{PrimitiveError as t}from"./errors.js";import{splitVariants as n}from"./classes.js";import{partition as r,resolveUtilities as i}from"@gjsify/gtk-host/style";function flattenStyle(e){if(e==null||e===!1)return{};if(!Array.isArray(e))return e;let t={};for(let n of e)Object.assign(t,flattenStyle(n));return t}const a=new Set([`flexGrow`,`flexShrink`,`flex`,`opacity`,`fontWeight`,`zIndex`,`aspectRatio`]);function normalise(e,t,r){let a=n(e.className,r),o={...i(a.base,t)};for(let[t,n]of Object.entries(flattenStyle(e.style)))n!=null&&(typeof n!=`number`&&typeof n!=`string`&&scalarOnly(r,t,n),o[t]=typeof n==`number`?stringify(t,n):n);return{props:o,groups:a}}function variantDeclarations(e,n,a){let o={};for(let[s,c]of Object.entries(e.variants)){let e=r(i(c,n)),l=Object.keys(e.props),u=Object.keys(e.intent);if(l.length>0||u.length>0)throw new t(a,`className "${s}:${c.join(` ${s}:`)}"`,`resolves to ${[...l,...u].join(`, `)}, which ${l.length>0?`is a GTK WIDGET PROPERTY`:`is a layout INTENT`} rather than a CSS declaration. A variant becomes a GTK CSS pseudo-class, and a widget property has no pseudo-class form — only the paint half of the vocabulary (colour, opacity, radius, border, font) can carry a variant`);o[s]=e.css}return o}function scalarOnly(n,r,i){throw new t(n,`style={{ ${r}: … }}`,e(i)?'carries an `Animated.Value`, and this element is not an `Animated.View`. A plain element partitions its style into GTK CSS and widget properties before a widget sees it, so the value would land in a CSS declaration as "[object Object]" — which GTK drops without a diagnostic. Render `<Animated.View>` instead':`is a ${Array.isArray(i)?`array`:typeof i}, and the style partition reads numbers and strings. GTK CSS is composed by interpolating the value into a declaration, so anything else becomes a declaration GTK’s parser drops in silence`)}const stringify=(e,t)=>a.has(e)?`${t}`:`${t}px`;function mintClass(e,t,n){let r=Object.values(n).some(e=>e.length>0);return t.length===0&&!r?null:e.classFor(t,n)}export{flattenStyle,mintClass,normalise,r as partition,variantDeclarations};
|
|
1
|
+
import"../_virtual/_rolldown/runtime.js";import{isAnimatedValue as e}from"../animated/brand.js";import{PrimitiveError as t}from"./errors.js";import{splitVariants as n}from"./classes.js";import{partition as r,resolveUtilities as i}from"@gjsify/gtk-host/style";function flattenStyle(e){if(e==null||e===!1)return{};if(!Array.isArray(e))return e;let t={};for(let n of e)Object.assign(t,flattenStyle(n));return t}function splitAnimatedStyle(t){let n={},r={};for(let[i,a]of Object.entries(flattenStyle(t)))e(a)?r[i]=a:n[i]=a;return{plain:n,animated:r}}const a=new Set([`flexGrow`,`flexShrink`,`flex`,`opacity`,`fontWeight`,`zIndex`,`aspectRatio`]);function normalise(e,t,r){let a=n(e.className,r),o={...i(a.base,t)};for(let[t,n]of Object.entries(flattenStyle(e.style)))n!=null&&(typeof n!=`number`&&typeof n!=`string`&&scalarOnly(r,t,n),o[t]=typeof n==`number`?stringify(t,n):n);return{props:o,groups:a}}function variantDeclarations(e,n,a){let o={};for(let[s,c]of Object.entries(e.variants)){let e=r(i(c,n)),l=Object.keys(e.props),u=Object.keys(e.intent);if(l.length>0||u.length>0)throw new t(a,`className "${s}:${c.join(` ${s}:`)}"`,`resolves to ${[...l,...u].join(`, `)}, which ${l.length>0?`is a GTK WIDGET PROPERTY`:`is a layout INTENT`} rather than a CSS declaration. A variant becomes a GTK CSS pseudo-class, and a widget property has no pseudo-class form — only the paint half of the vocabulary (colour, opacity, radius, border, font) can carry a variant`);o[s]=e.css}return o}function scalarOnly(n,r,i){throw new t(n,`style={{ ${r}: … }}`,e(i)?'carries an `Animated.Value`, and this element is not an `Animated.View`. A plain element partitions its style into GTK CSS and widget properties before a widget sees it, so the value would land in a CSS declaration as "[object Object]" — which GTK drops without a diagnostic. Render `<Animated.View>` instead':`is a ${Array.isArray(i)?`array`:typeof i}, and the style partition reads numbers and strings. GTK CSS is composed by interpolating the value into a declaration, so anything else becomes a declaration GTK’s parser drops in silence`)}const stringify=(e,t)=>a.has(e)?`${t}`:`${t}px`;function mintClass(e,t,n){let r=Object.values(n).some(e=>e.length>0);return t.length===0&&!r?null:e.classFor(t,n)}export{flattenStyle,mintClass,normalise,r as partition,splitAnimatedStyle,variantDeclarations};
|