react-native-gtkx 0.1.0-alpha.4 → 0.2.0-alpha.2

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.
Files changed (257) hide show
  1. package/README.md +22 -9
  2. package/dist/adw/index.d.ts +3 -0
  3. package/dist/adw/index.js +41 -0
  4. package/dist/adw/index.js.map +1 -0
  5. package/dist/adw/widgets.generated.d.ts +63 -0
  6. package/dist/adw/widgets.generated.js +125 -0
  7. package/dist/adw/widgets.generated.js.map +1 -0
  8. package/dist/animated/create-animated.d.ts +2 -0
  9. package/dist/animated/create-animated.js +2 -0
  10. package/dist/animated/create-animated.js.map +1 -1
  11. package/dist/animated/index.d.ts +2 -0
  12. package/dist/animated/index.js +1 -0
  13. package/dist/animated/index.js.map +1 -1
  14. package/dist/animated/value-xy.d.ts +41 -0
  15. package/dist/animated/value-xy.js +90 -0
  16. package/dist/animated/value-xy.js.map +1 -0
  17. package/dist/animated/value.d.ts +9 -0
  18. package/dist/animated/value.js +30 -2
  19. package/dist/animated/value.js.map +1 -1
  20. package/dist/common/content.d.ts +69 -0
  21. package/dist/common/content.js +84 -0
  22. package/dist/common/content.js.map +1 -0
  23. package/dist/common/icon.d.ts +23 -0
  24. package/dist/common/icon.js +14 -0
  25. package/dist/common/icon.js.map +1 -0
  26. package/dist/common/index.d.ts +5 -0
  27. package/dist/common/index.js +21 -0
  28. package/dist/common/index.js.map +1 -0
  29. package/dist/common/list.d.ts +82 -0
  30. package/dist/common/list.js +166 -0
  31. package/dist/common/list.js.map +1 -0
  32. package/dist/common/navigation-stack.d.ts +84 -0
  33. package/dist/common/navigation-stack.js +313 -0
  34. package/dist/common/navigation-stack.js.map +1 -0
  35. package/dist/common/widget.d.ts +62 -0
  36. package/dist/common/widget.js +209 -0
  37. package/dist/common/widget.js.map +1 -0
  38. package/dist/components/animated.d.ts +7 -4
  39. package/dist/components/animated.js +88 -67
  40. package/dist/components/animated.js.map +1 -1
  41. package/dist/components/app-registry.d.ts +36 -1
  42. package/dist/components/app-registry.js +8 -3
  43. package/dist/components/app-registry.js.map +1 -1
  44. package/dist/components/host-node.d.ts +7 -0
  45. package/dist/components/host-node.js +26 -1
  46. package/dist/components/host-node.js.map +1 -1
  47. package/dist/components/index.d.ts +6 -2
  48. package/dist/components/index.js +2 -1
  49. package/dist/components/index.js.map +1 -1
  50. package/dist/components/measure.d.ts +13 -0
  51. package/dist/components/measure.js +51 -0
  52. package/dist/components/measure.js.map +1 -0
  53. package/dist/components/modal.d.ts +1 -1
  54. package/dist/components/press-event.d.ts +28 -0
  55. package/dist/components/press-event.js +46 -0
  56. package/dist/components/press-event.js.map +1 -0
  57. package/dist/components/pressable.d.ts +2 -6
  58. package/dist/components/pressable.js +119 -20
  59. package/dist/components/pressable.js.map +1 -1
  60. package/dist/components/rect-store.d.ts +11 -1
  61. package/dist/components/rect-store.js +27 -3
  62. package/dist/components/rect-store.js.map +1 -1
  63. package/dist/components/scroll-view.d.ts +4 -0
  64. package/dist/components/scroll-view.js +8 -2
  65. package/dist/components/scroll-view.js.map +1 -1
  66. package/dist/components/svg/animated-support.d.ts +19 -0
  67. package/dist/components/svg/animated-support.js +64 -0
  68. package/dist/components/svg/animated-support.js.map +1 -0
  69. package/dist/components/svg/context.d.ts +8 -0
  70. package/dist/components/svg/context.js +15 -0
  71. package/dist/components/svg/context.js.map +1 -0
  72. package/dist/components/svg/gradients.d.ts +31 -0
  73. package/dist/components/svg/gradients.js +93 -0
  74. package/dist/components/svg/gradients.js.map +1 -0
  75. package/dist/components/svg/group.d.ts +8 -0
  76. package/dist/components/svg/group.js +30 -0
  77. package/dist/components/svg/group.js.map +1 -0
  78. package/dist/components/svg/index.d.ts +6 -0
  79. package/dist/components/svg/index.js +5 -0
  80. package/dist/components/svg/index.js.map +1 -0
  81. package/dist/components/svg/node.d.ts +7 -0
  82. package/dist/components/svg/node.js +7 -0
  83. package/dist/components/svg/node.js.map +1 -0
  84. package/dist/components/svg/paint.d.ts +24 -0
  85. package/dist/components/svg/paint.js +57 -0
  86. package/dist/components/svg/paint.js.map +1 -0
  87. package/dist/components/svg/shapes.d.ts +47 -0
  88. package/dist/components/svg/shapes.js +51 -0
  89. package/dist/components/svg/shapes.js.map +1 -0
  90. package/dist/components/svg/svg.d.ts +14 -0
  91. package/dist/components/svg/svg.js +48 -0
  92. package/dist/components/svg/svg.js.map +1 -0
  93. package/dist/components/svg/use-shape-node.d.ts +12 -0
  94. package/dist/components/svg/use-shape-node.js +52 -0
  95. package/dist/components/svg/use-shape-node.js.map +1 -0
  96. package/dist/components/text-input.js +1 -1
  97. package/dist/components/text-input.js.map +1 -1
  98. package/dist/components/text.js +36 -3
  99. package/dist/components/text.js.map +1 -1
  100. package/dist/components/use-layout-child.js +50 -4
  101. package/dist/components/use-layout-child.js.map +1 -1
  102. package/dist/components/view.d.ts +9 -4
  103. package/dist/components/view.js +8 -2
  104. package/dist/components/view.js.map +1 -1
  105. package/dist/contracts.d.ts +31 -4
  106. package/dist/contracts.js.map +1 -1
  107. package/dist/gtk/index.d.ts +7 -0
  108. package/dist/gtk/index.js +46 -0
  109. package/dist/gtk/index.js.map +1 -0
  110. package/dist/gtk/widgets.generated.d.ts +103 -0
  111. package/dist/gtk/widgets.generated.js +205 -0
  112. package/dist/gtk/widgets.generated.js.map +1 -0
  113. package/dist/gtk/window-actions.d.ts +77 -0
  114. package/dist/gtk/window-actions.js +193 -0
  115. package/dist/gtk/window-actions.js.map +1 -0
  116. package/dist/gtkx/bridge/geometry.d.ts +15 -0
  117. package/dist/gtkx/bridge/geometry.js +38 -0
  118. package/dist/gtkx/bridge/geometry.js.map +1 -0
  119. package/dist/gtkx/bridge/index.d.ts +11 -4
  120. package/dist/gtkx/bridge/index.js +47 -6
  121. package/dist/gtkx/bridge/index.js.map +1 -1
  122. package/dist/gtkx/bridge/layout-manager.d.ts +2 -1
  123. package/dist/gtkx/bridge/layout-manager.js +31 -9
  124. package/dist/gtkx/bridge/layout-manager.js.map +1 -1
  125. package/dist/gtkx/bridge/slot-portal.d.ts +12 -0
  126. package/dist/gtkx/bridge/slot-portal.js +17 -0
  127. package/dist/gtkx/bridge/slot-portal.js.map +1 -0
  128. package/dist/gtkx/bridge/svg-node.d.ts +79 -0
  129. package/dist/gtkx/bridge/svg-node.js +323 -0
  130. package/dist/gtkx/bridge/svg-node.js.map +1 -0
  131. package/dist/gtkx/bridge/use-signal.js +19 -9
  132. package/dist/gtkx/bridge/use-signal.js.map +1 -1
  133. package/dist/gtkx/bridge/widgets.generated.d.ts +2 -0
  134. package/dist/gtkx/bridge/widgets.generated.js +14 -0
  135. package/dist/gtkx/bridge/widgets.generated.js.map +1 -0
  136. package/dist/index.d.ts +2 -2
  137. package/dist/index.js +1 -1
  138. package/dist/index.js.map +1 -1
  139. package/dist/mcp/bin.d.ts +2 -0
  140. package/dist/mcp/bin.js +17 -0
  141. package/dist/mcp/bin.js.map +1 -0
  142. package/dist/mcp/data/generated.d.ts +1304 -0
  143. package/dist/mcp/data/generated.js +1179 -0
  144. package/dist/mcp/data/generated.js.map +1 -0
  145. package/dist/mcp/index.d.ts +5 -0
  146. package/dist/mcp/index.js +9 -0
  147. package/dist/mcp/index.js.map +1 -0
  148. package/dist/mcp/list.d.ts +4 -0
  149. package/dist/mcp/list.js +56 -0
  150. package/dist/mcp/list.js.map +1 -0
  151. package/dist/mcp/resolve.d.ts +55 -0
  152. package/dist/mcp/resolve.js +151 -0
  153. package/dist/mcp/resolve.js.map +1 -0
  154. package/dist/mcp/search.d.ts +13 -0
  155. package/dist/mcp/search.js +48 -0
  156. package/dist/mcp/search.js.map +1 -0
  157. package/dist/mcp/server.d.ts +7 -0
  158. package/dist/mcp/server.js +135 -0
  159. package/dist/mcp/server.js.map +1 -0
  160. package/dist/mcp/tool.d.ts +21 -0
  161. package/dist/mcp/tool.js +36 -0
  162. package/dist/mcp/tool.js.map +1 -0
  163. package/dist/metro/index.js +10 -0
  164. package/dist/metro/index.js.map +1 -1
  165. package/dist/navigation/index.d.ts +50 -13
  166. package/dist/navigation/index.js +183 -148
  167. package/dist/navigation/index.js.map +1 -1
  168. package/dist/navigation/option-warnings.js +9 -1
  169. package/dist/navigation/option-warnings.js.map +1 -1
  170. package/dist/navigation/sidebar.d.ts +207 -9
  171. package/dist/navigation/sidebar.js +294 -10
  172. package/dist/navigation/sidebar.js.map +1 -1
  173. package/dist/responder/system.d.ts +27 -0
  174. package/dist/responder/system.js +184 -0
  175. package/dist/responder/system.js.map +1 -0
  176. package/dist/responder/touch-history.d.ts +10 -0
  177. package/dist/responder/touch-history.js +78 -0
  178. package/dist/responder/touch-history.js.map +1 -0
  179. package/dist/responder/types.d.ts +63 -0
  180. package/dist/responder/types.js +29 -0
  181. package/dist/responder/types.js.map +1 -0
  182. package/dist/responder/use-responder.d.ts +12 -0
  183. package/dist/responder/use-responder.js +98 -0
  184. package/dist/responder/use-responder.js.map +1 -0
  185. package/dist/runner/host-dev.js +3 -1
  186. package/dist/runner/host-dev.js.map +1 -1
  187. package/dist/runner/host.js +5 -1
  188. package/dist/runner/host.js.map +1 -1
  189. package/dist/runner/index.d.ts +22 -2
  190. package/dist/runner/index.js +163 -13
  191. package/dist/runner/index.js.map +1 -1
  192. package/dist/sea/assemble.d.ts +29 -0
  193. package/dist/sea/assemble.js +129 -0
  194. package/dist/sea/assemble.js.map +1 -0
  195. package/dist/sea/bundle.d.ts +61 -0
  196. package/dist/sea/bundle.js +202 -0
  197. package/dist/sea/bundle.js.map +1 -0
  198. package/dist/sea/gtkx-config-module.d.ts +18 -0
  199. package/dist/sea/gtkx-config-module.js +67 -0
  200. package/dist/sea/gtkx-config-module.js.map +1 -0
  201. package/dist/sea/native-shim.d.ts +40 -0
  202. package/dist/sea/native-shim.js +121 -0
  203. package/dist/sea/native-shim.js.map +1 -0
  204. package/dist/sea/react-anchor-plugin.d.ts +2 -0
  205. package/dist/sea/react-anchor-plugin.js +30 -0
  206. package/dist/sea/react-anchor-plugin.js.map +1 -0
  207. package/dist/style/box-shadow.d.ts +7 -0
  208. package/dist/style/box-shadow.js +197 -0
  209. package/dist/style/box-shadow.js.map +1 -0
  210. package/dist/style/index.d.ts +3 -0
  211. package/dist/style/index.js +3 -0
  212. package/dist/style/index.js.map +1 -1
  213. package/dist/style/split-style.d.ts +5 -2
  214. package/dist/style/split-style.js +33 -5
  215. package/dist/style/split-style.js.map +1 -1
  216. package/dist/style/text-decoration.d.ts +15 -0
  217. package/dist/style/text-decoration.js +26 -0
  218. package/dist/style/text-decoration.js.map +1 -0
  219. package/dist/style/transform.d.ts +22 -0
  220. package/dist/style/transform.js +137 -0
  221. package/dist/style/transform.js.map +1 -0
  222. package/dist/style/visual-css.js +40 -3
  223. package/dist/style/visual-css.js.map +1 -1
  224. package/dist/svg/geometry.d.ts +19 -0
  225. package/dist/svg/geometry.js +80 -0
  226. package/dist/svg/geometry.js.map +1 -0
  227. package/dist/svg/gradient-geometry.d.ts +15 -0
  228. package/dist/svg/gradient-geometry.js +15 -0
  229. package/dist/svg/gradient-geometry.js.map +1 -0
  230. package/dist/svg/transform.d.ts +22 -0
  231. package/dist/svg/transform.js +74 -0
  232. package/dist/svg/transform.js.map +1 -0
  233. package/dist/svg/view-box.d.ts +34 -0
  234. package/dist/svg/view-box.js +108 -0
  235. package/dist/svg/view-box.js.map +1 -0
  236. package/dist/svg-compat/index.d.ts +1 -0
  237. package/dist/svg-compat/index.js +16 -0
  238. package/dist/svg-compat/index.js.map +1 -0
  239. package/dist/testing/index.d.ts +14 -0
  240. package/dist/testing/index.js +14 -0
  241. package/dist/testing/index.js.map +1 -0
  242. package/dist/vendor/react-native/pan-responder.d.ts +102 -0
  243. package/dist/vendor/react-native/pan-responder.js +196 -0
  244. package/dist/vendor/react-native/pan-responder.js.map +1 -0
  245. package/dist/vendor/react-native/touch-history-math.d.ts +18 -0
  246. package/dist/vendor/react-native/touch-history-math.js +102 -0
  247. package/dist/vendor/react-native/touch-history-math.js.map +1 -0
  248. package/dist/vite/index.d.ts +7 -3
  249. package/dist/vite/index.js +16 -4
  250. package/dist/vite/index.js.map +1 -1
  251. package/dist/vitest/index.d.ts +52 -0
  252. package/dist/vitest/index.js +58 -0
  253. package/dist/vitest/index.js.map +1 -0
  254. package/dist/vitest/setup.d.ts +4 -0
  255. package/dist/vitest/setup.js +22 -0
  256. package/dist/vitest/setup.js.map +1 -0
  257. package/package.json +52 -13
@@ -9,6 +9,12 @@ import { createInterpolator } from "./interpolate";
9
9
  const numeric = (value) => typeof value === "number" ? value : parseFloat(value);
10
10
  export class AnimatedValue {
11
11
  _value;
12
+ // RN splits a value into an animated part and a static offset: a drag sets
13
+ // the offset to where the last gesture ended, so dx/dy can keep starting
14
+ // from zero. Everything observable is the SUM; the animation runner only
15
+ // ever drives `_value`, so an untouched offset (0) leaves behaviour
16
+ // byte-identical to before it existed.
17
+ _offset = 0;
12
18
  _startingValue;
13
19
  _listeners = new Map();
14
20
  _nextListenerId = 1;
@@ -23,6 +29,23 @@ export class AnimatedValue {
23
29
  this._animation?.stop();
24
30
  this.__updateValue(value);
25
31
  }
32
+ /** Sets the static part. The animated part is left where it is. */
33
+ setOffset(offset) {
34
+ this._offset = offset;
35
+ this.__notify();
36
+ }
37
+ /** Folds the offset into the value, leaving the sum unchanged. */
38
+ flattenOffset() {
39
+ this._value += this._offset;
40
+ this._offset = 0;
41
+ this.__notify();
42
+ }
43
+ /** The mirror of flattenOffset: moves the value into the offset. */
44
+ extractOffset() {
45
+ this._offset += this._value;
46
+ this._value = 0;
47
+ this.__notify();
48
+ }
26
49
  addListener(listener) {
27
50
  const id = String(this._nextListenerId++);
28
51
  this._listeners.set(id, listener);
@@ -39,7 +62,7 @@ export class AnimatedValue {
39
62
  // { finished: false }.
40
63
  stopAnimation(callback) {
41
64
  this._animation?.stop();
42
- callback?.(this._value);
65
+ callback?.(this.__getValue());
43
66
  }
44
67
  // Stops any running animation, then snaps back to the construction-time
45
68
  // value. Unlike RN we do notify listeners about the snap-back: the direct
@@ -53,11 +76,16 @@ export class AnimatedValue {
53
76
  return new AnimatedInterpolation(this, config);
54
77
  }
55
78
  __getValue() {
56
- return this._value;
79
+ return this._value + this._offset;
57
80
  }
58
81
  /** @internal Called by the animation runner on every frame. */
59
82
  __updateValue(value) {
60
83
  this._value = value;
84
+ this.__notify();
85
+ }
86
+ /** @internal Publishes the current sum to every listener. */
87
+ __notify() {
88
+ const value = this.__getValue();
61
89
  for (const listener of [...this._listeners.values()]) {
62
90
  listener({ value });
63
91
  }
@@ -1 +1 @@
1
- {"version":3,"file":"value.js","sourceRoot":"","sources":["../../src/animated/value.ts"],"names":[],"mappings":"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","sourcesContent":["// Animated.Value and the read-only interpolation node. Values are observable\n// numbers; the animation runner (value-animation.ts) drives them frame by\n// frame through the __-prefixed internal hooks. Interpolation nodes subscribe\n// to their parent lazily (only while they have listeners themselves) and can\n// be interpolated again, cascading from the parent's numeric value.\n\nimport { createInterpolator } from \"./interpolate\"\nimport type {\n InterpolationConfig,\n InterpolationListener,\n ValueListener,\n} from \"./types\"\n\n// Internal handle a running animation registers on its value; the value calls\n// stop() to preempt it when a newer animation (or setValue) takes over — the\n// preempted animation ends with { finished: false }, matching RN.\nexport type AnimationHandle = { stop(): void }\n\n// Minimal parent protocol shared by AnimatedValue and AnimatedInterpolation,\n// enabling cascaded interpolate() chains over either kind of node.\ntype InterpolationParent = {\n __getValue(): number | string\n addListener(listener: InterpolationListener): string\n removeListener(id: string): void\n}\n\n// Cascading from a string-producing parent (\"45deg\") interpolates over its\n// numeric part.\nconst numeric = (value: number | string): number =>\n typeof value === \"number\" ? value : parseFloat(value)\n\nexport class AnimatedValue {\n private _value: number\n private readonly _startingValue: number\n private readonly _listeners = new Map<string, ValueListener>()\n private _nextListenerId = 1\n private _animation: AnimationHandle | null = null\n\n constructor(value: number) {\n this._value = value\n this._startingValue = value\n }\n\n // Stops the running animation (its callback gets { finished: false }, as in\n // RN) and jumps to the new value.\n setValue(value: number): void {\n this._animation?.stop()\n this.__updateValue(value)\n }\n\n addListener(listener: ValueListener): string {\n const id = String(this._nextListenerId++)\n this._listeners.set(id, listener)\n return id\n }\n\n removeListener(id: string): void {\n this._listeners.delete(id)\n }\n\n removeAllListeners(): void {\n this._listeners.clear()\n }\n\n // Stops the running animation where it stands and reports the current value\n // to the callback. The stopped animation's own callback gets\n // { finished: false }.\n stopAnimation(callback?: (value: number) => void): void {\n this._animation?.stop()\n callback?.(this._value)\n }\n\n // Stops any running animation, then snaps back to the construction-time\n // value. Unlike RN we do notify listeners about the snap-back: the direct\n // GTK path renders from listener events, so a silent reset would leave\n // widgets stale until the next animation frame.\n resetAnimation(callback?: (value: number) => void): void {\n this.stopAnimation(callback)\n this.__updateValue(this._startingValue)\n }\n\n interpolate(config: InterpolationConfig): AnimatedInterpolation {\n return new AnimatedInterpolation(this, config)\n }\n\n __getValue(): number {\n return this._value\n }\n\n /** @internal Called by the animation runner on every frame. */\n __updateValue(value: number): void {\n this._value = value\n for (const listener of [...this._listeners.values()]) {\n listener({ value })\n }\n }\n\n /** @internal Registers a running animation, preempting the previous one. */\n __startAnimation(handle: AnimationHandle): void {\n const previous = this._animation\n this._animation = handle\n if (previous && previous !== handle) {\n previous.stop()\n }\n }\n\n /** @internal */\n __endAnimation(handle: AnimationHandle): void {\n if (this._animation === handle) {\n this._animation = null\n }\n }\n}\n\nexport class AnimatedInterpolation {\n private readonly _parent: InterpolationParent\n private readonly _interpolator: (input: number) => number | string\n private readonly _listeners = new Map<string, InterpolationListener>()\n private _nextListenerId = 1\n private _parentSubscription: string | null = null\n\n constructor(parent: InterpolationParent, config: InterpolationConfig) {\n this._parent = parent\n this._interpolator = createInterpolator(config)\n }\n\n __getValue(): number | string {\n return this._interpolator(numeric(this._parent.__getValue()))\n }\n\n addListener(listener: InterpolationListener): string {\n const id = String(this._nextListenerId++)\n this._listeners.set(id, listener)\n if (this._parentSubscription === null) {\n // Lazy upstream subscription (same leak policy as the API emitters):\n // attach with the first listener, detach with the last one.\n this._parentSubscription = this._parent.addListener(({ value }) => {\n const output = this._interpolator(numeric(value))\n for (const entry of [...this._listeners.values()]) {\n entry({ value: output })\n }\n })\n }\n return id\n }\n\n removeListener(id: string): void {\n if (!this._listeners.delete(id)) {\n return\n }\n if (this._listeners.size === 0) {\n this._detachFromParent()\n }\n }\n\n removeAllListeners(): void {\n this._listeners.clear()\n this._detachFromParent()\n }\n\n interpolate(config: InterpolationConfig): AnimatedInterpolation {\n return new AnimatedInterpolation(this, config)\n }\n\n private _detachFromParent(): void {\n if (this._parentSubscription !== null) {\n this._parent.removeListener(this._parentSubscription)\n this._parentSubscription = null\n }\n }\n}\n"]}
1
+ {"version":3,"file":"value.js","sourceRoot":"","sources":["../../src/animated/value.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,0EAA0E;AAC1E,8EAA8E;AAC9E,6EAA6E;AAC7E,oEAAoE;AAEpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAoBlD,2EAA2E;AAC3E,gBAAgB;AAChB,MAAM,OAAO,GAAG,CAAC,KAAsB,EAAU,EAAE,CACjD,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;AAEvD,MAAM,OAAO,aAAa;IAChB,MAAM,CAAQ;IACtB,2EAA2E;IAC3E,yEAAyE;IACzE,yEAAyE;IACzE,oEAAoE;IACpE,uCAAuC;IAC/B,OAAO,GAAG,CAAC,CAAA;IACF,cAAc,CAAQ;IACtB,UAAU,GAAG,IAAI,GAAG,EAAyB,CAAA;IACtD,eAAe,GAAG,CAAC,CAAA;IACnB,UAAU,GAA2B,IAAI,CAAA;IAEjD,YAAY,KAAa;QACvB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAA;IAC7B,CAAC;IAED,4EAA4E;IAC5E,kCAAkC;IAClC,QAAQ,CAAC,KAAa;QACpB,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAA;QACvB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;IAED,mEAAmE;IACnE,SAAS,CAAC,MAAc;QACtB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,IAAI,CAAC,QAAQ,EAAE,CAAA;IACjB,CAAC;IAED,kEAAkE;IAClE,aAAa;QACX,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAA;QAC3B,IAAI,CAAC,OAAO,GAAG,CAAC,CAAA;QAChB,IAAI,CAAC,QAAQ,EAAE,CAAA;IACjB,CAAC;IAED,oEAAoE;IACpE,aAAa;QACX,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAA;QAC3B,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,QAAQ,EAAE,CAAA;IACjB,CAAC;IAED,WAAW,CAAC,QAAuB;QACjC,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;QACzC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;QACjC,OAAO,EAAE,CAAA;IACX,CAAC;IAED,cAAc,CAAC,EAAU;QACvB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAC5B,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;IACzB,CAAC;IAED,4EAA4E;IAC5E,6DAA6D;IAC7D,uBAAuB;IACvB,aAAa,CAAC,QAAkC;QAC9C,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAA;QACvB,QAAQ,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;IAC/B,CAAC;IAED,wEAAwE;IACxE,0EAA0E;IAC1E,uEAAuE;IACvE,gDAAgD;IAChD,cAAc,CAAC,QAAkC;QAC/C,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;QAC5B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IACzC,CAAC;IAED,WAAW,CAAC,MAA2B;QACrC,OAAO,IAAI,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAChD,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAA;IACnC,CAAC;IAED,+DAA+D;IAC/D,aAAa,CAAC,KAAa;QACzB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;QACnB,IAAI,CAAC,QAAQ,EAAE,CAAA;IACjB,CAAC;IAED,6DAA6D;IACrD,QAAQ;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA;QAC/B,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;YACrD,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QACrB,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,gBAAgB,CAAC,MAAuB;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAA;QAChC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAA;QACxB,IAAI,QAAQ,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YACpC,QAAQ,CAAC,IAAI,EAAE,CAAA;QACjB,CAAC;IACH,CAAC;IAED,gBAAgB;IAChB,cAAc,CAAC,MAAuB;QACpC,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;YAC/B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QACxB,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,qBAAqB;IACf,OAAO,CAAqB;IAC5B,aAAa,CAAoC;IACjD,UAAU,GAAG,IAAI,GAAG,EAAiC,CAAA;IAC9D,eAAe,GAAG,CAAC,CAAA;IACnB,mBAAmB,GAAkB,IAAI,CAAA;IAEjD,YAAY,MAA2B,EAAE,MAA2B;QAClE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,IAAI,CAAC,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;IACjD,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAA;IAC/D,CAAC;IAED,WAAW,CAAC,QAA+B;QACzC,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAA;QACzC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;QACjC,IAAI,IAAI,CAAC,mBAAmB,KAAK,IAAI,EAAE,CAAC;YACtC,qEAAqE;YACrE,4DAA4D;YAC5D,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;gBAChE,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;gBACjD,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;oBAClD,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;gBAC1B,CAAC;YACH,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;IAED,cAAc,CAAC,EAAU;QACvB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YAChC,OAAM;QACR,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,iBAAiB,EAAE,CAAA;QAC1B,CAAC;IACH,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;QACvB,IAAI,CAAC,iBAAiB,EAAE,CAAA;IAC1B,CAAC;IAED,WAAW,CAAC,MAA2B;QACrC,OAAO,IAAI,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAChD,CAAC;IAEO,iBAAiB;QACvB,IAAI,IAAI,CAAC,mBAAmB,KAAK,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;YACrD,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAA;QACjC,CAAC;IACH,CAAC;CACF","sourcesContent":["// Animated.Value and the read-only interpolation node. Values are observable\n// numbers; the animation runner (value-animation.ts) drives them frame by\n// frame through the __-prefixed internal hooks. Interpolation nodes subscribe\n// to their parent lazily (only while they have listeners themselves) and can\n// be interpolated again, cascading from the parent's numeric value.\n\nimport { createInterpolator } from \"./interpolate\"\nimport type {\n InterpolationConfig,\n InterpolationListener,\n ValueListener,\n} from \"./types\"\n\n// Internal handle a running animation registers on its value; the value calls\n// stop() to preempt it when a newer animation (or setValue) takes over — the\n// preempted animation ends with { finished: false }, matching RN.\nexport type AnimationHandle = { stop(): void }\n\n// Minimal parent protocol shared by AnimatedValue and AnimatedInterpolation,\n// enabling cascaded interpolate() chains over either kind of node.\ntype InterpolationParent = {\n __getValue(): number | string\n addListener(listener: InterpolationListener): string\n removeListener(id: string): void\n}\n\n// Cascading from a string-producing parent (\"45deg\") interpolates over its\n// numeric part.\nconst numeric = (value: number | string): number =>\n typeof value === \"number\" ? value : parseFloat(value)\n\nexport class AnimatedValue {\n private _value: number\n // RN splits a value into an animated part and a static offset: a drag sets\n // the offset to where the last gesture ended, so dx/dy can keep starting\n // from zero. Everything observable is the SUM; the animation runner only\n // ever drives `_value`, so an untouched offset (0) leaves behaviour\n // byte-identical to before it existed.\n private _offset = 0\n private readonly _startingValue: number\n private readonly _listeners = new Map<string, ValueListener>()\n private _nextListenerId = 1\n private _animation: AnimationHandle | null = null\n\n constructor(value: number) {\n this._value = value\n this._startingValue = value\n }\n\n // Stops the running animation (its callback gets { finished: false }, as in\n // RN) and jumps to the new value.\n setValue(value: number): void {\n this._animation?.stop()\n this.__updateValue(value)\n }\n\n /** Sets the static part. The animated part is left where it is. */\n setOffset(offset: number): void {\n this._offset = offset\n this.__notify()\n }\n\n /** Folds the offset into the value, leaving the sum unchanged. */\n flattenOffset(): void {\n this._value += this._offset\n this._offset = 0\n this.__notify()\n }\n\n /** The mirror of flattenOffset: moves the value into the offset. */\n extractOffset(): void {\n this._offset += this._value\n this._value = 0\n this.__notify()\n }\n\n addListener(listener: ValueListener): string {\n const id = String(this._nextListenerId++)\n this._listeners.set(id, listener)\n return id\n }\n\n removeListener(id: string): void {\n this._listeners.delete(id)\n }\n\n removeAllListeners(): void {\n this._listeners.clear()\n }\n\n // Stops the running animation where it stands and reports the current value\n // to the callback. The stopped animation's own callback gets\n // { finished: false }.\n stopAnimation(callback?: (value: number) => void): void {\n this._animation?.stop()\n callback?.(this.__getValue())\n }\n\n // Stops any running animation, then snaps back to the construction-time\n // value. Unlike RN we do notify listeners about the snap-back: the direct\n // GTK path renders from listener events, so a silent reset would leave\n // widgets stale until the next animation frame.\n resetAnimation(callback?: (value: number) => void): void {\n this.stopAnimation(callback)\n this.__updateValue(this._startingValue)\n }\n\n interpolate(config: InterpolationConfig): AnimatedInterpolation {\n return new AnimatedInterpolation(this, config)\n }\n\n __getValue(): number {\n return this._value + this._offset\n }\n\n /** @internal Called by the animation runner on every frame. */\n __updateValue(value: number): void {\n this._value = value\n this.__notify()\n }\n\n /** @internal Publishes the current sum to every listener. */\n private __notify(): void {\n const value = this.__getValue()\n for (const listener of [...this._listeners.values()]) {\n listener({ value })\n }\n }\n\n /** @internal Registers a running animation, preempting the previous one. */\n __startAnimation(handle: AnimationHandle): void {\n const previous = this._animation\n this._animation = handle\n if (previous && previous !== handle) {\n previous.stop()\n }\n }\n\n /** @internal */\n __endAnimation(handle: AnimationHandle): void {\n if (this._animation === handle) {\n this._animation = null\n }\n }\n}\n\nexport class AnimatedInterpolation {\n private readonly _parent: InterpolationParent\n private readonly _interpolator: (input: number) => number | string\n private readonly _listeners = new Map<string, InterpolationListener>()\n private _nextListenerId = 1\n private _parentSubscription: string | null = null\n\n constructor(parent: InterpolationParent, config: InterpolationConfig) {\n this._parent = parent\n this._interpolator = createInterpolator(config)\n }\n\n __getValue(): number | string {\n return this._interpolator(numeric(this._parent.__getValue()))\n }\n\n addListener(listener: InterpolationListener): string {\n const id = String(this._nextListenerId++)\n this._listeners.set(id, listener)\n if (this._parentSubscription === null) {\n // Lazy upstream subscription (same leak policy as the API emitters):\n // attach with the first listener, detach with the last one.\n this._parentSubscription = this._parent.addListener(({ value }) => {\n const output = this._interpolator(numeric(value))\n for (const entry of [...this._listeners.values()]) {\n entry({ value: output })\n }\n })\n }\n return id\n }\n\n removeListener(id: string): void {\n if (!this._listeners.delete(id)) {\n return\n }\n if (this._listeners.size === 0) {\n this._detachFromParent()\n }\n }\n\n removeAllListeners(): void {\n this._listeners.clear()\n this._detachFromParent()\n }\n\n interpolate(config: InterpolationConfig): AnimatedInterpolation {\n return new AnimatedInterpolation(this, config)\n }\n\n private _detachFromParent(): void {\n if (this._parentSubscription !== null) {\n this._parent.removeListener(this._parentSubscription)\n this._parentSubscription = null\n }\n }\n}\n"]}
@@ -0,0 +1,69 @@
1
+ import type { ReactNode } from "react";
2
+ import { type IntrinsicRootProps, type NestedRootProps } from "../components/root";
3
+ /**
4
+ * React Native content that FILLS its slot.
5
+ *
6
+ * Use it for the body of a page, a split-view pane, a dialog — anywhere the
7
+ * widget hands out a rectangle and the RN tree should lay out inside it.
8
+ *
9
+ * ```tsx
10
+ * <NavigationStackPage tag="home" title="Home">
11
+ * <SlotContent>
12
+ * <View style={{ flex: 1 }}>…</View>
13
+ * </SlotContent>
14
+ * </NavigationStackPage>
15
+ * ```
16
+ */
17
+ export declare const SlotContent: ({ children }: NestedRootProps) => React.JSX.Element;
18
+ export type SlotContentProps = NestedRootProps;
19
+ /**
20
+ * React Native content SIZED BY ITSELF.
21
+ *
22
+ * The content's own Yoga size becomes the slot size, which is what a
23
+ * HeaderBar slot, a toolbar button area or a list row needs — the widget asks
24
+ * "how big are you?" and the RN tree answers.
25
+ *
26
+ * ```tsx
27
+ * <AdwHeaderBar
28
+ * start={<IntrinsicContent><SearchField /></IntrinsicContent>}
29
+ * />
30
+ * ```
31
+ */
32
+ export declare const IntrinsicContent: ({ children }: IntrinsicRootProps) => React.JSX.Element;
33
+ export type IntrinsicContentProps = IntrinsicRootProps;
34
+ /**
35
+ * A HeaderBar slot's React Native content.
36
+ *
37
+ * {@link IntrinsicContent} on its own is not enough for a header slot: a
38
+ * Yoga root defaults to React Native's `column` direction, so two buttons
39
+ * handed to `headerLeft` stack vertically and push the HeaderBar to twice
40
+ * its height — with the window controls left stranded on the lower row.
41
+ * A GTK header slot is horizontal by definition (`gtk_header_bar_pack_start`
42
+ * appends along one axis), and react-navigation's `headerLeft`/`headerRight`
43
+ * mean a horizontal cluster on every other platform too, so the row is the
44
+ * correct default rather than a workaround.
45
+ *
46
+ * The 6px gap matches AdwHeaderBar's own spacing between packed children,
47
+ * so a slot built from RN content sits flush with buttons packed natively
48
+ * beside it.
49
+ */
50
+ export declare const HeaderSlotContent: ({ children }: {
51
+ children?: ReactNode;
52
+ }) => React.JSX.Element;
53
+ /**
54
+ * A slot whose children are GTK WIDGETS, not React Native content.
55
+ *
56
+ * Clears the enclosing layout root so the widgets from `react-native-gtkx/gtk`
57
+ * and `/adw` render bare — the same thing they already do outside any React
58
+ * Native tree. Without this, a widget under an ancestor root is a Yoga LEAF:
59
+ * it is measured for its own natural size and its own widget children never
60
+ * reach it, which shows up as a container that renders its first child and
61
+ * silently drops the rest.
62
+ *
63
+ * Use it wherever GTK chrome should own the layout — a page body that is a
64
+ * `GtkScrolledWindow` around a `.boxed-list`, say. React Native content
65
+ * nested further down opts back in with {@link SlotContent}.
66
+ */
67
+ export declare const WidgetContent: ({ children }: {
68
+ children?: ReactNode;
69
+ }) => React.JSX.Element;
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // View and StyleSheet come from this package's own modules, never from the
3
+ // bare public specifier: this package IS that module on the linux platform,
4
+ // so importing it here would alias back to itself and Metro would try to
5
+ // bundle it (tests/unit/metro-preset.test.ts pins that down).
6
+ import { HostNodeContext } from "../components/host-node";
7
+ import { IntrinsicRoot, NestedRoot, } from "../components/root";
8
+ import { View } from "../components/view";
9
+ import { StyleSheet } from "../style/index";
10
+ /**
11
+ * React Native content that FILLS its slot.
12
+ *
13
+ * Use it for the body of a page, a split-view pane, a dialog — anywhere the
14
+ * widget hands out a rectangle and the RN tree should lay out inside it.
15
+ *
16
+ * ```tsx
17
+ * <NavigationStackPage tag="home" title="Home">
18
+ * <SlotContent>
19
+ * <View style={{ flex: 1 }}>…</View>
20
+ * </SlotContent>
21
+ * </NavigationStackPage>
22
+ * ```
23
+ */
24
+ export const SlotContent = NestedRoot;
25
+ /**
26
+ * React Native content SIZED BY ITSELF.
27
+ *
28
+ * The content's own Yoga size becomes the slot size, which is what a
29
+ * HeaderBar slot, a toolbar button area or a list row needs — the widget asks
30
+ * "how big are you?" and the RN tree answers.
31
+ *
32
+ * ```tsx
33
+ * <AdwHeaderBar
34
+ * start={<IntrinsicContent><SearchField /></IntrinsicContent>}
35
+ * />
36
+ * ```
37
+ */
38
+ export const IntrinsicContent = IntrinsicRoot;
39
+ /**
40
+ * A HeaderBar slot's React Native content.
41
+ *
42
+ * {@link IntrinsicContent} on its own is not enough for a header slot: a
43
+ * Yoga root defaults to React Native's `column` direction, so two buttons
44
+ * handed to `headerLeft` stack vertically and push the HeaderBar to twice
45
+ * its height — with the window controls left stranded on the lower row.
46
+ * A GTK header slot is horizontal by definition (`gtk_header_bar_pack_start`
47
+ * appends along one axis), and react-navigation's `headerLeft`/`headerRight`
48
+ * mean a horizontal cluster on every other platform too, so the row is the
49
+ * correct default rather than a workaround.
50
+ *
51
+ * The 6px gap matches AdwHeaderBar's own spacing between packed children,
52
+ * so a slot built from RN content sits flush with buttons packed natively
53
+ * beside it.
54
+ */
55
+ export const HeaderSlotContent = ({ children }) => (_jsx(IntrinsicContent, { children: _jsx(View, { style: headerSlotStyles.row, children: children }) }));
56
+ const headerSlotStyles = StyleSheet.create({
57
+ // alignSelf keeps the row HUGGING its buttons. A Yoga root stretches its
58
+ // children across its own width by default, which a HeaderBar reads back
59
+ // as "this slot wants all of it" — the centred title then sits off centre
60
+ // and packed buttons drift apart. A header slot is content-sized on every
61
+ // platform; this is what says so.
62
+ row: {
63
+ flexDirection: "row",
64
+ alignItems: "center",
65
+ alignSelf: "center",
66
+ gap: 6,
67
+ },
68
+ });
69
+ /**
70
+ * A slot whose children are GTK WIDGETS, not React Native content.
71
+ *
72
+ * Clears the enclosing layout root so the widgets from `react-native-gtkx/gtk`
73
+ * and `/adw` render bare — the same thing they already do outside any React
74
+ * Native tree. Without this, a widget under an ancestor root is a Yoga LEAF:
75
+ * it is measured for its own natural size and its own widget children never
76
+ * reach it, which shows up as a container that renders its first child and
77
+ * silently drops the rest.
78
+ *
79
+ * Use it wherever GTK chrome should own the layout — a page body that is a
80
+ * `GtkScrolledWindow` around a `.boxed-list`, say. React Native content
81
+ * nested further down opts back in with {@link SlotContent}.
82
+ */
83
+ export const WidgetContent = ({ children }) => (_jsx(HostNodeContext.Provider, { value: null, children: children }));
84
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/common/content.tsx"],"names":[],"mappings":";AAQA,2EAA2E;AAC3E,4EAA4E;AAC5E,yEAAyE;AACzE,8DAA8D;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EACL,aAAa,EACb,UAAU,GAGX,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE3C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAA;AAGrC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAA;AAG7C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAAE,QAAQ,EAA4B,EAAE,EAAE,CAAC,CAC3E,KAAC,gBAAgB,cACf,KAAC,IAAI,IAAC,KAAK,EAAE,gBAAgB,CAAC,GAAG,YAAG,QAAQ,GAAQ,GACnC,CACpB,CAAA;AAED,MAAM,gBAAgB,GAAG,UAAU,CAAC,MAAM,CAAC;IACzC,yEAAyE;IACzE,yEAAyE;IACzE,0EAA0E;IAC1E,0EAA0E;IAC1E,kCAAkC;IAClC,GAAG,EAAE;QACH,aAAa,EAAE,KAAK;QACpB,UAAU,EAAE,QAAQ;QACpB,SAAS,EAAE,QAAQ;QACnB,GAAG,EAAE,CAAC;KACP;CACF,CAAC,CAAA;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,QAAQ,EAA4B,EAAE,EAAE,CAAC,CACvE,KAAC,eAAe,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAAG,QAAQ,GAA4B,CAC7E,CAAA","sourcesContent":["// Putting React Native content into a GTK widget slot.\n//\n// The Adwaita primitives in this subpath are widget bindings: their children\n// are widgets. React Native content is a different thing — it needs a layout\n// root that runs Yoga and reports a size. These two components are that\n// bridge, and they are what makes \"GTK chrome around RN content\" work\n// anywhere, not just inside our navigators.\nimport type { ReactNode } from \"react\"\n// View and StyleSheet come from this package's own modules, never from the\n// bare public specifier: this package IS that module on the linux platform,\n// so importing it here would alias back to itself and Metro would try to\n// bundle it (tests/unit/metro-preset.test.ts pins that down).\nimport { HostNodeContext } from \"../components/host-node\"\nimport {\n IntrinsicRoot,\n NestedRoot,\n type IntrinsicRootProps,\n type NestedRootProps,\n} from \"../components/root\"\nimport { View } from \"../components/view\"\nimport { StyleSheet } from \"../style/index\"\n\n/**\n * React Native content that FILLS its slot.\n *\n * Use it for the body of a page, a split-view pane, a dialog — anywhere the\n * widget hands out a rectangle and the RN tree should lay out inside it.\n *\n * ```tsx\n * <NavigationStackPage tag=\"home\" title=\"Home\">\n * <SlotContent>\n * <View style={{ flex: 1 }}>…</View>\n * </SlotContent>\n * </NavigationStackPage>\n * ```\n */\nexport const SlotContent = NestedRoot\nexport type SlotContentProps = NestedRootProps\n\n/**\n * React Native content SIZED BY ITSELF.\n *\n * The content's own Yoga size becomes the slot size, which is what a\n * HeaderBar slot, a toolbar button area or a list row needs — the widget asks\n * \"how big are you?\" and the RN tree answers.\n *\n * ```tsx\n * <AdwHeaderBar\n * start={<IntrinsicContent><SearchField /></IntrinsicContent>}\n * />\n * ```\n */\nexport const IntrinsicContent = IntrinsicRoot\nexport type IntrinsicContentProps = IntrinsicRootProps\n\n/**\n * A HeaderBar slot's React Native content.\n *\n * {@link IntrinsicContent} on its own is not enough for a header slot: a\n * Yoga root defaults to React Native's `column` direction, so two buttons\n * handed to `headerLeft` stack vertically and push the HeaderBar to twice\n * its height — with the window controls left stranded on the lower row.\n * A GTK header slot is horizontal by definition (`gtk_header_bar_pack_start`\n * appends along one axis), and react-navigation's `headerLeft`/`headerRight`\n * mean a horizontal cluster on every other platform too, so the row is the\n * correct default rather than a workaround.\n *\n * The 6px gap matches AdwHeaderBar's own spacing between packed children,\n * so a slot built from RN content sits flush with buttons packed natively\n * beside it.\n */\nexport const HeaderSlotContent = ({ children }: { children?: ReactNode }) => (\n <IntrinsicContent>\n <View style={headerSlotStyles.row}>{children}</View>\n </IntrinsicContent>\n)\n\nconst headerSlotStyles = StyleSheet.create({\n // alignSelf keeps the row HUGGING its buttons. A Yoga root stretches its\n // children across its own width by default, which a HeaderBar reads back\n // as \"this slot wants all of it\" — the centred title then sits off centre\n // and packed buttons drift apart. A header slot is content-sized on every\n // platform; this is what says so.\n row: {\n flexDirection: \"row\",\n alignItems: \"center\",\n alignSelf: \"center\",\n gap: 6,\n },\n})\n\n/**\n * A slot whose children are GTK WIDGETS, not React Native content.\n *\n * Clears the enclosing layout root so the widgets from `react-native-gtkx/gtk`\n * and `/adw` render bare — the same thing they already do outside any React\n * Native tree. Without this, a widget under an ancestor root is a Yoga LEAF:\n * it is measured for its own natural size and its own widget children never\n * reach it, which shows up as a container that renders its first child and\n * silently drops the rest.\n *\n * Use it wherever GTK chrome should own the layout — a page body that is a\n * `GtkScrolledWindow` around a `.boxed-list`, say. React Native content\n * nested further down opts back in with {@link SlotContent}.\n */\nexport const WidgetContent = ({ children }: { children?: ReactNode }) => (\n <HostNodeContext.Provider value={null}>{children}</HostNodeContext.Provider>\n)\n"]}
@@ -0,0 +1,23 @@
1
+ import type { ReactNode } from "react";
2
+ import type { StyleProp } from "../contracts";
3
+ export type IconProps = {
4
+ /** Icon-theme name, e.g. `"starred-symbolic"`. Symbolic icons take their
5
+ * colour from the surrounding label colour. */
6
+ name: string;
7
+ /** Square size in RN units. Defaults to 16, the size Adwaita uses for icons
8
+ * inside list rows and flat buttons. */
9
+ size?: number;
10
+ /** React Native style. Sizing here wins over `size`. */
11
+ style?: StyleProp;
12
+ testID?: string;
13
+ };
14
+ /**
15
+ * ```tsx
16
+ * <Icon name="starred-symbolic" size={16} />
17
+ * ```
18
+ *
19
+ * Sized through `pixel-size` as well as through Yoga: GTK would otherwise pick
20
+ * the nearest theme size and paint at that, so a 16-unit box could hold a
21
+ * 24px icon scaled down.
22
+ */
23
+ export declare const Icon: ({ name, size, style, testID, }: IconProps) => ReactNode;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { GtkImage } from "../gtkx/bridge/index";
3
+ import { Widget } from "./widget";
4
+ /**
5
+ * ```tsx
6
+ * <Icon name="starred-symbolic" size={16} />
7
+ * ```
8
+ *
9
+ * Sized through `pixel-size` as well as through Yoga: GTK would otherwise pick
10
+ * the nearest theme size and paint at that, so a 16-unit box could hold a
11
+ * 24px icon scaled down.
12
+ */
13
+ export const Icon = ({ name, size = 16, style, testID, }) => (_jsx(Widget, { testID: testID, style: [{ width: size, height: size }, style], children: _jsx(GtkImage, { iconName: name, pixelSize: size }) }));
14
+ //# sourceMappingURL=icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon.js","sourceRoot":"","sources":["../../src/common/icon.tsx"],"names":[],"mappings":";AAeA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAcjC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EACnB,IAAI,EACJ,IAAI,GAAG,EAAE,EACT,KAAK,EACL,MAAM,GACI,EAAa,EAAE,CAAC,CAC1B,KAAC,MAAM,IACL,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,YAE7C,KAAC,QAAQ,IACP,QAAQ,EAAE,IAAI,EACd,SAAS,EAAE,IAAI,GACf,GACK,CACV,CAAA","sourcesContent":["// A named icon from the desktop icon theme, in React Native layout.\n//\n// WHY this is not `Image`. RN's `Image` takes a file path or a URI, because on\n// iOS and Android an icon is an asset the app ships. On the Linux desktop an\n// icon is a NAME resolved against the current icon theme at paint time —\n// `user-trash-symbolic` recolours itself with the label colour, follows the\n// user's theme, and has no file the app could point at. There is nothing in\n// RN's `Image` contract that can express that, and pretending a name is a URI\n// would break `onError`, `resizeMode` and the loading states along with it.\n//\n// So this is the same shape RN apps already reach for on every platform —\n// react-native-vector-icons' `<Icon name size color />` — with the desktop\n// icon theme behind it instead of a bundled font.\nimport type { ReactNode } from \"react\"\nimport type { StyleProp } from \"../contracts\"\nimport { GtkImage } from \"../gtkx/bridge/index\"\nimport { Widget } from \"./widget\"\n\nexport type IconProps = {\n /** Icon-theme name, e.g. `\"starred-symbolic\"`. Symbolic icons take their\n * colour from the surrounding label colour. */\n name: string\n /** Square size in RN units. Defaults to 16, the size Adwaita uses for icons\n * inside list rows and flat buttons. */\n size?: number\n /** React Native style. Sizing here wins over `size`. */\n style?: StyleProp\n testID?: string\n}\n\n/**\n * ```tsx\n * <Icon name=\"starred-symbolic\" size={16} />\n * ```\n *\n * Sized through `pixel-size` as well as through Yoga: GTK would otherwise pick\n * the nearest theme size and paint at that, so a 16-unit box could hold a\n * 24px icon scaled down.\n */\nexport const Icon = ({\n name,\n size = 16,\n style,\n testID,\n}: IconProps): ReactNode => (\n <Widget\n testID={testID}\n style={[{ width: size, height: size }, style]}\n >\n <GtkImage\n iconName={name}\n pixelSize={size}\n />\n </Widget>\n)\n"]}
@@ -0,0 +1,5 @@
1
+ export { NavigationStack, NavigationStackPage, type NavigationStackPageProps, type NavigationStackProps, } from "./navigation-stack";
2
+ export { HeaderSlotContent, IntrinsicContent, SlotContent, WidgetContent, type IntrinsicContentProps, type SlotContentProps, } from "./content";
3
+ export { useWidgetLayout, Widget, wrapReactNative, type ReactNativeLayoutProps, type UseWidgetLayoutOptions, type WidgetProps, } from "./widget";
4
+ export { Icon, type IconProps } from "./icon";
5
+ export { List, ListRow, ListSeparator, rowPosition, type ListProps, type ListRowPosition, type ListRowProps, } from "./list";
@@ -0,0 +1,21 @@
1
+ // react-native-gtkx/common — the parts of the platform layer we wrote.
2
+ //
3
+ // The other two subpaths are widget bindings: react-native-gtkx/gtk and
4
+ // react-native-gtkx/adw re-export what gtkx generates, name for name. This
5
+ // one holds what has no upstream counterpart, which is why nothing here
6
+ // carries a `Gtk` or `Adw` prefix.
7
+ //
8
+ // Two jobs live here. Getting React Native content INTO a GTK slot
9
+ // (SlotContent, IntrinsicContent), and getting a GTK widget INTO React
10
+ // Native layout (Widget, wrapReactNative, useWidgetLayout). Plus
11
+ // NavigationStack, which is a declarative component over an imperative
12
+ // widget rather than a binding of one — a different contract from
13
+ // Adw.NavigationView, which is why it has its own name and lives apart.
14
+ //
15
+ // Nothing here imports react-navigation.
16
+ export { NavigationStack, NavigationStackPage, } from "./navigation-stack";
17
+ export { HeaderSlotContent, IntrinsicContent, SlotContent, WidgetContent, } from "./content";
18
+ export { useWidgetLayout, Widget, wrapReactNative, } from "./widget";
19
+ export { Icon } from "./icon";
20
+ export { List, ListRow, ListSeparator, rowPosition, } from "./list";
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,wEAAwE;AACxE,2EAA2E;AAC3E,wEAAwE;AACxE,mCAAmC;AACnC,EAAE;AACF,mEAAmE;AACnE,uEAAuE;AACvE,iEAAiE;AACjE,uEAAuE;AACvE,kEAAkE;AAClE,wEAAwE;AACxE,EAAE;AACF,yCAAyC;AAEzC,OAAO,EACL,eAAe,EACf,mBAAmB,GAGpB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,aAAa,GAGd,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,eAAe,EACf,MAAM,EACN,eAAe,GAIhB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,IAAI,EAAkB,MAAM,QAAQ,CAAA;AAE7C,OAAO,EACL,IAAI,EACJ,OAAO,EACP,aAAa,EACb,WAAW,GAIZ,MAAM,QAAQ,CAAA","sourcesContent":["// react-native-gtkx/common — the parts of the platform layer we wrote.\n//\n// The other two subpaths are widget bindings: react-native-gtkx/gtk and\n// react-native-gtkx/adw re-export what gtkx generates, name for name. This\n// one holds what has no upstream counterpart, which is why nothing here\n// carries a `Gtk` or `Adw` prefix.\n//\n// Two jobs live here. Getting React Native content INTO a GTK slot\n// (SlotContent, IntrinsicContent), and getting a GTK widget INTO React\n// Native layout (Widget, wrapReactNative, useWidgetLayout). Plus\n// NavigationStack, which is a declarative component over an imperative\n// widget rather than a binding of one — a different contract from\n// Adw.NavigationView, which is why it has its own name and lives apart.\n//\n// Nothing here imports react-navigation.\n\nexport {\n NavigationStack,\n NavigationStackPage,\n type NavigationStackPageProps,\n type NavigationStackProps,\n} from \"./navigation-stack\"\n\nexport {\n HeaderSlotContent,\n IntrinsicContent,\n SlotContent,\n WidgetContent,\n type IntrinsicContentProps,\n type SlotContentProps,\n} from \"./content\"\n\nexport {\n useWidgetLayout,\n Widget,\n wrapReactNative,\n type ReactNativeLayoutProps,\n type UseWidgetLayoutOptions,\n type WidgetProps,\n} from \"./widget\"\n\nexport { Icon, type IconProps } from \"./icon\"\n\nexport {\n List,\n ListRow,\n ListSeparator,\n rowPosition,\n type ListProps,\n type ListRowPosition,\n type ListRowProps,\n} from \"./list\"\n"]}
@@ -0,0 +1,82 @@
1
+ import { type ReactNode } from "react";
2
+ import type { StyleProp } from "../contracts";
3
+ /**
4
+ * Where a row sits in its list, which is what decides its corner radii and
5
+ * whether it draws a separator under itself.
6
+ *
7
+ * RN has no `:first-child`, so this is explicit. From a `FlatList` it is
8
+ * `rowPosition(index, data.length)`; from a static list it is the same
9
+ * expression over the array.
10
+ */
11
+ export type ListRowPosition = "first" | "middle" | "last" | "only";
12
+ /** The usual derivation, so no call site has to get the one-row case wrong. */
13
+ export declare const rowPosition: (index: number, count: number) => ListRowPosition;
14
+ export type ListProps = {
15
+ children?: ReactNode;
16
+ style?: StyleProp;
17
+ testID?: string;
18
+ };
19
+ /**
20
+ * The `.boxed-list` frame: a rounded, shadowed card. Put `ListRow`s in it
21
+ * directly, or a `FlatList` whose `renderItem` returns them.
22
+ *
23
+ * ```tsx
24
+ * <List>
25
+ * {tasks.map((task, index) => (
26
+ * <ListRow
27
+ * key={task.id}
28
+ * title={task.title}
29
+ * position={rowPosition(index, tasks.length)}
30
+ * onPress={() => open(task)}
31
+ * />
32
+ * ))}
33
+ * </List>
34
+ * ```
35
+ */
36
+ export declare const List: ({ children, style, testID }: ListProps) => ReactNode;
37
+ export type ListRowProps = {
38
+ /** Primary line. A string renders with the row's own typography; a node is
39
+ * rendered as given, for a title that needs its own styling. */
40
+ title?: ReactNode;
41
+ /** Second, dimmed line. Omitted rows are single-line, as `AdwActionRow`'s
42
+ * are. */
43
+ subtitle?: ReactNode;
44
+ /** Leading content — a checkbox, an icon, a colour swatch. */
45
+ prefix?: ReactNode;
46
+ /** Trailing content — buttons, a value, a chevron. */
47
+ suffix?: ReactNode;
48
+ /** Makes the row activatable: it gains the hover and press tints and calls
49
+ * this. Without it the row is inert, like a non-`activatable`
50
+ * `AdwActionRow`. */
51
+ onPress?: () => void;
52
+ /** Position in the list, for the corner radii and the separator. Defaults
53
+ * to `"middle"`, which is right for a row that is neither. */
54
+ position?: ListRowPosition;
55
+ /** Draw the hairline under this row. Default true for every position except
56
+ * the last — set it false when the list supplies its own separators (a
57
+ * `FlatList`'s `ItemSeparatorComponent`, say). */
58
+ separator?: boolean;
59
+ style?: StyleProp;
60
+ testID?: string;
61
+ };
62
+ /**
63
+ * One row of a {@link List} — `AdwActionRow`'s layout and states, built from
64
+ * `Pressable`, `View` and `Text`.
65
+ *
66
+ * Hover and press come from `Pressable`'s state callback, so they cost what
67
+ * they cost anywhere else in this platform: the hover path swaps a CSS class
68
+ * on the widget without a React render (see components/pressable.tsx).
69
+ *
70
+ * **Not yet:** keyboard navigation between rows and a focus ring.
71
+ * `GtkListBox` implements those as widget behaviour and RN has no focus model
72
+ * for `View` to hang them on — `Pressable`'s state is `{pressed, hovered}`
73
+ * with no `focused`. The ring itself is now drawable (`outlineWidth` and
74
+ * friends), so what is missing is the state, not the paint.
75
+ */
76
+ export declare const ListRow: ({ title, subtitle, prefix, suffix, onPress, position, separator, style, testID, }: ListRowProps) => ReactNode;
77
+ /**
78
+ * The hairline between two rows, for lists that draw their own separators —
79
+ * a `FlatList`'s `ItemSeparatorComponent` is exactly this, and using it means
80
+ * the rows themselves stay position-agnostic apart from their corners.
81
+ */
82
+ export declare const ListSeparator: () => ReactNode;
@@ -0,0 +1,166 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useColorScheme } from "../apis/index";
3
+ import { Pressable } from "../components/pressable";
4
+ import { Text } from "../components/text";
5
+ import { View } from "../components/view";
6
+ import { PlatformColor, StyleSheet } from "../style/index";
7
+ /** The usual derivation, so no call site has to get the one-row case wrong. */
8
+ export const rowPosition = (index, count) => {
9
+ const first = index === 0;
10
+ const last = index === count - 1;
11
+ if (first && last) {
12
+ return "only";
13
+ }
14
+ return first ? "first" : last ? "last" : "middle";
15
+ };
16
+ // libadwaita 1.9, /org/gnome/Adwaita/styles/gtk.css:
17
+ // list.boxed-list { background-color: var(--card-bg-color); border-radius: 12px;
18
+ // box-shadow: 0 0 0 1px RGB(0 0 6/3%),
19
+ // 0 1px 3px 1px RGB(0 0 6/7%),
20
+ // 0 2px 6px 2px RGB(0 0 6/3%); }
21
+ const RADIUS = 12;
22
+ const styles = StyleSheet.create({
23
+ list: {
24
+ backgroundColor: PlatformColor("card-bg-color"),
25
+ borderRadius: RADIUS,
26
+ // The frame is a shadow, not a border, and that distinction is load
27
+ // bearing: a border would consume the box and inset every row by a pixel,
28
+ // and no border draws the two soft drops underneath.
29
+ boxShadow: [
30
+ {
31
+ offsetX: 0,
32
+ offsetY: 0,
33
+ spreadDistance: 1,
34
+ color: "rgba(0, 0, 6, 0.03)",
35
+ },
36
+ {
37
+ offsetX: 0,
38
+ offsetY: 1,
39
+ blurRadius: 3,
40
+ spreadDistance: 1,
41
+ color: "rgba(0, 0, 6, 0.07)",
42
+ },
43
+ {
44
+ offsetX: 0,
45
+ offsetY: 2,
46
+ blurRadius: 6,
47
+ spreadDistance: 2,
48
+ color: "rgba(0, 0, 6, 0.03)",
49
+ },
50
+ ],
51
+ },
52
+ // `list > row { padding: 2px }` plus
53
+ // `row > box.header { margin: 0 12px; border-spacing: 6px; min-height: 50px }`
54
+ // — 2 + 50 + 2 + the 1px separator is the 55px row pitch measured off the
55
+ // widget's own screenshot.
56
+ row: {
57
+ flexDirection: "row",
58
+ alignItems: "center",
59
+ minHeight: 54,
60
+ paddingVertical: 2,
61
+ paddingHorizontal: 14,
62
+ gap: 6,
63
+ },
64
+ separatorUnder: {
65
+ borderBottomWidth: 1,
66
+ borderBottomColor: PlatformColor("card-shade-color"),
67
+ },
68
+ firstRow: { borderTopLeftRadius: RADIUS, borderTopRightRadius: RADIUS },
69
+ lastRow: {
70
+ borderBottomLeftRadius: RADIUS,
71
+ borderBottomRightRadius: RADIUS,
72
+ },
73
+ // `row > box.header > box.title { margin: 6px 0; border-spacing: 3px }`
74
+ titleBox: { flex: 1, marginVertical: 6, gap: 3 },
75
+ // The theme font is `Adwaita Sans 11`, i.e. 11pt = 14.67px, and Adwaita sets
76
+ // the subtitle to `font-size: smaller` — Pango's one-step-down, 1/1.2. RN's
77
+ // fontSize is numeric only (there is no `smaller`, no em, no inherited
78
+ // percentage), so the computed value is what an app can write. Documented
79
+ // in docs/api.md rather than hidden here.
80
+ title: { fontSize: 14.7 },
81
+ // `row label.subtitle { opacity: var(--dim-opacity) }`, 55% in the light
82
+ // Adwaita palette.
83
+ subtitle: { fontSize: 12.2, opacity: 0.55 },
84
+ separator: {
85
+ height: 1,
86
+ backgroundColor: PlatformColor("card-shade-color"),
87
+ },
88
+ });
89
+ // Adwaita tints the hover and press states with a fraction of the FOREGROUND
90
+ // colour (`color-mix(in srgb, currentColor 4%, transparent)`), so one literal
91
+ // cannot serve both themes and CSS colour functions are not part of RN's
92
+ // colour contract. Two literals plus the scheme is what an RN app writes on
93
+ // every platform, and it is what this does.
94
+ const TINTS = {
95
+ light: { hover: "rgba(0, 0, 0, 0.04)", press: "rgba(0, 0, 0, 0.08)" },
96
+ dark: {
97
+ hover: "rgba(255, 255, 255, 0.04)",
98
+ press: "rgba(255, 255, 255, 0.08)",
99
+ },
100
+ };
101
+ /**
102
+ * The `.boxed-list` frame: a rounded, shadowed card. Put `ListRow`s in it
103
+ * directly, or a `FlatList` whose `renderItem` returns them.
104
+ *
105
+ * ```tsx
106
+ * <List>
107
+ * {tasks.map((task, index) => (
108
+ * <ListRow
109
+ * key={task.id}
110
+ * title={task.title}
111
+ * position={rowPosition(index, tasks.length)}
112
+ * onPress={() => open(task)}
113
+ * />
114
+ * ))}
115
+ * </List>
116
+ * ```
117
+ */
118
+ export const List = ({ children, style, testID }) => (_jsx(View, { testID: testID, style: [styles.list, style], children: children }));
119
+ /**
120
+ * One row of a {@link List} — `AdwActionRow`'s layout and states, built from
121
+ * `Pressable`, `View` and `Text`.
122
+ *
123
+ * Hover and press come from `Pressable`'s state callback, so they cost what
124
+ * they cost anywhere else in this platform: the hover path swaps a CSS class
125
+ * on the widget without a React render (see components/pressable.tsx).
126
+ *
127
+ * **Not yet:** keyboard navigation between rows and a focus ring.
128
+ * `GtkListBox` implements those as widget behaviour and RN has no focus model
129
+ * for `View` to hang them on — `Pressable`'s state is `{pressed, hovered}`
130
+ * with no `focused`. The ring itself is now drawable (`outlineWidth` and
131
+ * friends), so what is missing is the state, not the paint.
132
+ */
133
+ export const ListRow = ({ title, subtitle, prefix, suffix, onPress, position = "middle", separator, style, testID, }) => {
134
+ const scheme = useColorScheme() === "dark" ? "dark" : "light";
135
+ const tints = TINTS[scheme];
136
+ const isFirst = position === "first" || position === "only";
137
+ const isLast = position === "last" || position === "only";
138
+ const drawSeparator = separator ?? !isLast;
139
+ const body = (_jsxs(_Fragment, { children: [prefix, _jsxs(View, { style: styles.titleBox, children: [typeof title === "string" ? (_jsx(Text, { style: styles.title, children: title })) : (title), typeof subtitle === "string" ? (_jsx(Text, { style: styles.subtitle, children: subtitle })) : (subtitle)] }), suffix] }));
140
+ const base = [
141
+ styles.row,
142
+ isFirst && styles.firstRow,
143
+ isLast && styles.lastRow,
144
+ drawSeparator && styles.separatorUnder,
145
+ style,
146
+ ];
147
+ if (!onPress) {
148
+ return (_jsx(View, { testID: testID, style: base, children: body }));
149
+ }
150
+ return (_jsx(Pressable, { testID: testID, onPress: onPress,
151
+ // The tint goes on the ROW, which is why the corner radii above have to
152
+ // be on the row too: a hovered first row must round its own top corners
153
+ // or the highlight paints square over the card's rounded ones.
154
+ style: ({ hovered, pressed }) => [
155
+ ...base,
156
+ hovered && { backgroundColor: tints.hover },
157
+ pressed && { backgroundColor: tints.press },
158
+ ], children: body }));
159
+ };
160
+ /**
161
+ * The hairline between two rows, for lists that draw their own separators —
162
+ * a `FlatList`'s `ItemSeparatorComponent` is exactly this, and using it means
163
+ * the rows themselves stay position-agnostic apart from their corners.
164
+ */
165
+ export const ListSeparator = () => _jsx(View, { style: styles.separator });
166
+ //# sourceMappingURL=list.js.map