panelui-native 0.71.0 → 0.75.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.
Files changed (306) hide show
  1. package/README.md +5 -2
  2. package/lib/module/components/accordion/index.js +10 -4
  3. package/lib/module/components/accordion/index.js.map +1 -1
  4. package/lib/module/components/area-chart/index.js +1 -0
  5. package/lib/module/components/area-chart/index.js.map +1 -1
  6. package/lib/module/components/avatar/avatar-group.js +64 -0
  7. package/lib/module/components/avatar/avatar-group.js.map +1 -0
  8. package/lib/module/components/avatar/index.js +84 -2
  9. package/lib/module/components/avatar/index.js.map +1 -1
  10. package/lib/module/components/breadcrumb/index.js +2 -1
  11. package/lib/module/components/breadcrumb/index.js.map +1 -1
  12. package/lib/module/components/button/index.js +7 -5
  13. package/lib/module/components/button/index.js.map +1 -1
  14. package/lib/module/components/carousel/index.js +1 -1
  15. package/lib/module/components/carousel/index.js.map +1 -1
  16. package/lib/module/components/chip/index.js +2 -2
  17. package/lib/module/components/chip/index.js.map +1 -1
  18. package/lib/module/components/code-block/index.js.map +1 -1
  19. package/lib/module/components/collapsible/index.js +5 -1
  20. package/lib/module/components/collapsible/index.js.map +1 -1
  21. package/lib/module/components/color-picker/color-picker-accessibility.js +12 -0
  22. package/lib/module/components/color-picker/color-picker-accessibility.js.map +1 -0
  23. package/lib/module/components/color-picker/index.js +9 -5
  24. package/lib/module/components/color-picker/index.js.map +1 -1
  25. package/lib/module/components/date-time-picker/index.js +11 -3
  26. package/lib/module/components/date-time-picker/index.js.map +1 -1
  27. package/lib/module/components/drawer/index.js +58 -13
  28. package/lib/module/components/drawer/index.js.map +1 -1
  29. package/lib/module/components/fab/index.js +7 -6
  30. package/lib/module/components/fab/index.js.map +1 -1
  31. package/lib/module/components/flow/index.js +1 -1
  32. package/lib/module/components/flow/index.js.map +1 -1
  33. package/lib/module/components/frame/index.js +2 -2
  34. package/lib/module/components/frame/index.js.map +1 -1
  35. package/lib/module/components/grid-item/index.js +2 -2
  36. package/lib/module/components/grid-item/index.js.map +1 -1
  37. package/lib/module/components/heatmap-chart/index.js +1 -0
  38. package/lib/module/components/heatmap-chart/index.js.map +1 -1
  39. package/lib/module/components/hex-chart/index.js +1 -0
  40. package/lib/module/components/hex-chart/index.js.map +1 -1
  41. package/lib/module/components/input/index.js +7 -4
  42. package/lib/module/components/input/index.js.map +1 -1
  43. package/lib/module/components/input/input-content-padding.js +6 -0
  44. package/lib/module/components/input/input-content-padding.js.map +1 -0
  45. package/lib/module/components/input-group/index.js +21 -11
  46. package/lib/module/components/input-group/index.js.map +1 -1
  47. package/lib/module/components/input-group/input-group-measurements.js +60 -0
  48. package/lib/module/components/input-group/input-group-measurements.js.map +1 -0
  49. package/lib/module/components/item/index.js +2 -2
  50. package/lib/module/components/item/index.js.map +1 -1
  51. package/lib/module/components/line-chart/index.js +1 -0
  52. package/lib/module/components/line-chart/index.js.map +1 -1
  53. package/lib/module/components/marker/index.js +2 -2
  54. package/lib/module/components/marker/index.js.map +1 -1
  55. package/lib/module/components/marquee/index.js +9 -12
  56. package/lib/module/components/marquee/index.js.map +1 -1
  57. package/lib/module/components/marquee/marquee-math.js +39 -0
  58. package/lib/module/components/marquee/marquee-math.js.map +1 -0
  59. package/lib/module/components/menu/index.js +11 -3
  60. package/lib/module/components/menu/index.js.map +1 -1
  61. package/lib/module/components/otp-input/index.js +3 -1
  62. package/lib/module/components/otp-input/index.js.map +1 -1
  63. package/lib/module/components/otp-input/otp-input-state.js +7 -0
  64. package/lib/module/components/otp-input/otp-input-state.js.map +1 -0
  65. package/lib/module/components/pagination/index.js +27 -11
  66. package/lib/module/components/pagination/index.js.map +1 -1
  67. package/lib/module/components/panelside/index.js +7 -2
  68. package/lib/module/components/panelside/index.js.map +1 -1
  69. package/lib/module/components/planner/index.js +46 -11
  70. package/lib/module/components/planner/index.js.map +1 -1
  71. package/lib/module/components/planner/planner-today.js +8 -0
  72. package/lib/module/components/planner/planner-today.js.map +1 -0
  73. package/lib/module/components/plot/index.js +113 -53
  74. package/lib/module/components/plot/index.js.map +1 -1
  75. package/lib/module/components/plot/plot-series-registry.js +32 -0
  76. package/lib/module/components/plot/plot-series-registry.js.map +1 -0
  77. package/lib/module/components/post/index.js +4 -4
  78. package/lib/module/components/post/index.js.map +1 -1
  79. package/lib/module/components/radio-group/index.js +2 -1
  80. package/lib/module/components/radio-group/index.js.map +1 -1
  81. package/lib/module/components/radio-group/radio-group-value.js +8 -0
  82. package/lib/module/components/radio-group/radio-group-value.js.map +1 -0
  83. package/lib/module/components/rating/index.js +7 -4
  84. package/lib/module/components/rating/index.js.map +1 -1
  85. package/lib/module/components/rating/rating-inputs.js +15 -0
  86. package/lib/module/components/rating/rating-inputs.js.map +1 -0
  87. package/lib/module/components/search-bar/index.js +331 -0
  88. package/lib/module/components/search-bar/index.js.map +1 -0
  89. package/lib/module/components/search-bar/search-bar-debounce.js +23 -0
  90. package/lib/module/components/search-bar/search-bar-debounce.js.map +1 -0
  91. package/lib/module/components/select/index.js +9 -1
  92. package/lib/module/components/select/index.js.map +1 -1
  93. package/lib/module/components/select/native-select-contract.js +11 -0
  94. package/lib/module/components/select/native-select-contract.js.map +1 -0
  95. package/lib/module/components/split-view/index.js +439 -0
  96. package/lib/module/components/split-view/index.js.map +1 -0
  97. package/lib/module/components/split-view/split-view-math.js +132 -0
  98. package/lib/module/components/split-view/split-view-math.js.map +1 -0
  99. package/lib/module/components/splitter/index.js +433 -0
  100. package/lib/module/components/splitter/index.js.map +1 -0
  101. package/lib/module/components/splitter/splitter-math.js +206 -0
  102. package/lib/module/components/splitter/splitter-math.js.map +1 -0
  103. package/lib/module/components/steps/index.js +16 -5
  104. package/lib/module/components/steps/index.js.map +1 -1
  105. package/lib/module/components/steps/steps-trigger.js +6 -0
  106. package/lib/module/components/steps/steps-trigger.js.map +1 -0
  107. package/lib/module/components/table/index.js +3 -4
  108. package/lib/module/components/table/index.js.map +1 -1
  109. package/lib/module/components/tag-input/index.js +15 -10
  110. package/lib/module/components/tag-input/index.js.map +1 -1
  111. package/lib/module/components/tag-input/tag-input-state.js +14 -0
  112. package/lib/module/components/tag-input/tag-input-state.js.map +1 -0
  113. package/lib/module/components/textarea/index.js +9 -4
  114. package/lib/module/components/textarea/index.js.map +1 -1
  115. package/lib/module/components/textarea/textarea-disabled.js +6 -0
  116. package/lib/module/components/textarea/textarea-disabled.js.map +1 -0
  117. package/lib/module/components/timeline/index.js +352 -47
  118. package/lib/module/components/timeline/index.js.map +1 -1
  119. package/lib/module/components/timeline/timeline-geometry.js +11 -0
  120. package/lib/module/components/timeline/timeline-geometry.js.map +1 -0
  121. package/lib/module/components/toast/index.js +18 -1
  122. package/lib/module/components/toast/index.js.map +1 -1
  123. package/lib/module/components/toast/toast-store.js +36 -4
  124. package/lib/module/components/toast/toast-store.js.map +1 -1
  125. package/lib/module/components/toggle-button/index.js +1 -1
  126. package/lib/module/components/toggle-button/index.js.map +1 -1
  127. package/lib/module/components/tour/index.js +4 -2
  128. package/lib/module/components/tour/index.js.map +1 -1
  129. package/lib/module/components/tour/tour-card-measurement.js +24 -0
  130. package/lib/module/components/tour/tour-card-measurement.js.map +1 -0
  131. package/lib/module/components/tree/index.js +13 -8
  132. package/lib/module/components/tree/index.js.map +1 -1
  133. package/lib/module/hooks/use-keyboard-avoidance.js.map +1 -1
  134. package/lib/module/index.js +3 -0
  135. package/lib/module/index.js.map +1 -1
  136. package/lib/module/utils/chart.js +50 -7
  137. package/lib/module/utils/chart.js.map +1 -1
  138. package/lib/typescript/src/components/accordion/index.d.ts +2 -2
  139. package/lib/typescript/src/components/accordion/index.d.ts.map +1 -1
  140. package/lib/typescript/src/components/area-chart/index.d.ts.map +1 -1
  141. package/lib/typescript/src/components/avatar/avatar-group.d.ts +46 -0
  142. package/lib/typescript/src/components/avatar/avatar-group.d.ts.map +1 -0
  143. package/lib/typescript/src/components/avatar/index.d.ts +23 -1
  144. package/lib/typescript/src/components/avatar/index.d.ts.map +1 -1
  145. package/lib/typescript/src/components/breadcrumb/index.d.ts.map +1 -1
  146. package/lib/typescript/src/components/button/index.d.ts.map +1 -1
  147. package/lib/typescript/src/components/code-block/index.d.ts +3 -3
  148. package/lib/typescript/src/components/code-block/index.d.ts.map +1 -1
  149. package/lib/typescript/src/components/collapsible/index.d.ts +2 -2
  150. package/lib/typescript/src/components/collapsible/index.d.ts.map +1 -1
  151. package/lib/typescript/src/components/color-picker/color-picker-accessibility.d.ts +8 -0
  152. package/lib/typescript/src/components/color-picker/color-picker-accessibility.d.ts.map +1 -0
  153. package/lib/typescript/src/components/color-picker/index.d.ts.map +1 -1
  154. package/lib/typescript/src/components/date-time-picker/index.d.ts.map +1 -1
  155. package/lib/typescript/src/components/drawer/index.d.ts.map +1 -1
  156. package/lib/typescript/src/components/fab/index.d.ts +4 -2
  157. package/lib/typescript/src/components/fab/index.d.ts.map +1 -1
  158. package/lib/typescript/src/components/heatmap-chart/index.d.ts.map +1 -1
  159. package/lib/typescript/src/components/hex-chart/index.d.ts.map +1 -1
  160. package/lib/typescript/src/components/input/index.d.ts.map +1 -1
  161. package/lib/typescript/src/components/input/input-content-padding.d.ts +2 -0
  162. package/lib/typescript/src/components/input/input-content-padding.d.ts.map +1 -0
  163. package/lib/typescript/src/components/input-group/index.d.ts.map +1 -1
  164. package/lib/typescript/src/components/input-group/input-group-measurements.d.ts +16 -0
  165. package/lib/typescript/src/components/input-group/input-group-measurements.d.ts.map +1 -0
  166. package/lib/typescript/src/components/line-chart/index.d.ts.map +1 -1
  167. package/lib/typescript/src/components/marquee/index.d.ts +1 -1
  168. package/lib/typescript/src/components/marquee/index.d.ts.map +1 -1
  169. package/lib/typescript/src/components/marquee/marquee-math.d.ts +21 -0
  170. package/lib/typescript/src/components/marquee/marquee-math.d.ts.map +1 -0
  171. package/lib/typescript/src/components/menu/index.d.ts +1 -1
  172. package/lib/typescript/src/components/menu/index.d.ts.map +1 -1
  173. package/lib/typescript/src/components/otp-input/index.d.ts.map +1 -1
  174. package/lib/typescript/src/components/otp-input/otp-input-state.d.ts +3 -0
  175. package/lib/typescript/src/components/otp-input/otp-input-state.d.ts.map +1 -0
  176. package/lib/typescript/src/components/pagination/index.d.ts.map +1 -1
  177. package/lib/typescript/src/components/panelside/index.d.ts +1 -1
  178. package/lib/typescript/src/components/panelside/index.d.ts.map +1 -1
  179. package/lib/typescript/src/components/plan/index.d.ts +2 -2
  180. package/lib/typescript/src/components/planner/index.d.ts.map +1 -1
  181. package/lib/typescript/src/components/planner/planner-today.d.ts +2 -0
  182. package/lib/typescript/src/components/planner/planner-today.d.ts.map +1 -0
  183. package/lib/typescript/src/components/plot/index.d.ts +60 -6
  184. package/lib/typescript/src/components/plot/index.d.ts.map +1 -1
  185. package/lib/typescript/src/components/plot/plot-series-registry.d.ts +8 -0
  186. package/lib/typescript/src/components/plot/plot-series-registry.d.ts.map +1 -0
  187. package/lib/typescript/src/components/radio-group/index.d.ts.map +1 -1
  188. package/lib/typescript/src/components/radio-group/radio-group-value.d.ts +2 -0
  189. package/lib/typescript/src/components/radio-group/radio-group-value.d.ts.map +1 -0
  190. package/lib/typescript/src/components/rating/index.d.ts.map +1 -1
  191. package/lib/typescript/src/components/rating/rating-inputs.d.ts +4 -0
  192. package/lib/typescript/src/components/rating/rating-inputs.d.ts.map +1 -0
  193. package/lib/typescript/src/components/search-bar/index.d.ts +216 -0
  194. package/lib/typescript/src/components/search-bar/index.d.ts.map +1 -0
  195. package/lib/typescript/src/components/search-bar/search-bar-debounce.d.ts +7 -0
  196. package/lib/typescript/src/components/search-bar/search-bar-debounce.d.ts.map +1 -0
  197. package/lib/typescript/src/components/select/index.d.ts.map +1 -1
  198. package/lib/typescript/src/components/select/native-select-contract.d.ts +11 -0
  199. package/lib/typescript/src/components/select/native-select-contract.d.ts.map +1 -0
  200. package/lib/typescript/src/components/split-view/index.d.ts +159 -0
  201. package/lib/typescript/src/components/split-view/index.d.ts.map +1 -0
  202. package/lib/typescript/src/components/split-view/split-view-math.d.ts +54 -0
  203. package/lib/typescript/src/components/split-view/split-view-math.d.ts.map +1 -0
  204. package/lib/typescript/src/components/splitter/index.d.ts +78 -0
  205. package/lib/typescript/src/components/splitter/index.d.ts.map +1 -0
  206. package/lib/typescript/src/components/splitter/splitter-math.d.ts +67 -0
  207. package/lib/typescript/src/components/splitter/splitter-math.d.ts.map +1 -0
  208. package/lib/typescript/src/components/steps/index.d.ts +2 -2
  209. package/lib/typescript/src/components/steps/index.d.ts.map +1 -1
  210. package/lib/typescript/src/components/steps/steps-trigger.d.ts +2 -0
  211. package/lib/typescript/src/components/steps/steps-trigger.d.ts.map +1 -0
  212. package/lib/typescript/src/components/tag-input/index.d.ts.map +1 -1
  213. package/lib/typescript/src/components/tag-input/tag-input-state.d.ts +12 -0
  214. package/lib/typescript/src/components/tag-input/tag-input-state.d.ts.map +1 -0
  215. package/lib/typescript/src/components/textarea/index.d.ts.map +1 -1
  216. package/lib/typescript/src/components/textarea/textarea-disabled.d.ts +2 -0
  217. package/lib/typescript/src/components/textarea/textarea-disabled.d.ts.map +1 -0
  218. package/lib/typescript/src/components/timeline/index.d.ts +36 -2
  219. package/lib/typescript/src/components/timeline/index.d.ts.map +1 -1
  220. package/lib/typescript/src/components/timeline/timeline-geometry.d.ts +4 -0
  221. package/lib/typescript/src/components/timeline/timeline-geometry.d.ts.map +1 -0
  222. package/lib/typescript/src/components/toast/index.d.ts.map +1 -1
  223. package/lib/typescript/src/components/toast/toast-store.d.ts +7 -2
  224. package/lib/typescript/src/components/toast/toast-store.d.ts.map +1 -1
  225. package/lib/typescript/src/components/tour/index.d.ts.map +1 -1
  226. package/lib/typescript/src/components/tour/tour-card-measurement.d.ts +14 -0
  227. package/lib/typescript/src/components/tour/tour-card-measurement.d.ts.map +1 -0
  228. package/lib/typescript/src/components/tree/index.d.ts +3 -4
  229. package/lib/typescript/src/components/tree/index.d.ts.map +1 -1
  230. package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts +2 -2
  231. package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts.map +1 -1
  232. package/lib/typescript/src/index.d.ts +5 -2
  233. package/lib/typescript/src/index.d.ts.map +1 -1
  234. package/lib/typescript/src/utils/chart.d.ts +28 -3
  235. package/lib/typescript/src/utils/chart.d.ts.map +1 -1
  236. package/package.json +1 -1
  237. package/src/components/accordion/index.tsx +17 -7
  238. package/src/components/area-chart/index.tsx +8 -0
  239. package/src/components/avatar/avatar-group.ts +78 -0
  240. package/src/components/avatar/index.tsx +121 -1
  241. package/src/components/breadcrumb/index.tsx +2 -1
  242. package/src/components/button/index.tsx +3 -2
  243. package/src/components/carousel/index.tsx +1 -1
  244. package/src/components/chip/index.tsx +2 -2
  245. package/src/components/code-block/index.tsx +3 -3
  246. package/src/components/collapsible/index.tsx +13 -4
  247. package/src/components/color-picker/color-picker-accessibility.ts +12 -0
  248. package/src/components/color-picker/index.tsx +30 -10
  249. package/src/components/date-time-picker/index.tsx +11 -3
  250. package/src/components/drawer/index.tsx +42 -14
  251. package/src/components/fab/index.tsx +21 -11
  252. package/src/components/flow/index.tsx +1 -1
  253. package/src/components/frame/index.tsx +2 -2
  254. package/src/components/grid-item/index.tsx +2 -2
  255. package/src/components/heatmap-chart/index.tsx +7 -1
  256. package/src/components/hex-chart/index.tsx +7 -1
  257. package/src/components/input/index.tsx +6 -2
  258. package/src/components/input/input-content-padding.ts +3 -0
  259. package/src/components/input-group/index.tsx +45 -12
  260. package/src/components/input-group/input-group-measurements.ts +98 -0
  261. package/src/components/item/index.tsx +2 -2
  262. package/src/components/line-chart/index.tsx +9 -0
  263. package/src/components/marker/index.tsx +2 -2
  264. package/src/components/marquee/index.tsx +14 -12
  265. package/src/components/marquee/marquee-math.ts +37 -0
  266. package/src/components/menu/index.tsx +11 -3
  267. package/src/components/otp-input/index.tsx +3 -1
  268. package/src/components/otp-input/otp-input-state.ts +7 -0
  269. package/src/components/pagination/index.tsx +26 -13
  270. package/src/components/panelside/index.tsx +7 -2
  271. package/src/components/plan/index.tsx +2 -2
  272. package/src/components/planner/index.tsx +44 -11
  273. package/src/components/planner/planner-today.ts +5 -0
  274. package/src/components/plot/index.tsx +199 -51
  275. package/src/components/plot/plot-series-registry.ts +41 -0
  276. package/src/components/post/index.tsx +4 -4
  277. package/src/components/radio-group/index.tsx +4 -1
  278. package/src/components/radio-group/radio-group-value.ts +9 -0
  279. package/src/components/rating/index.tsx +11 -4
  280. package/src/components/rating/rating-inputs.ts +19 -0
  281. package/src/components/search-bar/index.tsx +441 -0
  282. package/src/components/search-bar/search-bar-debounce.ts +35 -0
  283. package/src/components/select/index.tsx +10 -1
  284. package/src/components/select/native-select-contract.ts +12 -0
  285. package/src/components/split-view/index.tsx +565 -0
  286. package/src/components/split-view/split-view-math.ts +146 -0
  287. package/src/components/splitter/index.tsx +589 -0
  288. package/src/components/splitter/splitter-math.ts +244 -0
  289. package/src/components/steps/index.tsx +35 -9
  290. package/src/components/steps/steps-trigger.ts +6 -0
  291. package/src/components/table/index.tsx +2 -2
  292. package/src/components/tag-input/index.tsx +13 -11
  293. package/src/components/tag-input/tag-input-state.ts +18 -0
  294. package/src/components/textarea/index.tsx +8 -4
  295. package/src/components/textarea/textarea-disabled.ts +6 -0
  296. package/src/components/timeline/index.tsx +405 -46
  297. package/src/components/timeline/timeline-geometry.ts +9 -0
  298. package/src/components/toast/index.tsx +26 -1
  299. package/src/components/toast/toast-store.ts +43 -8
  300. package/src/components/toggle-button/index.tsx +1 -1
  301. package/src/components/tour/index.tsx +11 -3
  302. package/src/components/tour/tour-card-measurement.ts +29 -0
  303. package/src/components/tree/index.tsx +17 -12
  304. package/src/hooks/use-keyboard-avoidance.ts +7 -2
  305. package/src/index.ts +19 -0
  306. package/src/utils/chart.ts +66 -7
@@ -13,8 +13,18 @@
13
13
  * attribute selectors for a stylesheet to key off. `Steps` resolves its states
14
14
  * the same way, so the two read as siblings.
15
15
  *
16
- * Vertical only — a horizontal timeline gives each item roughly a fifth of a
17
- * phone's width, which is not enough for a date and a title.
16
+ * ## Two orientations
17
+ *
18
+ * Vertical is the default and the ordinary case. Horizontal lays the items out
19
+ * as columns on a rail that runs off the side of the screen and is swiped
20
+ * through, which is the arrangement a long span of time wants: a decade of
21
+ * entries read top to bottom is a page nobody reaches the end of.
22
+ *
23
+ * The objection to a horizontal timeline is that each item gets a fifth of a
24
+ * phone's width, which will not hold a date and a title. The answer is that it
25
+ * does not have to fit — the rail is wider than the screen, and a column takes
26
+ * the width its contents need. An item with nothing on it collapses to a tick,
27
+ * so a quiet stretch compresses and a busy one keeps its room.
18
28
  *
19
29
  * ```tsx
20
30
  * <Timeline variant="icon" value={2}>
@@ -35,15 +45,53 @@
35
45
  * </Timeline>
36
46
  * ```
37
47
  */
38
- import { createContext, forwardRef, useContext, useMemo } from 'react';
39
- import { View } from 'react-native';
48
+ import { Children, createContext, forwardRef, isValidElement, useContext, useMemo } from 'react';
49
+ import { ScrollView, View } from 'react-native';
50
+ import Animated, { interpolate, useAnimatedScrollHandler, useAnimatedStyle, useReducedMotion, useSharedValue } from 'react-native-reanimated';
40
51
  import { tv } from 'tailwind-variants';
41
52
  import { useCSSVariable } from 'uniwind';
42
53
  import { IconColorProvider } from "../../icons/index.js";
43
54
  import { Text, textChildren } from "../../primitives/text.js";
55
+ import { timelineColumnWidth } from "./timeline-geometry.js";
44
56
 
45
57
  /** Semantic colour for a single event, independent of progress. */
58
+
59
+ /** Which way the sequence runs. */
46
60
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
61
+ const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);
62
+
63
+ /*
64
+ * Horizontal geometry.
65
+ *
66
+ * The rail has to land on exactly the same line in every column, and the
67
+ * simplest way to guarantee that is to make the band above it a fixed height
68
+ * rather than to position the rail against measured content. So the aside is
69
+ * `HORIZONTAL_RAIL_TOP` tall in every column, the rail is drawn once across the
70
+ * whole track at that offset, and each column's tick is pulled up by half its
71
+ * own height to sit centred on it.
72
+ */
73
+ const HORIZONTAL_RAIL_TOP = 64;
74
+ const HORIZONTAL_TICK_HEIGHT = 10;
75
+
76
+ /**
77
+ * How wide a column is: what it was given, else what its contents ask for.
78
+ *
79
+ * Read by the item to size itself and by the root to build the snap offsets, so
80
+ * it lives here rather than in either — the two disagreeing would put every
81
+ * snap point half a column out.
82
+ */
83
+ function itemWidth(props) {
84
+ let filled = false;
85
+ Children.forEach(props.children, child => {
86
+ if (filled || ! /*#__PURE__*/isValidElement(child)) return;
87
+ const displayName = child.type?.displayName;
88
+ if (displayName !== 'Timeline.Content') return;
89
+ const inner = child.props.children;
90
+ if (inner !== undefined && inner !== null && inner !== false) filled = true;
91
+ });
92
+ return timelineColumnWidth(props.width, filled);
93
+ }
94
+
47
95
  /** Variants whose node is a filled disc rather than an outlined ring. */
48
96
  const SOLID_VARIANTS = ['dot', 'card'];
49
97
  const timelineVariants = tv({
@@ -117,12 +165,30 @@ const timelineVariants = tv({
117
165
  false: {
118
166
  separator: 'bg-muted'
119
167
  }
168
+ },
169
+ /*
170
+ * Horizontal turns the item from a row into a column and the rail from a
171
+ * line down the side into a line across the top. The aside is a fixed
172
+ * height because that height *is* where the rail sits — see
173
+ * HORIZONTAL_RAIL_TOP — and it is left-aligned rather than right, since a
174
+ * column reads from its own left edge rather than towards a rail beside it.
175
+ */
176
+ orientation: {
177
+ vertical: {},
178
+ horizontal: {
179
+ item: 'w-auto shrink-0 flex-col gap-0 pr-6',
180
+ aside: 'w-auto items-start justify-end gap-1 pb-2 pt-0',
181
+ rail: 'w-full items-start',
182
+ body: 'w-auto flex-none pb-0 pt-5',
183
+ title: 'text-sm'
184
+ }
120
185
  }
121
186
  },
122
187
  defaultVariants: {
123
188
  variant: 'dot',
124
189
  tone: 'default',
125
- completed: false
190
+ completed: false,
191
+ orientation: 'vertical'
126
192
  }
127
193
  });
128
194
 
@@ -204,18 +270,62 @@ const TimelineRoot = /*#__PURE__*/forwardRef(({
204
270
  className,
205
271
  value = 0,
206
272
  variant = 'dot',
273
+ orientation = 'vertical',
274
+ snap = true,
207
275
  children,
208
276
  ...props
209
277
  }, ref) => {
278
+ const horizontal = orientation === 'horizontal';
210
279
  const {
211
280
  root
212
281
  } = timelineVariants({
213
- variant
282
+ variant,
283
+ orientation
214
284
  });
285
+ const reducedMotion = useReducedMotion();
286
+ const scrollX = useSharedValue(0);
287
+ const border = useCSSVariable('--color-border');
288
+
289
+ /*
290
+ * The columns' left edges, from the same width rule the items size
291
+ * themselves by. These are the snap points, and they are what an item reads
292
+ * to know how far it is from the reading edge.
293
+ */
294
+ const offsets = useMemo(() => {
295
+ if (!horizontal) return [];
296
+ const result = [];
297
+ let sum = 0;
298
+ Children.forEach(children, child => {
299
+ if (! /*#__PURE__*/isValidElement(child)) return;
300
+ result.push(sum);
301
+ sum += itemWidth(child.props);
302
+ });
303
+ return result;
304
+ }, [children, horizontal]);
215
305
  const context = useMemo(() => ({
216
306
  activeStep: value,
217
- variant
218
- }), [value, variant]);
307
+ variant,
308
+ orientation,
309
+ scrollX,
310
+ offsets,
311
+ animate: !reducedMotion
312
+ }), [value, variant, orientation, scrollX, offsets, reducedMotion]);
313
+ const onScroll = useAnimatedScrollHandler(event => {
314
+ scrollX.value = event.contentOffset.x;
315
+ });
316
+ if (!horizontal) {
317
+ return /*#__PURE__*/_jsx(TimelineContext.Provider, {
318
+ value: context,
319
+ children: /*#__PURE__*/_jsx(View, {
320
+ ref: ref,
321
+ className: root({
322
+ className
323
+ }),
324
+ ...props,
325
+ children: textChildren(children)
326
+ })
327
+ });
328
+ }
219
329
  return /*#__PURE__*/_jsx(TimelineContext.Provider, {
220
330
  value: context,
221
331
  children: /*#__PURE__*/_jsx(View, {
@@ -224,7 +334,34 @@ const TimelineRoot = /*#__PURE__*/forwardRef(({
224
334
  className
225
335
  }),
226
336
  ...props,
227
- children: textChildren(children)
337
+ children: /*#__PURE__*/_jsx(AnimatedScrollView, {
338
+ horizontal: true,
339
+ onScroll: onScroll,
340
+ scrollEventThrottle: 16,
341
+ showsHorizontalScrollIndicator: false,
342
+ decelerationRate: "fast",
343
+ snapToAlignment: "start",
344
+ snapToOffsets: snap ? offsets : undefined,
345
+ children: /*#__PURE__*/_jsxs(View, {
346
+ className: "relative flex-row",
347
+ children: [/*#__PURE__*/_jsx(View, {
348
+ accessibilityElementsHidden: true,
349
+ importantForAccessibility: "no-hide-descendants",
350
+ pointerEvents: "none",
351
+ style: {
352
+ position: 'absolute',
353
+ left: 0,
354
+ right: 0,
355
+ top: HORIZONTAL_RAIL_TOP,
356
+ borderTopWidth: 1,
357
+ // Dashed borders only render at a radius of zero, which this
358
+ // has, and the rule is the whole element.
359
+ borderStyle: 'dashed',
360
+ borderColor: typeof border === 'string' ? border : undefined
361
+ }
362
+ }), textChildren(children)]
363
+ })
364
+ })
228
365
  })
229
366
  });
230
367
  });
@@ -235,12 +372,18 @@ const TimelineItem = /*#__PURE__*/forwardRef(({
235
372
  completed,
236
373
  tone = 'default',
237
374
  last = false,
375
+ width,
376
+ style,
238
377
  children,
239
378
  ...props
240
379
  }, ref) => {
241
380
  const {
242
381
  activeStep,
243
- variant
382
+ variant,
383
+ orientation,
384
+ scrollX,
385
+ offsets,
386
+ animate
244
387
  } = useTimeline('Timeline.Item');
245
388
  const isCompleted = completed ?? step <= activeStep;
246
389
  const {
@@ -248,22 +391,82 @@ const TimelineItem = /*#__PURE__*/forwardRef(({
248
391
  } = timelineVariants({
249
392
  variant,
250
393
  tone,
251
- completed: isCompleted
394
+ completed: isCompleted,
395
+ orientation
252
396
  });
397
+ const horizontal = orientation === 'horizontal';
398
+ const columnWidth = horizontal ? itemWidth({
399
+ step,
400
+ width,
401
+ children
402
+ }) : undefined;
403
+ const offset = offsets[step] ?? 0;
253
404
  const context = useMemo(() => ({
254
405
  step,
255
406
  completed: isCompleted,
256
407
  tone,
257
- showSeparator: !last
258
- }), [step, isCompleted, tone, last]);
408
+ showSeparator: !last,
409
+ offset,
410
+ columnWidth: columnWidth ?? 0
411
+ }), [step, isCompleted, tone, last, offset, columnWidth]);
412
+
413
+ /*
414
+ * A column recedes as it leaves the reading edge, so the one being read is
415
+ * the one that looks read.
416
+ *
417
+ * One column's width either side, not two: a window wide enough to hold
418
+ * three columns near full strength is a row where nothing is picked out,
419
+ * and picking one out is the whole job. The neighbours stay legible at the
420
+ * far end of it — a timeline is worth reading for what came before and
421
+ * after — they simply stop competing.
422
+ *
423
+ * The scale and the drop are what turn a fade into a focus. Four points and
424
+ * four percent is under the threshold where anybody would call it movement,
425
+ * and over the one where the column at the edge stops looking flat against
426
+ * the rest.
427
+ */
428
+ const columnStyle = useAnimatedStyle(() => {
429
+ if (!horizontal || !animate) return {
430
+ opacity: 1,
431
+ transform: []
432
+ };
433
+ const distance = Math.abs(scrollX.value - offset);
434
+ const window = Math.max(columnWidth ?? timelineColumnWidth(undefined, true), 1);
435
+ const away = interpolate(distance, [0, window], [0, 1], 'clamp');
436
+ return {
437
+ opacity: 1 - away * 0.4,
438
+ transform: [{
439
+ scale: 1 - away * 0.04
440
+ }, {
441
+ translateY: away * 4
442
+ }]
443
+ };
444
+ });
445
+ if (!horizontal) {
446
+ return /*#__PURE__*/_jsx(TimelineItemContext.Provider, {
447
+ value: context,
448
+ children: /*#__PURE__*/_jsx(View, {
449
+ ref: ref,
450
+ className: item({
451
+ className
452
+ }),
453
+ style: style,
454
+ ...props,
455
+ children: textChildren(children)
456
+ })
457
+ });
458
+ }
259
459
  return /*#__PURE__*/_jsx(TimelineItemContext.Provider, {
260
460
  value: context,
261
- children: /*#__PURE__*/_jsx(View, {
461
+ children: /*#__PURE__*/_jsx(Animated.View, {
262
462
  ref: ref,
263
463
  className: item({
264
464
  className
265
465
  }),
266
466
  ...props,
467
+ style: [style, {
468
+ width: columnWidth
469
+ }, columnStyle],
267
470
  children: textChildren(children)
268
471
  })
269
472
  });
@@ -276,21 +479,33 @@ TimelineItem.displayName = 'Timeline.Item';
276
479
  */
277
480
  const TimelineAside = /*#__PURE__*/forwardRef(({
278
481
  className,
482
+ style,
279
483
  ...props
280
484
  }, ref) => {
281
485
  const {
282
- variant
486
+ variant,
487
+ orientation
283
488
  } = useTimeline('Timeline.Aside');
284
489
  const {
285
490
  aside
286
491
  } = timelineVariants({
287
- variant
492
+ variant,
493
+ orientation
288
494
  });
289
495
  return /*#__PURE__*/_jsx(View, {
290
496
  ref: ref,
291
497
  className: aside({
292
498
  className
293
- }),
499
+ })
500
+ /*
501
+ * Horizontal: this band's height is where the rail lands, so it is
502
+ * fixed rather than sized to whatever the column happens to put in it.
503
+ * A column with a longer label would otherwise push its own tick below
504
+ * everybody else's and the rail would stop being a line.
505
+ */,
506
+ style: orientation === 'horizontal' ? [{
507
+ height: HORIZONTAL_RAIL_TOP
508
+ }, style] : style,
294
509
  ...props
295
510
  });
296
511
  });
@@ -308,7 +523,8 @@ const TimelineIndicator = /*#__PURE__*/forwardRef(({
308
523
  ...props
309
524
  }, ref) => {
310
525
  const {
311
- variant
526
+ variant,
527
+ orientation
312
528
  } = useTimeline('Timeline.Indicator');
313
529
  const {
314
530
  step,
@@ -324,9 +540,36 @@ const TimelineIndicator = /*#__PURE__*/forwardRef(({
324
540
  } = timelineVariants({
325
541
  variant,
326
542
  tone,
327
- completed
543
+ completed,
544
+ orientation
328
545
  });
329
546
 
547
+ /*
548
+ * Horizontal: a tick sitting on the rail, not a node with a connector
549
+ * running out of it. The rail is already drawn across the whole track by
550
+ * the root, so what a column owes it is the mark saying where this entry
551
+ * falls — pulled up by half its height to straddle the line rather than
552
+ * hang off it.
553
+ */
554
+ if (orientation === 'horizontal') {
555
+ return /*#__PURE__*/_jsx(View, {
556
+ className: rail(),
557
+ children: /*#__PURE__*/_jsx(View, {
558
+ ref: ref,
559
+ accessibilityElementsHidden: true,
560
+ importantForAccessibility: "no-hide-descendants",
561
+ className: indicator({
562
+ className: `w-px rounded-none ${completed ? 'bg-primary' : 'bg-muted-foreground'} ${className ?? ''}`
563
+ }),
564
+ style: {
565
+ height: HORIZONTAL_TICK_HEIGHT,
566
+ marginTop: -HORIZONTAL_TICK_HEIGHT / 2
567
+ },
568
+ ...props
569
+ })
570
+ });
571
+ }
572
+
330
573
  // dot/card nodes are small discs with nothing inside, so they keep full
331
574
  // saturation — a soft tint at 16px would disappear. Nodes that hold an
332
575
  // icon or a number take the tinted fill instead.
@@ -376,14 +619,20 @@ TimelineIndicator.displayName = 'Timeline.Indicator';
376
619
  const TimelineContent = /*#__PURE__*/forwardRef(({
377
620
  className,
378
621
  children,
622
+ style,
379
623
  ...props
380
624
  }, ref) => {
381
625
  const {
382
- variant
626
+ variant,
627
+ orientation,
628
+ scrollX,
629
+ animate
383
630
  } = useTimeline('Timeline.Content');
384
631
  const {
385
632
  completed,
386
- tone
633
+ tone,
634
+ offset,
635
+ columnWidth
387
636
  } = useTimelineItem('Timeline.Content');
388
637
  const {
389
638
  body,
@@ -391,18 +640,54 @@ const TimelineContent = /*#__PURE__*/forwardRef(({
391
640
  } = timelineVariants({
392
641
  variant,
393
642
  tone,
394
- completed
643
+ completed,
644
+ orientation
395
645
  });
396
- return /*#__PURE__*/_jsx(View, {
646
+ const horizontal = orientation === 'horizontal';
647
+
648
+ /*
649
+ * Horizontal: the body recedes further than the column around it.
650
+ *
651
+ * The rail is a continuous thing and has to stay readable across the whole
652
+ * track — the years either side of the one being read are half of what a
653
+ * timeline is for. The prose under them is not: several columns of it at
654
+ * equal weight is a wall, and no amount of fading the column as a whole
655
+ * fixes that without taking the years down with it. So the body takes a
656
+ * second, steeper curve and the dates keep the first one.
657
+ */
658
+ const bodyStyle = useAnimatedStyle(() => {
659
+ if (!horizontal || !animate) return {
660
+ opacity: 1
661
+ };
662
+ const distance = Math.abs(scrollX.value - offset);
663
+ const window = Math.max(columnWidth, 1);
664
+ return {
665
+ opacity: interpolate(distance, [0, window], [1, 0.3], 'clamp')
666
+ };
667
+ });
668
+ const inner = variant === 'card' ? /*#__PURE__*/_jsx(View, {
669
+ className: panel(),
670
+ children: textChildren(children)
671
+ }) : children;
672
+ if (!horizontal) {
673
+ return /*#__PURE__*/_jsx(View, {
674
+ ref: ref,
675
+ className: body({
676
+ className
677
+ }),
678
+ style: style,
679
+ ...props,
680
+ children: inner
681
+ });
682
+ }
683
+ return /*#__PURE__*/_jsx(Animated.View, {
397
684
  ref: ref,
398
685
  className: body({
399
686
  className
400
687
  }),
401
688
  ...props,
402
- children: variant === 'card' ? /*#__PURE__*/_jsx(View, {
403
- className: panel(),
404
- children: textChildren(children)
405
- }) : children
689
+ style: [style, bodyStyle],
690
+ children: inner
406
691
  });
407
692
  });
408
693
  TimelineContent.displayName = 'Timeline.Content';
@@ -413,12 +698,14 @@ const TimelineHeader = /*#__PURE__*/forwardRef(({
413
698
  ...props
414
699
  }, ref) => {
415
700
  const {
416
- variant
701
+ variant,
702
+ orientation
417
703
  } = useTimeline('Timeline.Header');
418
704
  const {
419
705
  header
420
706
  } = timelineVariants({
421
- variant
707
+ variant,
708
+ orientation
422
709
  });
423
710
  return /*#__PURE__*/_jsx(View, {
424
711
  ref: ref,
@@ -436,12 +723,14 @@ const TimelineHeading = /*#__PURE__*/forwardRef(({
436
723
  ...props
437
724
  }, ref) => {
438
725
  const {
439
- variant
726
+ variant,
727
+ orientation
440
728
  } = useTimeline('Timeline.Heading');
441
729
  const {
442
730
  heading
443
731
  } = timelineVariants({
444
- variant
732
+ variant,
733
+ orientation
445
734
  });
446
735
  return /*#__PURE__*/_jsx(View, {
447
736
  ref: ref,
@@ -457,12 +746,14 @@ const TimelineDate = /*#__PURE__*/forwardRef(({
457
746
  ...props
458
747
  }, ref) => {
459
748
  const {
460
- variant
749
+ variant,
750
+ orientation
461
751
  } = useTimeline('Timeline.Date');
462
752
  const {
463
753
  date
464
754
  } = timelineVariants({
465
- variant
755
+ variant,
756
+ orientation
466
757
  });
467
758
  return /*#__PURE__*/_jsx(Text, {
468
759
  ref: ref,
@@ -480,7 +771,8 @@ const TimelineLabel = /*#__PURE__*/forwardRef(({
480
771
  ...props
481
772
  }, ref) => {
482
773
  const {
483
- variant
774
+ variant,
775
+ orientation
484
776
  } = useTimeline('Timeline.Label');
485
777
  const {
486
778
  tone
@@ -489,7 +781,8 @@ const TimelineLabel = /*#__PURE__*/forwardRef(({
489
781
  label
490
782
  } = timelineVariants({
491
783
  variant,
492
- tone
784
+ tone,
785
+ orientation
493
786
  });
494
787
  return /*#__PURE__*/_jsx(Text, {
495
788
  ref: ref,
@@ -507,12 +800,14 @@ const TimelineMeta = /*#__PURE__*/forwardRef(({
507
800
  ...props
508
801
  }, ref) => {
509
802
  const {
510
- variant
803
+ variant,
804
+ orientation
511
805
  } = useTimeline('Timeline.Meta');
512
806
  const {
513
807
  meta
514
808
  } = timelineVariants({
515
- variant
809
+ variant,
810
+ orientation
516
811
  });
517
812
  return /*#__PURE__*/_jsx(Text, {
518
813
  ref: ref,
@@ -528,12 +823,14 @@ const TimelineTitle = /*#__PURE__*/forwardRef(({
528
823
  ...props
529
824
  }, ref) => {
530
825
  const {
531
- variant
826
+ variant,
827
+ orientation
532
828
  } = useTimeline('Timeline.Title');
533
829
  const {
534
830
  title
535
831
  } = timelineVariants({
536
- variant
832
+ variant,
833
+ orientation
537
834
  });
538
835
  return /*#__PURE__*/_jsx(Text, {
539
836
  ref: ref,
@@ -551,12 +848,14 @@ const TimelineTrailing = /*#__PURE__*/forwardRef(({
551
848
  ...props
552
849
  }, ref) => {
553
850
  const {
554
- variant
851
+ variant,
852
+ orientation
555
853
  } = useTimeline('Timeline.Trailing');
556
854
  const {
557
855
  trailing
558
856
  } = timelineVariants({
559
- variant
857
+ variant,
858
+ orientation
560
859
  });
561
860
  return /*#__PURE__*/_jsx(Text, {
562
861
  ref: ref,
@@ -572,12 +871,14 @@ const TimelineDescription = /*#__PURE__*/forwardRef(({
572
871
  ...props
573
872
  }, ref) => {
574
873
  const {
575
- variant
874
+ variant,
875
+ orientation
576
876
  } = useTimeline('Timeline.Description');
577
877
  const {
578
878
  content
579
879
  } = timelineVariants({
580
- variant
880
+ variant,
881
+ orientation
581
882
  });
582
883
  return /*#__PURE__*/_jsx(Text, {
583
884
  ref: ref,
@@ -595,12 +896,14 @@ const TimelineStats = /*#__PURE__*/forwardRef(({
595
896
  ...props
596
897
  }, ref) => {
597
898
  const {
598
- variant
899
+ variant,
900
+ orientation
599
901
  } = useTimeline('Timeline.Stats');
600
902
  const {
601
903
  stats
602
904
  } = timelineVariants({
603
- variant
905
+ variant,
906
+ orientation
604
907
  });
605
908
  return /*#__PURE__*/_jsx(View, {
606
909
  ref: ref,
@@ -618,13 +921,15 @@ const TimelineStat = /*#__PURE__*/forwardRef(({
618
921
  ...props
619
922
  }, ref) => {
620
923
  const {
621
- variant
924
+ variant,
925
+ orientation
622
926
  } = useTimeline('Timeline.Stat');
623
927
  const {
624
928
  statLabel,
625
929
  statValue
626
930
  } = timelineVariants({
627
- variant
931
+ variant,
932
+ orientation
628
933
  });
629
934
  return /*#__PURE__*/_jsxs(View, {
630
935
  ref: ref,