react-native-agenda-kit 0.1.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 (403) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +364 -0
  3. package/lib/commonjs/agenda/AgendaBackdrop.js +68 -0
  4. package/lib/commonjs/agenda/AgendaBackdrop.js.map +1 -0
  5. package/lib/commonjs/agenda/AgendaList.js +354 -0
  6. package/lib/commonjs/agenda/AgendaList.js.map +1 -0
  7. package/lib/commonjs/agenda/AgendaSlot.js +88 -0
  8. package/lib/commonjs/agenda/AgendaSlot.js.map +1 -0
  9. package/lib/commonjs/agenda/AgendaWindow.js +171 -0
  10. package/lib/commonjs/agenda/AgendaWindow.js.map +1 -0
  11. package/lib/commonjs/agenda/StickyHeaderOverlay.js +125 -0
  12. package/lib/commonjs/agenda/StickyHeaderOverlay.js.map +1 -0
  13. package/lib/commonjs/agenda/buildAgendaLayout.js +100 -0
  14. package/lib/commonjs/agenda/buildAgendaLayout.js.map +1 -0
  15. package/lib/commonjs/agenda/constants.js +29 -0
  16. package/lib/commonjs/agenda/constants.js.map +1 -0
  17. package/lib/commonjs/agenda/heights.js +49 -0
  18. package/lib/commonjs/agenda/heights.js.map +1 -0
  19. package/lib/commonjs/agenda/useAgendaScrollSync.js +204 -0
  20. package/lib/commonjs/agenda/useAgendaScrollSync.js.map +1 -0
  21. package/lib/commonjs/core/ArrowGlyph.js +65 -0
  22. package/lib/commonjs/core/ArrowGlyph.js.map +1 -0
  23. package/lib/commonjs/core/CalendarContext.js +32 -0
  24. package/lib/commonjs/core/CalendarContext.js.map +1 -0
  25. package/lib/commonjs/core/CalendarProvider.js +141 -0
  26. package/lib/commonjs/core/CalendarProvider.js.map +1 -0
  27. package/lib/commonjs/core/CalendarStore.js +70 -0
  28. package/lib/commonjs/core/CalendarStore.js.map +1 -0
  29. package/lib/commonjs/core/KitText.js +23 -0
  30. package/lib/commonjs/core/KitText.js.map +1 -0
  31. package/lib/commonjs/core/TodayButton.js +136 -0
  32. package/lib/commonjs/core/TodayButton.js.map +1 -0
  33. package/lib/commonjs/core/civil.js +101 -0
  34. package/lib/commonjs/core/civil.js.map +1 -0
  35. package/lib/commonjs/core/dateKey.js +56 -0
  36. package/lib/commonjs/core/dateKey.js.map +1 -0
  37. package/lib/commonjs/core/motion.js +56 -0
  38. package/lib/commonjs/core/motion.js.map +1 -0
  39. package/lib/commonjs/core/worklets.js +44 -0
  40. package/lib/commonjs/core/worklets.js.map +1 -0
  41. package/lib/commonjs/expandable/DayCell.js +120 -0
  42. package/lib/commonjs/expandable/DayCell.js.map +1 -0
  43. package/lib/commonjs/expandable/ExpandableCalendar.js +280 -0
  44. package/lib/commonjs/expandable/ExpandableCalendar.js.map +1 -0
  45. package/lib/commonjs/expandable/Knob.js +72 -0
  46. package/lib/commonjs/expandable/Knob.js.map +1 -0
  47. package/lib/commonjs/expandable/MonthPager.js +180 -0
  48. package/lib/commonjs/expandable/MonthPager.js.map +1 -0
  49. package/lib/commonjs/expandable/WeekStrip.js +451 -0
  50. package/lib/commonjs/expandable/WeekStrip.js.map +1 -0
  51. package/lib/commonjs/expandable/calendarCells.js +152 -0
  52. package/lib/commonjs/expandable/calendarCells.js.map +1 -0
  53. package/lib/commonjs/expandable/geometry.js +62 -0
  54. package/lib/commonjs/expandable/geometry.js.map +1 -0
  55. package/lib/commonjs/expandable/useExpandGesture.js +124 -0
  56. package/lib/commonjs/expandable/useExpandGesture.js.map +1 -0
  57. package/lib/commonjs/expandable/useHorizontalPager.js +97 -0
  58. package/lib/commonjs/expandable/useHorizontalPager.js.map +1 -0
  59. package/lib/commonjs/index.js +167 -0
  60. package/lib/commonjs/index.js.map +1 -0
  61. package/lib/commonjs/package.json +1 -0
  62. package/lib/commonjs/theme/ThemeProvider.js +73 -0
  63. package/lib/commonjs/theme/ThemeProvider.js.map +1 -0
  64. package/lib/commonjs/theme/index.js +75 -0
  65. package/lib/commonjs/theme/index.js.map +1 -0
  66. package/lib/commonjs/theme/theme.js +79 -0
  67. package/lib/commonjs/theme/theme.js.map +1 -0
  68. package/lib/commonjs/theme/tokens.js +54 -0
  69. package/lib/commonjs/theme/tokens.js.map +1 -0
  70. package/lib/commonjs/timeline/DayColumn.js +95 -0
  71. package/lib/commonjs/timeline/DayColumn.js.map +1 -0
  72. package/lib/commonjs/timeline/DayPager.js +250 -0
  73. package/lib/commonjs/timeline/DayPager.js.map +1 -0
  74. package/lib/commonjs/timeline/EventBlock.js +91 -0
  75. package/lib/commonjs/timeline/EventBlock.js.map +1 -0
  76. package/lib/commonjs/timeline/GridLines.js +47 -0
  77. package/lib/commonjs/timeline/GridLines.js.map +1 -0
  78. package/lib/commonjs/timeline/HourGrid.js +96 -0
  79. package/lib/commonjs/timeline/HourGrid.js.map +1 -0
  80. package/lib/commonjs/timeline/NowIndicator.js +132 -0
  81. package/lib/commonjs/timeline/NowIndicator.js.map +1 -0
  82. package/lib/commonjs/timeline/TimelineDay.js +126 -0
  83. package/lib/commonjs/timeline/TimelineDay.js.map +1 -0
  84. package/lib/commonjs/timeline/packEvents.js +102 -0
  85. package/lib/commonjs/timeline/packEvents.js.map +1 -0
  86. package/lib/commonjs/timeline/timelineGeometry.js +27 -0
  87. package/lib/commonjs/timeline/timelineGeometry.js.map +1 -0
  88. package/lib/commonjs/timeline/timelineMath.js +82 -0
  89. package/lib/commonjs/timeline/timelineMath.js.map +1 -0
  90. package/lib/commonjs/types.js +71 -0
  91. package/lib/commonjs/types.js.map +1 -0
  92. package/lib/module/agenda/AgendaBackdrop.js +63 -0
  93. package/lib/module/agenda/AgendaBackdrop.js.map +1 -0
  94. package/lib/module/agenda/AgendaList.js +349 -0
  95. package/lib/module/agenda/AgendaList.js.map +1 -0
  96. package/lib/module/agenda/AgendaSlot.js +84 -0
  97. package/lib/module/agenda/AgendaSlot.js.map +1 -0
  98. package/lib/module/agenda/AgendaWindow.js +167 -0
  99. package/lib/module/agenda/AgendaWindow.js.map +1 -0
  100. package/lib/module/agenda/StickyHeaderOverlay.js +120 -0
  101. package/lib/module/agenda/StickyHeaderOverlay.js.map +1 -0
  102. package/lib/module/agenda/buildAgendaLayout.js +95 -0
  103. package/lib/module/agenda/buildAgendaLayout.js.map +1 -0
  104. package/lib/module/agenda/constants.js +25 -0
  105. package/lib/module/agenda/constants.js.map +1 -0
  106. package/lib/module/agenda/heights.js +42 -0
  107. package/lib/module/agenda/heights.js.map +1 -0
  108. package/lib/module/agenda/useAgendaScrollSync.js +200 -0
  109. package/lib/module/agenda/useAgendaScrollSync.js.map +1 -0
  110. package/lib/module/core/ArrowGlyph.js +60 -0
  111. package/lib/module/core/ArrowGlyph.js.map +1 -0
  112. package/lib/module/core/CalendarContext.js +26 -0
  113. package/lib/module/core/CalendarContext.js.map +1 -0
  114. package/lib/module/core/CalendarProvider.js +136 -0
  115. package/lib/module/core/CalendarProvider.js.map +1 -0
  116. package/lib/module/core/CalendarStore.js +66 -0
  117. package/lib/module/core/CalendarStore.js.map +1 -0
  118. package/lib/module/core/KitText.js +19 -0
  119. package/lib/module/core/KitText.js.map +1 -0
  120. package/lib/module/core/TodayButton.js +133 -0
  121. package/lib/module/core/TodayButton.js.map +1 -0
  122. package/lib/module/core/civil.js +88 -0
  123. package/lib/module/core/civil.js.map +1 -0
  124. package/lib/module/core/dateKey.js +47 -0
  125. package/lib/module/core/dateKey.js.map +1 -0
  126. package/lib/module/core/motion.js +49 -0
  127. package/lib/module/core/motion.js.map +1 -0
  128. package/lib/module/core/worklets.js +38 -0
  129. package/lib/module/core/worklets.js.map +1 -0
  130. package/lib/module/expandable/DayCell.js +116 -0
  131. package/lib/module/expandable/DayCell.js.map +1 -0
  132. package/lib/module/expandable/ExpandableCalendar.js +275 -0
  133. package/lib/module/expandable/ExpandableCalendar.js.map +1 -0
  134. package/lib/module/expandable/Knob.js +67 -0
  135. package/lib/module/expandable/Knob.js.map +1 -0
  136. package/lib/module/expandable/MonthPager.js +175 -0
  137. package/lib/module/expandable/MonthPager.js.map +1 -0
  138. package/lib/module/expandable/WeekStrip.js +446 -0
  139. package/lib/module/expandable/WeekStrip.js.map +1 -0
  140. package/lib/module/expandable/calendarCells.js +142 -0
  141. package/lib/module/expandable/calendarCells.js.map +1 -0
  142. package/lib/module/expandable/geometry.js +58 -0
  143. package/lib/module/expandable/geometry.js.map +1 -0
  144. package/lib/module/expandable/useExpandGesture.js +118 -0
  145. package/lib/module/expandable/useExpandGesture.js.map +1 -0
  146. package/lib/module/expandable/useHorizontalPager.js +92 -0
  147. package/lib/module/expandable/useHorizontalPager.js.map +1 -0
  148. package/lib/module/index.js +35 -0
  149. package/lib/module/index.js.map +1 -0
  150. package/lib/module/package.json +1 -0
  151. package/lib/module/theme/ThemeProvider.js +65 -0
  152. package/lib/module/theme/ThemeProvider.js.map +1 -0
  153. package/lib/module/theme/index.js +6 -0
  154. package/lib/module/theme/index.js.map +1 -0
  155. package/lib/module/theme/theme.js +74 -0
  156. package/lib/module/theme/theme.js.map +1 -0
  157. package/lib/module/theme/tokens.js +50 -0
  158. package/lib/module/theme/tokens.js.map +1 -0
  159. package/lib/module/timeline/DayColumn.js +91 -0
  160. package/lib/module/timeline/DayColumn.js.map +1 -0
  161. package/lib/module/timeline/DayPager.js +245 -0
  162. package/lib/module/timeline/DayPager.js.map +1 -0
  163. package/lib/module/timeline/EventBlock.js +87 -0
  164. package/lib/module/timeline/EventBlock.js.map +1 -0
  165. package/lib/module/timeline/GridLines.js +43 -0
  166. package/lib/module/timeline/GridLines.js.map +1 -0
  167. package/lib/module/timeline/HourGrid.js +94 -0
  168. package/lib/module/timeline/HourGrid.js.map +1 -0
  169. package/lib/module/timeline/NowIndicator.js +126 -0
  170. package/lib/module/timeline/NowIndicator.js.map +1 -0
  171. package/lib/module/timeline/TimelineDay.js +122 -0
  172. package/lib/module/timeline/TimelineDay.js.map +1 -0
  173. package/lib/module/timeline/packEvents.js +97 -0
  174. package/lib/module/timeline/packEvents.js.map +1 -0
  175. package/lib/module/timeline/timelineGeometry.js +22 -0
  176. package/lib/module/timeline/timelineGeometry.js.map +1 -0
  177. package/lib/module/timeline/timelineMath.js +75 -0
  178. package/lib/module/timeline/timelineMath.js.map +1 -0
  179. package/lib/module/types.js +67 -0
  180. package/lib/module/types.js.map +1 -0
  181. package/lib/typescript/commonjs/agenda/AgendaBackdrop.d.ts +20 -0
  182. package/lib/typescript/commonjs/agenda/AgendaBackdrop.d.ts.map +1 -0
  183. package/lib/typescript/commonjs/agenda/AgendaList.d.ts +12 -0
  184. package/lib/typescript/commonjs/agenda/AgendaList.d.ts.map +1 -0
  185. package/lib/typescript/commonjs/agenda/AgendaSlot.d.ts +45 -0
  186. package/lib/typescript/commonjs/agenda/AgendaSlot.d.ts.map +1 -0
  187. package/lib/typescript/commonjs/agenda/AgendaWindow.d.ts +49 -0
  188. package/lib/typescript/commonjs/agenda/AgendaWindow.d.ts.map +1 -0
  189. package/lib/typescript/commonjs/agenda/StickyHeaderOverlay.d.ts +39 -0
  190. package/lib/typescript/commonjs/agenda/StickyHeaderOverlay.d.ts.map +1 -0
  191. package/lib/typescript/commonjs/agenda/buildAgendaLayout.d.ts +57 -0
  192. package/lib/typescript/commonjs/agenda/buildAgendaLayout.d.ts.map +1 -0
  193. package/lib/typescript/commonjs/agenda/constants.d.ts +19 -0
  194. package/lib/typescript/commonjs/agenda/constants.d.ts.map +1 -0
  195. package/lib/typescript/commonjs/agenda/heights.d.ts +20 -0
  196. package/lib/typescript/commonjs/agenda/heights.d.ts.map +1 -0
  197. package/lib/typescript/commonjs/agenda/useAgendaScrollSync.d.ts +44 -0
  198. package/lib/typescript/commonjs/agenda/useAgendaScrollSync.d.ts.map +1 -0
  199. package/lib/typescript/commonjs/core/ArrowGlyph.d.ts +14 -0
  200. package/lib/typescript/commonjs/core/ArrowGlyph.d.ts.map +1 -0
  201. package/lib/typescript/commonjs/core/CalendarContext.d.ts +35 -0
  202. package/lib/typescript/commonjs/core/CalendarContext.d.ts.map +1 -0
  203. package/lib/typescript/commonjs/core/CalendarProvider.d.ts +41 -0
  204. package/lib/typescript/commonjs/core/CalendarProvider.d.ts.map +1 -0
  205. package/lib/typescript/commonjs/core/CalendarStore.d.ts +28 -0
  206. package/lib/typescript/commonjs/core/CalendarStore.d.ts.map +1 -0
  207. package/lib/typescript/commonjs/core/KitText.d.ts +10 -0
  208. package/lib/typescript/commonjs/core/KitText.d.ts.map +1 -0
  209. package/lib/typescript/commonjs/core/TodayButton.d.ts +18 -0
  210. package/lib/typescript/commonjs/core/TodayButton.d.ts.map +1 -0
  211. package/lib/typescript/commonjs/core/civil.d.ts +26 -0
  212. package/lib/typescript/commonjs/core/civil.d.ts.map +1 -0
  213. package/lib/typescript/commonjs/core/dateKey.d.ts +21 -0
  214. package/lib/typescript/commonjs/core/dateKey.d.ts.map +1 -0
  215. package/lib/typescript/commonjs/core/motion.d.ts +18 -0
  216. package/lib/typescript/commonjs/core/motion.d.ts.map +1 -0
  217. package/lib/typescript/commonjs/core/worklets.d.ts +12 -0
  218. package/lib/typescript/commonjs/core/worklets.d.ts.map +1 -0
  219. package/lib/typescript/commonjs/expandable/DayCell.d.ts +22 -0
  220. package/lib/typescript/commonjs/expandable/DayCell.d.ts.map +1 -0
  221. package/lib/typescript/commonjs/expandable/ExpandableCalendar.d.ts +40 -0
  222. package/lib/typescript/commonjs/expandable/ExpandableCalendar.d.ts.map +1 -0
  223. package/lib/typescript/commonjs/expandable/Knob.d.ts +19 -0
  224. package/lib/typescript/commonjs/expandable/Knob.d.ts.map +1 -0
  225. package/lib/typescript/commonjs/expandable/MonthPager.d.ts +35 -0
  226. package/lib/typescript/commonjs/expandable/MonthPager.d.ts.map +1 -0
  227. package/lib/typescript/commonjs/expandable/WeekStrip.d.ts +34 -0
  228. package/lib/typescript/commonjs/expandable/WeekStrip.d.ts.map +1 -0
  229. package/lib/typescript/commonjs/expandable/calendarCells.d.ts +52 -0
  230. package/lib/typescript/commonjs/expandable/calendarCells.d.ts.map +1 -0
  231. package/lib/typescript/commonjs/expandable/geometry.d.ts +43 -0
  232. package/lib/typescript/commonjs/expandable/geometry.d.ts.map +1 -0
  233. package/lib/typescript/commonjs/expandable/useExpandGesture.d.ts +35 -0
  234. package/lib/typescript/commonjs/expandable/useExpandGesture.d.ts.map +1 -0
  235. package/lib/typescript/commonjs/expandable/useHorizontalPager.d.ts +35 -0
  236. package/lib/typescript/commonjs/expandable/useHorizontalPager.d.ts.map +1 -0
  237. package/lib/typescript/commonjs/index.d.ts +26 -0
  238. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  239. package/lib/typescript/commonjs/package.json +1 -0
  240. package/lib/typescript/commonjs/theme/ThemeProvider.d.ts +27 -0
  241. package/lib/typescript/commonjs/theme/ThemeProvider.d.ts.map +1 -0
  242. package/lib/typescript/commonjs/theme/index.d.ts +4 -0
  243. package/lib/typescript/commonjs/theme/index.d.ts.map +1 -0
  244. package/lib/typescript/commonjs/theme/theme.d.ts +62 -0
  245. package/lib/typescript/commonjs/theme/theme.d.ts.map +1 -0
  246. package/lib/typescript/commonjs/theme/tokens.d.ts +46 -0
  247. package/lib/typescript/commonjs/theme/tokens.d.ts.map +1 -0
  248. package/lib/typescript/commonjs/timeline/DayColumn.d.ts +32 -0
  249. package/lib/typescript/commonjs/timeline/DayColumn.d.ts.map +1 -0
  250. package/lib/typescript/commonjs/timeline/DayPager.d.ts +32 -0
  251. package/lib/typescript/commonjs/timeline/DayPager.d.ts.map +1 -0
  252. package/lib/typescript/commonjs/timeline/EventBlock.d.ts +17 -0
  253. package/lib/typescript/commonjs/timeline/EventBlock.d.ts.map +1 -0
  254. package/lib/typescript/commonjs/timeline/GridLines.d.ts +5 -0
  255. package/lib/typescript/commonjs/timeline/GridLines.d.ts.map +1 -0
  256. package/lib/typescript/commonjs/timeline/HourGrid.d.ts +12 -0
  257. package/lib/typescript/commonjs/timeline/HourGrid.d.ts.map +1 -0
  258. package/lib/typescript/commonjs/timeline/NowIndicator.d.ts +28 -0
  259. package/lib/typescript/commonjs/timeline/NowIndicator.d.ts.map +1 -0
  260. package/lib/typescript/commonjs/timeline/TimelineDay.d.ts +14 -0
  261. package/lib/typescript/commonjs/timeline/TimelineDay.d.ts.map +1 -0
  262. package/lib/typescript/commonjs/timeline/packEvents.d.ts +25 -0
  263. package/lib/typescript/commonjs/timeline/packEvents.d.ts.map +1 -0
  264. package/lib/typescript/commonjs/timeline/timelineGeometry.d.ts +14 -0
  265. package/lib/typescript/commonjs/timeline/timelineGeometry.d.ts.map +1 -0
  266. package/lib/typescript/commonjs/timeline/timelineMath.d.ts +32 -0
  267. package/lib/typescript/commonjs/timeline/timelineMath.d.ts.map +1 -0
  268. package/lib/typescript/commonjs/types.d.ts +237 -0
  269. package/lib/typescript/commonjs/types.d.ts.map +1 -0
  270. package/lib/typescript/module/agenda/AgendaBackdrop.d.ts +20 -0
  271. package/lib/typescript/module/agenda/AgendaBackdrop.d.ts.map +1 -0
  272. package/lib/typescript/module/agenda/AgendaList.d.ts +12 -0
  273. package/lib/typescript/module/agenda/AgendaList.d.ts.map +1 -0
  274. package/lib/typescript/module/agenda/AgendaSlot.d.ts +45 -0
  275. package/lib/typescript/module/agenda/AgendaSlot.d.ts.map +1 -0
  276. package/lib/typescript/module/agenda/AgendaWindow.d.ts +49 -0
  277. package/lib/typescript/module/agenda/AgendaWindow.d.ts.map +1 -0
  278. package/lib/typescript/module/agenda/StickyHeaderOverlay.d.ts +39 -0
  279. package/lib/typescript/module/agenda/StickyHeaderOverlay.d.ts.map +1 -0
  280. package/lib/typescript/module/agenda/buildAgendaLayout.d.ts +57 -0
  281. package/lib/typescript/module/agenda/buildAgendaLayout.d.ts.map +1 -0
  282. package/lib/typescript/module/agenda/constants.d.ts +19 -0
  283. package/lib/typescript/module/agenda/constants.d.ts.map +1 -0
  284. package/lib/typescript/module/agenda/heights.d.ts +20 -0
  285. package/lib/typescript/module/agenda/heights.d.ts.map +1 -0
  286. package/lib/typescript/module/agenda/useAgendaScrollSync.d.ts +44 -0
  287. package/lib/typescript/module/agenda/useAgendaScrollSync.d.ts.map +1 -0
  288. package/lib/typescript/module/core/ArrowGlyph.d.ts +14 -0
  289. package/lib/typescript/module/core/ArrowGlyph.d.ts.map +1 -0
  290. package/lib/typescript/module/core/CalendarContext.d.ts +35 -0
  291. package/lib/typescript/module/core/CalendarContext.d.ts.map +1 -0
  292. package/lib/typescript/module/core/CalendarProvider.d.ts +41 -0
  293. package/lib/typescript/module/core/CalendarProvider.d.ts.map +1 -0
  294. package/lib/typescript/module/core/CalendarStore.d.ts +28 -0
  295. package/lib/typescript/module/core/CalendarStore.d.ts.map +1 -0
  296. package/lib/typescript/module/core/KitText.d.ts +10 -0
  297. package/lib/typescript/module/core/KitText.d.ts.map +1 -0
  298. package/lib/typescript/module/core/TodayButton.d.ts +18 -0
  299. package/lib/typescript/module/core/TodayButton.d.ts.map +1 -0
  300. package/lib/typescript/module/core/civil.d.ts +26 -0
  301. package/lib/typescript/module/core/civil.d.ts.map +1 -0
  302. package/lib/typescript/module/core/dateKey.d.ts +21 -0
  303. package/lib/typescript/module/core/dateKey.d.ts.map +1 -0
  304. package/lib/typescript/module/core/motion.d.ts +18 -0
  305. package/lib/typescript/module/core/motion.d.ts.map +1 -0
  306. package/lib/typescript/module/core/worklets.d.ts +12 -0
  307. package/lib/typescript/module/core/worklets.d.ts.map +1 -0
  308. package/lib/typescript/module/expandable/DayCell.d.ts +22 -0
  309. package/lib/typescript/module/expandable/DayCell.d.ts.map +1 -0
  310. package/lib/typescript/module/expandable/ExpandableCalendar.d.ts +40 -0
  311. package/lib/typescript/module/expandable/ExpandableCalendar.d.ts.map +1 -0
  312. package/lib/typescript/module/expandable/Knob.d.ts +19 -0
  313. package/lib/typescript/module/expandable/Knob.d.ts.map +1 -0
  314. package/lib/typescript/module/expandable/MonthPager.d.ts +35 -0
  315. package/lib/typescript/module/expandable/MonthPager.d.ts.map +1 -0
  316. package/lib/typescript/module/expandable/WeekStrip.d.ts +34 -0
  317. package/lib/typescript/module/expandable/WeekStrip.d.ts.map +1 -0
  318. package/lib/typescript/module/expandable/calendarCells.d.ts +52 -0
  319. package/lib/typescript/module/expandable/calendarCells.d.ts.map +1 -0
  320. package/lib/typescript/module/expandable/geometry.d.ts +43 -0
  321. package/lib/typescript/module/expandable/geometry.d.ts.map +1 -0
  322. package/lib/typescript/module/expandable/useExpandGesture.d.ts +35 -0
  323. package/lib/typescript/module/expandable/useExpandGesture.d.ts.map +1 -0
  324. package/lib/typescript/module/expandable/useHorizontalPager.d.ts +35 -0
  325. package/lib/typescript/module/expandable/useHorizontalPager.d.ts.map +1 -0
  326. package/lib/typescript/module/index.d.ts +26 -0
  327. package/lib/typescript/module/index.d.ts.map +1 -0
  328. package/lib/typescript/module/package.json +1 -0
  329. package/lib/typescript/module/theme/ThemeProvider.d.ts +27 -0
  330. package/lib/typescript/module/theme/ThemeProvider.d.ts.map +1 -0
  331. package/lib/typescript/module/theme/index.d.ts +4 -0
  332. package/lib/typescript/module/theme/index.d.ts.map +1 -0
  333. package/lib/typescript/module/theme/theme.d.ts +62 -0
  334. package/lib/typescript/module/theme/theme.d.ts.map +1 -0
  335. package/lib/typescript/module/theme/tokens.d.ts +46 -0
  336. package/lib/typescript/module/theme/tokens.d.ts.map +1 -0
  337. package/lib/typescript/module/timeline/DayColumn.d.ts +32 -0
  338. package/lib/typescript/module/timeline/DayColumn.d.ts.map +1 -0
  339. package/lib/typescript/module/timeline/DayPager.d.ts +32 -0
  340. package/lib/typescript/module/timeline/DayPager.d.ts.map +1 -0
  341. package/lib/typescript/module/timeline/EventBlock.d.ts +17 -0
  342. package/lib/typescript/module/timeline/EventBlock.d.ts.map +1 -0
  343. package/lib/typescript/module/timeline/GridLines.d.ts +5 -0
  344. package/lib/typescript/module/timeline/GridLines.d.ts.map +1 -0
  345. package/lib/typescript/module/timeline/HourGrid.d.ts +12 -0
  346. package/lib/typescript/module/timeline/HourGrid.d.ts.map +1 -0
  347. package/lib/typescript/module/timeline/NowIndicator.d.ts +28 -0
  348. package/lib/typescript/module/timeline/NowIndicator.d.ts.map +1 -0
  349. package/lib/typescript/module/timeline/TimelineDay.d.ts +14 -0
  350. package/lib/typescript/module/timeline/TimelineDay.d.ts.map +1 -0
  351. package/lib/typescript/module/timeline/packEvents.d.ts +25 -0
  352. package/lib/typescript/module/timeline/packEvents.d.ts.map +1 -0
  353. package/lib/typescript/module/timeline/timelineGeometry.d.ts +14 -0
  354. package/lib/typescript/module/timeline/timelineGeometry.d.ts.map +1 -0
  355. package/lib/typescript/module/timeline/timelineMath.d.ts +32 -0
  356. package/lib/typescript/module/timeline/timelineMath.d.ts.map +1 -0
  357. package/lib/typescript/module/types.d.ts +237 -0
  358. package/lib/typescript/module/types.d.ts.map +1 -0
  359. package/package.json +105 -0
  360. package/src/agenda/AgendaBackdrop.tsx +55 -0
  361. package/src/agenda/AgendaList.tsx +370 -0
  362. package/src/agenda/AgendaSlot.tsx +88 -0
  363. package/src/agenda/AgendaWindow.tsx +183 -0
  364. package/src/agenda/StickyHeaderOverlay.tsx +126 -0
  365. package/src/agenda/buildAgendaLayout.ts +110 -0
  366. package/src/agenda/constants.ts +22 -0
  367. package/src/agenda/heights.ts +44 -0
  368. package/src/agenda/useAgendaScrollSync.ts +251 -0
  369. package/src/core/ArrowGlyph.tsx +53 -0
  370. package/src/core/CalendarContext.ts +47 -0
  371. package/src/core/CalendarProvider.tsx +165 -0
  372. package/src/core/CalendarStore.ts +64 -0
  373. package/src/core/KitText.tsx +10 -0
  374. package/src/core/TodayButton.tsx +121 -0
  375. package/src/core/civil.ts +92 -0
  376. package/src/core/dateKey.ts +52 -0
  377. package/src/core/motion.ts +51 -0
  378. package/src/core/worklets.ts +37 -0
  379. package/src/expandable/DayCell.tsx +97 -0
  380. package/src/expandable/ExpandableCalendar.tsx +278 -0
  381. package/src/expandable/Knob.tsx +67 -0
  382. package/src/expandable/MonthPager.tsx +208 -0
  383. package/src/expandable/WeekStrip.tsx +439 -0
  384. package/src/expandable/calendarCells.ts +155 -0
  385. package/src/expandable/geometry.ts +51 -0
  386. package/src/expandable/useExpandGesture.ts +147 -0
  387. package/src/expandable/useHorizontalPager.ts +116 -0
  388. package/src/index.ts +62 -0
  389. package/src/theme/ThemeProvider.tsx +85 -0
  390. package/src/theme/index.ts +18 -0
  391. package/src/theme/theme.ts +110 -0
  392. package/src/theme/tokens.ts +50 -0
  393. package/src/timeline/DayColumn.tsx +84 -0
  394. package/src/timeline/DayPager.tsx +295 -0
  395. package/src/timeline/EventBlock.tsx +76 -0
  396. package/src/timeline/GridLines.tsx +36 -0
  397. package/src/timeline/HourGrid.tsx +90 -0
  398. package/src/timeline/NowIndicator.tsx +123 -0
  399. package/src/timeline/TimelineDay.tsx +112 -0
  400. package/src/timeline/packEvents.ts +118 -0
  401. package/src/timeline/timelineGeometry.ts +23 -0
  402. package/src/timeline/timelineMath.ts +86 -0
  403. package/src/types.ts +252 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Day columns, paged horizontally across the SELECTABLE days (the range is padded to whole weeks;
3
+ * a swipe must not land on padding). Column `i` sits at `(i − minIndex) · width`; only the centre
4
+ * and its neighbours are mounted. Content stacking is the library's: bands → lines → events.
5
+ *
6
+ * The doctor's swipe commits at MOMENTUM END as `origin: 'timeline'`, which this pager ignores.
7
+ * Any other move animates to a mounted neighbour, or mounts the destination first (keeping the
8
+ * current columns), jumps once it exists, and releases the old columns on the first scroll there.
9
+ *
10
+ * `contentOffset` is read once: the native ScrollView re-applies it whenever its value changes, so
11
+ * a width-derived offset per render would throw the pager back to the day it opened on.
12
+ */
13
+
14
+ import {
15
+ memo,
16
+ useCallback,
17
+ useEffect,
18
+ useLayoutEffect,
19
+ useMemo,
20
+ useRef,
21
+ useState,
22
+ type ReactElement,
23
+ } from 'react';
24
+ import { StyleSheet, View } from 'react-native';
25
+ import Animated, {
26
+ scrollTo,
27
+ useAnimatedReaction,
28
+ useAnimatedRef,
29
+ useAnimatedScrollHandler,
30
+ useSharedValue,
31
+ } from 'react-native-reanimated';
32
+ import { runOnJS, scheduleOnUI } from 'react-native-worklets';
33
+ import { useCalendarContext } from '../core/CalendarContext';
34
+ import { clampIndex, dayIndexOf, ymdAt } from '../core/dateKey';
35
+ import type { AvailableHours, DateString, PackedTimelineEvent, TimelineEvent } from '../types';
36
+ import { DayBands, DayEvents } from './DayColumn';
37
+ import { ColumnLines } from './GridLines';
38
+ import { NowKnob, useNowMinutesSV } from './NowIndicator';
39
+
40
+ const offsetOfIndex = (idx: number, minIndex: number, width: number): number => {
41
+ 'worklet';
42
+ return (idx - minIndex) * width;
43
+ };
44
+
45
+ const indexAtOffset = (x: number, minIndex: number, width: number): number => {
46
+ 'worklet';
47
+ return minIndex + Math.round(x / width);
48
+ };
49
+
50
+ type Props<E extends TimelineEvent> = {
51
+ left: number;
52
+ width: number;
53
+ height: number;
54
+ events: Record<DateString, E[]>;
55
+ availableHoursFor: (ymd: DateString) => AvailableHours | undefined;
56
+ bandColor: string;
57
+ hourHeight: number;
58
+ overlapEventsSpacing: number;
59
+ rightEdgeSpacing: number;
60
+ renderEvent?: (event: PackedTimelineEvent<E>) => ReactElement | null;
61
+ onEventPress?: (event: PackedTimelineEvent<E>) => void;
62
+ showNowIndicator: boolean;
63
+ };
64
+
65
+ const DayPagerInner = <E extends TimelineEvent>({
66
+ left,
67
+ width,
68
+ height,
69
+ events,
70
+ availableHoursFor,
71
+ bandColor,
72
+ hourHeight,
73
+ overlapEventsSpacing,
74
+ rightEdgeSpacing,
75
+ renderEvent,
76
+ onEventPress,
77
+ showNowIndicator,
78
+ }: Props<E>) => {
79
+ const { range, store, dateRef, commitDate } = useCalendarContext();
80
+ const listRef = useAnimatedRef<Animated.ScrollView>();
81
+
82
+ // Plain numbers for the worklets: a captured `range` would be frozen in dev.
83
+ const { minIndex, maxIndex, todayIndex } = range;
84
+ const pageCount = maxIndex - minIndex + 1;
85
+ const todayPage = todayIndex >= minIndex && todayIndex <= maxIndex ? todayIndex - minIndex : -1;
86
+ const showNow = showNowIndicator && todayPage >= 0;
87
+ const nowMinutes = useNowMinutesSV(showNow);
88
+
89
+ const [initialCenter] = useState(() => clampIndex(range, dayIndexOf(range, dateRef.current)));
90
+ const [initialOffset] = useState(() => ({ x: offsetOfIndex(initialCenter, minIndex, width), y: 0 }));
91
+ const [center, setCenter] = useState(initialCenter);
92
+ const [jumpFrom, setJumpFrom] = useState<number | null>(null);
93
+ const pendingX = useRef<number | null>(null);
94
+
95
+ const centerSV = useSharedValue(initialCenter);
96
+ const widthSV = useSharedValue(width);
97
+ const scrollX = useSharedValue(initialOffset.x);
98
+ const userDriven = useSharedValue(0);
99
+ const ready = useSharedValue(0);
100
+ const releaseAtX = useSharedValue(-1);
101
+
102
+ // Every column just moved: land back on the day that was showing.
103
+ useEffect(() => {
104
+ scheduleOnUI(() => {
105
+ 'worklet';
106
+ if (widthSV.value === width) return;
107
+ widthSV.value = width;
108
+ const x = offsetOfIndex(centerSV.value, minIndex, width);
109
+ scrollX.value = x;
110
+ scrollTo(listRef, x, 0, false);
111
+ });
112
+ }, [centerSV, listRef, minIndex, scrollX, width, widthSV]);
113
+
114
+ /** The doctor's swipe settled on a new day. */
115
+ const onSwipeSettled = useCallback(
116
+ (idx: number) => {
117
+ setCenter(idx);
118
+ commitDate(idx, 'listDrag', 'timeline');
119
+ },
120
+ [commitDate],
121
+ );
122
+
123
+ const prepareJump = useCallback(
124
+ (idx: number, x: number) => {
125
+ pendingX.current = x;
126
+ setJumpFrom(centerSV.value);
127
+ setCenter(idx);
128
+ },
129
+ [centerSV],
130
+ );
131
+
132
+ const releaseJump = useCallback(() => setJumpFrom(null), []);
133
+
134
+ // The destination columns are committed: land on them.
135
+ useLayoutEffect(() => {
136
+ const x = pendingX.current;
137
+ if (x === null) return;
138
+ pendingX.current = null;
139
+ centerSV.value = center;
140
+ scheduleOnUI(() => {
141
+ 'worklet';
142
+ releaseAtX.value = x;
143
+ userDriven.value = 0;
144
+ scrollX.value = x;
145
+ scrollTo(listRef, x, 0, false);
146
+ });
147
+ }, [center, centerSV, listRef, releaseAtX, scrollX, userDriven]);
148
+
149
+ useAnimatedReaction(
150
+ () => store.move.value,
151
+ (m, prev) => {
152
+ if (!prev || m.seq === prev.seq || m.origin === 'timeline') return;
153
+ if (ready.value === 0) return;
154
+ const idx = m.idx < minIndex ? minIndex : m.idx > maxIndex ? maxIndex : m.idx;
155
+ const x = offsetOfIndex(idx, minIndex, widthSV.value);
156
+ userDriven.value = 0;
157
+ if (Math.abs(idx - centerSV.value) <= 1) {
158
+ scrollTo(listRef, x, 0, m.animated);
159
+ if (idx !== centerSV.value) {
160
+ centerSV.value = idx;
161
+ runOnJS(setCenter)(idx);
162
+ }
163
+ return;
164
+ }
165
+ runOnJS(prepareJump)(idx, x);
166
+ },
167
+ );
168
+
169
+ const onScroll = useAnimatedScrollHandler({
170
+ onScroll: (e) => {
171
+ scrollX.value = e.contentOffset.x;
172
+ if (releaseAtX.value >= 0 && Math.abs(e.contentOffset.x - releaseAtX.value) < 1) {
173
+ releaseAtX.value = -1;
174
+ runOnJS(releaseJump)();
175
+ }
176
+ },
177
+ onBeginDrag: () => {
178
+ userDriven.value = 1;
179
+ },
180
+ onMomentumEnd: (e) => {
181
+ const idx = indexAtOffset(e.contentOffset.x, minIndex, widthSV.value);
182
+ const wasUser = userDriven.value === 1;
183
+ userDriven.value = 0;
184
+ if (!wasUser || idx === centerSV.value) return;
185
+ // This pager owns the position while the doctor swipes it, so it writes
186
+ // the UI-thread date itself; `commitDate` deliberately does not.
187
+ store.dayIndex.value = idx;
188
+ centerSV.value = idx;
189
+ runOnJS(onSwipeSettled)(idx);
190
+ },
191
+ });
192
+
193
+ const onLayout = useCallback(() => {
194
+ ready.value = 1;
195
+ }, [ready]);
196
+
197
+ const layers = useMemo(() => {
198
+ const bands: ReactElement[] = [];
199
+ const dayEvents: ReactElement[] = [];
200
+ const lo = jumpFrom === null || center <= jumpFrom ? center : jumpFrom;
201
+ const hi = jumpFrom === null || center >= jumpFrom ? center : jumpFrom;
202
+ let last = minIndex - 1;
203
+ // Two ascending 3-day windows; starting past `last` skips the days they share.
204
+ for (let pass = 0; pass < 2; pass += 1) {
205
+ const c = pass === 0 ? lo : hi;
206
+ for (let i = Math.max(c - 1, last + 1); i <= c + 1 && i <= maxIndex; i += 1) {
207
+ last = i;
208
+ const ymd = ymdAt(range, i);
209
+ const colLeft = offsetOfIndex(i, minIndex, width);
210
+ bands.push(
211
+ <DayBands
212
+ key={ymd}
213
+ left={colLeft}
214
+ width={width}
215
+ availableHours={availableHoursFor(ymd)}
216
+ color={bandColor}
217
+ hourHeight={hourHeight}
218
+ />,
219
+ );
220
+ dayEvents.push(
221
+ <DayEvents
222
+ key={ymd}
223
+ left={colLeft}
224
+ width={width}
225
+ events={events[ymd]}
226
+ hourHeight={hourHeight}
227
+ overlapEventsSpacing={overlapEventsSpacing}
228
+ rightEdgeSpacing={rightEdgeSpacing}
229
+ renderEvent={renderEvent}
230
+ onEventPress={onEventPress}
231
+ nowMinutes={showNow && i === todayIndex ? nowMinutes : undefined}
232
+ />,
233
+ );
234
+ }
235
+ }
236
+ return { bands, dayEvents };
237
+ }, [
238
+ availableHoursFor,
239
+ bandColor,
240
+ center,
241
+ events,
242
+ hourHeight,
243
+ jumpFrom,
244
+ maxIndex,
245
+ minIndex,
246
+ nowMinutes,
247
+ onEventPress,
248
+ overlapEventsSpacing,
249
+ range,
250
+ renderEvent,
251
+ rightEdgeSpacing,
252
+ showNow,
253
+ todayIndex,
254
+ width,
255
+ ]);
256
+
257
+ return (
258
+ <>
259
+ <Animated.ScrollView
260
+ ref={listRef}
261
+ horizontal
262
+ pagingEnabled
263
+ nestedScrollEnabled
264
+ showsHorizontalScrollIndicator={false}
265
+ onScroll={onScroll}
266
+ scrollEventThrottle={16}
267
+ contentOffset={initialOffset}
268
+ onLayout={onLayout}
269
+ style={[styles.pager, { left, width, height }]}
270
+ >
271
+ <View style={{ width: pageCount * width, height }}>
272
+ {layers.bands}
273
+ <ColumnLines hourHeight={hourHeight} />
274
+ {layers.dayEvents}
275
+ </View>
276
+ </Animated.ScrollView>
277
+ {showNow ? (
278
+ <NowKnob
279
+ left={left}
280
+ hourHeight={hourHeight}
281
+ minutes={nowMinutes}
282
+ page={todayPage}
283
+ pageWidth={widthSV}
284
+ scrollX={scrollX}
285
+ />
286
+ ) : null}
287
+ </>
288
+ );
289
+ };
290
+
291
+ export const DayPager = memo(DayPagerInner) as typeof DayPagerInner;
292
+
293
+ const styles = StyleSheet.create({
294
+ pager: { position: 'absolute', top: 0 },
295
+ });
@@ -0,0 +1,76 @@
1
+ /**
2
+ * One packed event: the library's `EventBlock` container (absolute, `minHeight: 25`, padding 4/5,
3
+ * 0.9 opacity when pressed) around the caller's `renderEvent`. The fill is the event's own colour,
4
+ * else the soft accent token; the hairline ring gives a pastel block an edge on the dark palette
5
+ *.
6
+ */
7
+
8
+ import { useKitStyles, type KitStyleArgs } from '../theme';
9
+ import { FONT_SIZE, RADIUS } from '../theme/tokens';
10
+ import { memo, useCallback, useMemo, type ReactElement } from 'react';
11
+ import { Pressable, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
12
+ import { KitText } from '../core/KitText';
13
+ import type { PackedTimelineEvent, TimelineEvent } from '../types';
14
+ import { EVENT_MIN_HEIGHT } from './timelineGeometry';
15
+
16
+ type Props<E extends TimelineEvent> = {
17
+ event: PackedTimelineEvent<E>;
18
+ renderEvent?: (event: PackedTimelineEvent<E>) => ReactElement | null;
19
+ onPress?: (event: PackedTimelineEvent<E>) => void;
20
+ };
21
+
22
+ const EventBlockInner = <E extends TimelineEvent>({ event, renderEvent, onPress }: Props<E>) => {
23
+ const styles = useKitStyles(makeStyles);
24
+ const handlePress = useCallback(() => onPress?.(event), [event, onPress]);
25
+
26
+ const { color, left, top, width, height } = event;
27
+ const blockStyle = useMemo(() => {
28
+ const rest: StyleProp<ViewStyle> = [
29
+ styles.block,
30
+ color ? { backgroundColor: color } : styles.blockDefault,
31
+ { left, top, width, height },
32
+ ];
33
+ const pressed: StyleProp<ViewStyle> = [rest, styles.pressed];
34
+ return { rest, pressed };
35
+ }, [color, height, left, styles, top, width]);
36
+
37
+ return (
38
+ <Pressable
39
+ onPress={handlePress}
40
+ style={({ pressed }) => (pressed ? blockStyle.pressed : blockStyle.rest)}
41
+ >
42
+ {renderEvent ? (
43
+ renderEvent(event)
44
+ ) : (
45
+ <KitText style={styles.title} numberOfLines={1}>
46
+ {event.title}
47
+ </KitText>
48
+ )}
49
+ </Pressable>
50
+ );
51
+ };
52
+
53
+ export const EventBlock = memo(EventBlockInner) as typeof EventBlockInner;
54
+
55
+ const makeStyles = ({ colors, fonts }: KitStyleArgs) =>
56
+ StyleSheet.create({
57
+ block: {
58
+ position: 'absolute',
59
+ minHeight: EVENT_MIN_HEIGHT,
60
+ paddingLeft: 4,
61
+ paddingTop: 5,
62
+ flexDirection: 'column',
63
+ alignItems: 'flex-start',
64
+ overflow: 'hidden',
65
+ borderRadius: RADIUS.inner,
66
+ borderWidth: StyleSheet.hairlineWidth,
67
+ borderColor: colors.border,
68
+ },
69
+ blockDefault: { backgroundColor: colors.accentSoft },
70
+ pressed: { opacity: 0.9 },
71
+ title: {
72
+ fontFamily: fonts.semiBold,
73
+ fontSize: FONT_SIZE.xs,
74
+ color: colors.text,
75
+ },
76
+ });
@@ -0,0 +1,36 @@
1
+ /** The half-hour and hour lines: ONE layer across the pager's whole content, between bands and events. */
2
+
3
+ import { useKitStyles, type KitStyleArgs } from '../theme';
4
+ import { memo, useMemo, type ReactElement } from 'react';
5
+ import { StyleSheet, View } from 'react-native';
6
+
7
+ const ColumnLinesInner = ({ hourHeight }: { hourHeight: number }) => {
8
+ const styles = useKitStyles(makeStyles);
9
+ const lines = useMemo(() => {
10
+ const out: ReactElement[] = [];
11
+ for (let half = 1; half <= 48; half += 1) {
12
+ out.push(<View key={half} style={[styles.line, { top: (hourHeight * half) / 2 }]} />);
13
+ }
14
+ return out;
15
+ }, [hourHeight, styles.line]);
16
+
17
+ return (
18
+ <View pointerEvents="none" style={StyleSheet.absoluteFill}>
19
+ {lines}
20
+ </View>
21
+ );
22
+ };
23
+
24
+ export const ColumnLines = memo(ColumnLinesInner);
25
+ ColumnLines.displayName = 'ColumnLines';
26
+
27
+ const makeStyles = ({ colors }: KitStyleArgs) =>
28
+ StyleSheet.create({
29
+ line: {
30
+ position: 'absolute',
31
+ left: 0,
32
+ right: 0,
33
+ height: 1,
34
+ backgroundColor: colors.border,
35
+ },
36
+ });
@@ -0,0 +1,90 @@
1
+ /**
2
+ * The time gutter: hour labels, the gutter's edge, and each line's 16 px stub into the gutter
3
+ * (`TimelineHours.js` starts lines at `timelineLeftInset − 16`). The stubs stay here because the
4
+ * pager starts at `GUTTER` and clips, so its shared line layer cannot reach into the gutter.
5
+ */
6
+
7
+ import { useKitStyles, type KitStyleArgs } from '../theme';
8
+ import { Fragment, memo, useMemo, type ReactElement } from 'react';
9
+ import { StyleSheet, View } from 'react-native';
10
+ import { KitText } from '../core/KitText';
11
+ import {
12
+ CONTENT_BOTTOM_PAD,
13
+ GUTTER,
14
+ LABEL_OFFSET_Y,
15
+ LABEL_PADDING_LEFT,
16
+ LINE_GUTTER_OVERHANG,
17
+ gridHeight,
18
+ } from './timelineGeometry';
19
+
20
+ /** `TimelineHours.js`: no label at 0, "23:59" at 24, no zero padding. */
21
+ const hourLabel = (i: number, format24h: boolean): string => {
22
+ if (i < 12) return format24h ? `${i}:00` : `${i} AM`;
23
+ if (i === 12) return format24h ? `${i}:00` : `${i} PM`;
24
+ if (i === 24) return format24h ? '23:59' : '12 AM';
25
+ return format24h ? `${i}:00` : `${i - 12} PM`;
26
+ };
27
+
28
+ type Props = { hourHeight: number; format24h: boolean };
29
+
30
+ const HourGridInner = ({ hourHeight, format24h }: Props) => {
31
+ const styles = useKitStyles(makeStyles);
32
+
33
+ const nodes = useMemo(() => {
34
+ const out: ReactElement[] = [];
35
+ for (let i = 0; i < 24; i += 1) {
36
+ const hourTop = hourHeight * (i + 1);
37
+ out.push(
38
+ <Fragment key={i}>
39
+ <View style={[styles.stub, { top: hourHeight * (i + 0.5) }]} />
40
+ <View style={[styles.stub, { top: hourTop }]} />
41
+ <KitText style={[styles.label, { top: hourTop + LABEL_OFFSET_Y }]}>
42
+ {hourLabel(i + 1, format24h)}
43
+ </KitText>
44
+ </Fragment>,
45
+ );
46
+ }
47
+ out.push(
48
+ <View key="edge" style={[styles.edge, { height: gridHeight(hourHeight) + CONTENT_BOTTOM_PAD }]} />,
49
+ );
50
+ return out;
51
+ }, [format24h, hourHeight, styles.edge, styles.label, styles.stub]);
52
+
53
+ return (
54
+ <View pointerEvents="none" style={StyleSheet.absoluteFill}>
55
+ {nodes}
56
+ </View>
57
+ );
58
+ };
59
+
60
+ export const HourGrid = memo(HourGridInner);
61
+ HourGrid.displayName = 'HourGrid';
62
+
63
+ const makeStyles = ({ colors, fonts }: KitStyleArgs) =>
64
+ StyleSheet.create({
65
+ label: {
66
+ position: 'absolute',
67
+ left: 0,
68
+ width: GUTTER - LINE_GUTTER_OVERHANG,
69
+ paddingLeft: LABEL_PADDING_LEFT,
70
+ textAlign: 'center',
71
+ fontFamily: fonts.medium,
72
+ fontSize: 10,
73
+ color: colors.textMuted,
74
+ },
75
+ stub: {
76
+ position: 'absolute',
77
+ left: GUTTER - LINE_GUTTER_OVERHANG,
78
+ width: LINE_GUTTER_OVERHANG,
79
+ height: 1,
80
+ backgroundColor: colors.border,
81
+ },
82
+ // The last gutter pixel (`TimelineHours.js`: `right: width`); at `GUTTER` the bands painted over it.
83
+ edge: {
84
+ position: 'absolute',
85
+ top: 0,
86
+ left: GUTTER - 1,
87
+ width: 1,
88
+ backgroundColor: colors.border,
89
+ },
90
+ });
@@ -0,0 +1,123 @@
1
+ /**
2
+ * The now-line. The minute lives in a SharedValue re-read just past each minute boundary (a bare
3
+ * 60 s interval started mid-minute runs late for the life of the screen) and on foreground; the
4
+ * line and knob move through animated styles, so a tick is zero React commits. No spring: a line
5
+ * that overshoots claims a time that is not now. The pager clips at the gutter, so `NowKnob` draws
6
+ * the whole dot above it at rest and hides mid-swipe — a worklet-driven knob trails by a frame.
7
+ */
8
+
9
+ import { useKitStyles, type KitStyleArgs } from '../theme';
10
+ import { RADIUS } from '../theme/tokens';
11
+ import { memo, useEffect } from 'react';
12
+ import { AppState, StyleSheet, View } from 'react-native';
13
+ import Animated, {
14
+ useAnimatedStyle,
15
+ useSharedValue,
16
+ type SharedValue,
17
+ } from 'react-native-reanimated';
18
+ import { NOW_KNOB } from './timelineGeometry';
19
+
20
+ const KNOB_HANG = Math.floor(NOW_KNOB / 2);
21
+ const SHOWN = { opacity: 1 };
22
+ const HIDDEN = { opacity: 0 };
23
+
24
+ const minutesAt = (d: Date) => d.getHours() * 60 + d.getMinutes();
25
+
26
+ /** Minutes since local midnight, shared by the line and the knob. Disabled means no timer. */
27
+ export const useNowMinutesSV = (enabled: boolean): SharedValue<number> => {
28
+ const minutes = useSharedValue(minutesAt(new Date()));
29
+
30
+ useEffect(() => {
31
+ if (!enabled) return;
32
+ let timer: ReturnType<typeof setTimeout> | undefined;
33
+ const tick = () => {
34
+ const now = new Date();
35
+ minutes.value = minutesAt(now);
36
+ // 50 ms past the boundary so the re-read lands in the new minute.
37
+ timer = setTimeout(tick, (60 - now.getSeconds()) * 1000 - now.getMilliseconds() + 50);
38
+ };
39
+ tick();
40
+ const sub = AppState.addEventListener('change', (state) => {
41
+ if (state !== 'active') return;
42
+ clearTimeout(timer);
43
+ tick();
44
+ });
45
+ return () => {
46
+ clearTimeout(timer);
47
+ sub.remove();
48
+ };
49
+ }, [enabled, minutes]);
50
+
51
+ return minutes;
52
+ };
53
+
54
+ type Props = { hourHeight: number; minutes: SharedValue<number> };
55
+
56
+ const NowIndicatorInner = ({ hourHeight, minutes }: Props) => {
57
+ const styles = useKitStyles(makeStyles);
58
+ const position = useAnimatedStyle(() => ({ top: (minutes.value / 60) * hourHeight }));
59
+ return (
60
+ <Animated.View pointerEvents="none" style={[styles.root, position]}>
61
+ <View style={styles.line} />
62
+ <View style={styles.knob} />
63
+ </Animated.View>
64
+ );
65
+ };
66
+
67
+ export const NowIndicator = memo(NowIndicatorInner);
68
+ NowIndicator.displayName = 'NowIndicator';
69
+
70
+ type KnobProps = {
71
+ /** The pager's left edge in the timeline content — where today's column starts at rest. */
72
+ left: number;
73
+ hourHeight: number;
74
+ minutes: SharedValue<number>;
75
+ /** Today's page, and the live pager position it is compared against. */
76
+ page: number;
77
+ pageWidth: SharedValue<number>;
78
+ scrollX: SharedValue<number>;
79
+ };
80
+
81
+ const NowKnobInner = ({ left, hourHeight, minutes, page, pageWidth, scrollX }: KnobProps) => {
82
+ const styles = useKitStyles(makeStyles);
83
+ const position = useAnimatedStyle(() => ({
84
+ top: (minutes.value / 60) * hourHeight - KNOB_HANG,
85
+ }));
86
+ // Runs every scroll frame: return the constants by reference, never a fresh object.
87
+ const atRest = useAnimatedStyle(() => {
88
+ const dx = page * pageWidth.value - scrollX.value;
89
+ return dx > -1 && dx < 1 ? SHOWN : HIDDEN;
90
+ });
91
+ return (
92
+ <Animated.View
93
+ pointerEvents="none"
94
+ style={[styles.knob, { left: left - KNOB_HANG }, position, atRest]}
95
+ />
96
+ );
97
+ };
98
+
99
+ export const NowKnob = memo(NowKnobInner);
100
+ NowKnob.displayName = 'NowKnob';
101
+
102
+ const makeStyles = ({ colors }: KitStyleArgs) =>
103
+ StyleSheet.create({
104
+ root: { position: 'absolute', left: 0, right: 0, height: 0 },
105
+ // The now-line carries information (this minute), so a status colour may appear.
106
+ line: {
107
+ position: 'absolute',
108
+ left: 0,
109
+ right: 0,
110
+ top: 0,
111
+ height: 1,
112
+ backgroundColor: colors.nowIndicator,
113
+ },
114
+ knob: {
115
+ position: 'absolute',
116
+ left: -KNOB_HANG,
117
+ top: -KNOB_HANG,
118
+ width: NOW_KNOB,
119
+ height: NOW_KNOB,
120
+ borderRadius: RADIUS.full,
121
+ backgroundColor: colors.nowIndicator,
122
+ },
123
+ });