@ankhorage/zora 15.0.0 → 16.0.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 (374) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +1 -1
  3. package/dist/constants.d.ts +5 -0
  4. package/dist/constants.d.ts.map +1 -1
  5. package/dist/constants.js +5 -0
  6. package/dist/constants.js.map +1 -1
  7. package/dist/features/accordion/accordionItemMeta.d.ts +1 -1
  8. package/dist/features/bottom-sheet/bottomSheetMeta.d.ts +1 -1
  9. package/dist/features/button/utils/resolveButtonThemeRecipe.d.ts +1 -1
  10. package/dist/features/card/cardMeta.d.ts +1 -1
  11. package/dist/features/card/mediaCardMeta.d.ts +1 -1
  12. package/dist/features/card/postCardMeta.d.ts +1 -1
  13. package/dist/features/dialog/adapters/inbound/Dialog.d.ts +5 -0
  14. package/dist/features/dialog/adapters/inbound/Dialog.d.ts.map +1 -0
  15. package/dist/features/dialog/adapters/inbound/Dialog.js +45 -0
  16. package/dist/features/dialog/adapters/inbound/Dialog.js.map +1 -0
  17. package/dist/features/dialog/dialogMeta.d.ts +87 -0
  18. package/dist/features/dialog/dialogMeta.d.ts.map +1 -0
  19. package/dist/features/dialog/dialogMeta.js +59 -0
  20. package/dist/features/dialog/dialogMeta.js.map +1 -0
  21. package/dist/features/dialog/public.d.ts +3 -0
  22. package/dist/features/dialog/public.d.ts.map +1 -0
  23. package/dist/features/dialog/public.js +2 -0
  24. package/dist/features/dialog/public.js.map +1 -0
  25. package/dist/features/form/formFieldMeta.d.ts +1 -1
  26. package/dist/features/form/formFieldMeta.d.ts.map +1 -1
  27. package/dist/features/form/formFieldMeta.js +8 -1
  28. package/dist/features/form/formFieldMeta.js.map +1 -1
  29. package/dist/features/form/radio/utils/resolveRadioGroupThemeRecipe.d.ts +1 -1
  30. package/dist/features/form/search-input/adapters/inbound/SearchInput.d.ts +4 -0
  31. package/dist/features/form/search-input/adapters/inbound/SearchInput.d.ts.map +1 -0
  32. package/dist/{components/search-bar/SearchBar.js → features/form/search-input/adapters/inbound/SearchInput.js} +8 -10
  33. package/dist/features/form/search-input/adapters/inbound/SearchInput.js.map +1 -0
  34. package/dist/features/form/search-input/public.d.ts +3 -0
  35. package/dist/features/form/search-input/public.d.ts.map +1 -0
  36. package/dist/features/form/search-input/public.js +2 -0
  37. package/dist/features/form/search-input/public.js.map +1 -0
  38. package/dist/features/form/search-input/searchInputMeta.d.ts +126 -0
  39. package/dist/features/form/search-input/searchInputMeta.d.ts.map +1 -0
  40. package/dist/features/form/search-input/searchInputMeta.js +67 -0
  41. package/dist/features/form/search-input/searchInputMeta.js.map +1 -0
  42. package/dist/features/gradient/gradientMeta.d.ts +1 -1
  43. package/dist/features/keyboard-avoiding-view/keyboardAvoidingViewMeta.d.ts +1 -1
  44. package/dist/features/layout/boxMeta.d.ts +1 -1
  45. package/dist/features/layout/containerMeta.d.ts +1 -1
  46. package/dist/features/layout/gridMeta.d.ts +1 -1
  47. package/dist/features/layout/stackMeta.d.ts +1 -1
  48. package/dist/features/list/flatListMeta.d.ts +1 -1
  49. package/dist/features/list/sectionListMeta.d.ts +1 -1
  50. package/dist/features/pagination/adapters/inbound/Pagination.d.ts +5 -0
  51. package/dist/features/pagination/adapters/inbound/Pagination.d.ts.map +1 -0
  52. package/dist/features/pagination/adapters/inbound/Pagination.js +43 -0
  53. package/dist/features/pagination/adapters/inbound/Pagination.js.map +1 -0
  54. package/dist/features/pagination/paginationMeta.d.ts +118 -0
  55. package/dist/features/pagination/paginationMeta.d.ts.map +1 -0
  56. package/dist/features/pagination/paginationMeta.js +53 -0
  57. package/dist/features/pagination/paginationMeta.js.map +1 -0
  58. package/dist/features/pagination/public.d.ts +3 -0
  59. package/dist/features/pagination/public.d.ts.map +1 -0
  60. package/dist/features/pagination/public.js +2 -0
  61. package/dist/features/pagination/public.js.map +1 -0
  62. package/dist/features/pagination/utils/resolvePaginationPage.d.ts +3 -0
  63. package/dist/features/pagination/utils/resolvePaginationPage.d.ts.map +1 -0
  64. package/dist/features/pagination/utils/resolvePaginationPage.js +7 -0
  65. package/dist/features/pagination/utils/resolvePaginationPage.js.map +1 -0
  66. package/dist/features/pagination/utils/resolvePaginationState.d.ts +17 -0
  67. package/dist/features/pagination/utils/resolvePaginationState.d.ts.map +1 -0
  68. package/dist/features/pagination/utils/resolvePaginationState.js +34 -0
  69. package/dist/features/pagination/utils/resolvePaginationState.js.map +1 -0
  70. package/dist/features/rating/adapters/inbound/Rating.d.ts +4 -0
  71. package/dist/features/rating/adapters/inbound/Rating.d.ts.map +1 -0
  72. package/dist/features/rating/adapters/inbound/Rating.js +49 -0
  73. package/dist/features/rating/adapters/inbound/Rating.js.map +1 -0
  74. package/dist/features/rating/public.d.ts +3 -0
  75. package/dist/features/rating/public.d.ts.map +1 -0
  76. package/dist/features/rating/public.js +2 -0
  77. package/dist/features/rating/public.js.map +1 -0
  78. package/dist/features/rating/ratingMeta.d.ts +57 -0
  79. package/dist/features/rating/ratingMeta.d.ts.map +1 -0
  80. package/dist/features/rating/ratingMeta.js +43 -0
  81. package/dist/features/rating/ratingMeta.js.map +1 -0
  82. package/dist/features/rating/utils/resolveRatingSegments.d.ts +9 -0
  83. package/dist/features/rating/utils/resolveRatingSegments.d.ts.map +1 -0
  84. package/dist/features/rating/utils/resolveRatingSegments.js +14 -0
  85. package/dist/features/rating/utils/resolveRatingSegments.js.map +1 -0
  86. package/dist/features/surface/surfaceMeta.d.ts +1 -1
  87. package/dist/features/tabs/adapters/inbound/Tab.d.ts +5 -0
  88. package/dist/features/tabs/adapters/inbound/Tab.d.ts.map +1 -0
  89. package/dist/features/tabs/adapters/inbound/Tab.js +14 -0
  90. package/dist/features/tabs/adapters/inbound/Tab.js.map +1 -0
  91. package/dist/features/tabs/adapters/inbound/TabList.d.ts +4 -0
  92. package/dist/features/tabs/adapters/inbound/TabList.d.ts.map +1 -0
  93. package/dist/features/tabs/adapters/inbound/TabList.js +9 -0
  94. package/dist/features/tabs/adapters/inbound/TabList.js.map +1 -0
  95. package/dist/features/tabs/adapters/inbound/TabPanel.d.ts +4 -0
  96. package/dist/features/tabs/adapters/inbound/TabPanel.d.ts.map +1 -0
  97. package/dist/features/tabs/adapters/inbound/TabPanel.js +11 -0
  98. package/dist/features/tabs/adapters/inbound/TabPanel.js.map +1 -0
  99. package/dist/features/tabs/adapters/inbound/Tabs.d.ts +4 -0
  100. package/dist/features/tabs/adapters/inbound/Tabs.d.ts.map +1 -0
  101. package/dist/features/tabs/adapters/inbound/Tabs.js +12 -0
  102. package/dist/features/tabs/adapters/inbound/Tabs.js.map +1 -0
  103. package/dist/features/tabs/composition/TabsInteractionPolicyContext.d.ts +3 -0
  104. package/dist/features/tabs/composition/TabsInteractionPolicyContext.d.ts.map +1 -0
  105. package/dist/features/tabs/composition/TabsInteractionPolicyContext.js +3 -0
  106. package/dist/features/tabs/composition/TabsInteractionPolicyContext.js.map +1 -0
  107. package/dist/features/tabs/public.d.ts +6 -0
  108. package/dist/features/tabs/public.d.ts.map +1 -0
  109. package/dist/features/tabs/public.js +5 -0
  110. package/dist/features/tabs/public.js.map +1 -0
  111. package/dist/features/tabs/tabListMeta.d.ts +9 -0
  112. package/dist/features/tabs/tabListMeta.d.ts.map +1 -0
  113. package/dist/features/tabs/tabListMeta.js +9 -0
  114. package/dist/features/tabs/tabListMeta.js.map +1 -0
  115. package/dist/features/tabs/tabMeta.d.ts +32 -0
  116. package/dist/features/tabs/tabMeta.d.ts.map +1 -0
  117. package/dist/features/tabs/tabMeta.js +14 -0
  118. package/dist/features/tabs/tabMeta.js.map +1 -0
  119. package/dist/features/tabs/tabPanelMeta.d.ts +15 -0
  120. package/dist/features/tabs/tabPanelMeta.d.ts.map +1 -0
  121. package/dist/features/tabs/tabPanelMeta.js +12 -0
  122. package/dist/features/tabs/tabPanelMeta.js.map +1 -0
  123. package/dist/features/tabs/tabsMeta.d.ts +58 -0
  124. package/dist/features/tabs/tabsMeta.d.ts.map +1 -0
  125. package/dist/features/tabs/tabsMeta.js +40 -0
  126. package/dist/features/tabs/tabsMeta.js.map +1 -0
  127. package/dist/features/toolbar/adapters/inbound/Toolbar.d.ts +4 -0
  128. package/dist/features/toolbar/adapters/inbound/Toolbar.d.ts.map +1 -0
  129. package/dist/features/toolbar/adapters/inbound/Toolbar.js +14 -0
  130. package/dist/features/toolbar/adapters/inbound/Toolbar.js.map +1 -0
  131. package/dist/features/toolbar/public.d.ts +3 -0
  132. package/dist/features/toolbar/public.d.ts.map +1 -0
  133. package/dist/features/toolbar/public.js +2 -0
  134. package/dist/features/toolbar/public.js.map +1 -0
  135. package/dist/features/toolbar/toolbarMeta.d.ts +29 -0
  136. package/dist/features/toolbar/toolbarMeta.d.ts.map +1 -0
  137. package/dist/features/toolbar/toolbarMeta.js +22 -0
  138. package/dist/features/toolbar/toolbarMeta.js.map +1 -0
  139. package/dist/features/typography/utils/resolveHeadingThemeRecipe.d.ts +1 -1
  140. package/dist/features/typography/utils/resolveTextThemeRecipe.d.ts +1 -1
  141. package/dist/features/uploader/adapters/inbound/Uploader.d.ts.map +1 -1
  142. package/dist/features/uploader/adapters/inbound/Uploader.js +3 -3
  143. package/dist/features/uploader/adapters/inbound/Uploader.js.map +1 -1
  144. package/dist/index.d.ts +6 -12
  145. package/dist/index.d.ts.map +1 -1
  146. package/dist/index.js +6 -6
  147. package/dist/index.js.map +1 -1
  148. package/dist/layout/screen/meta.d.ts +1 -1
  149. package/dist/layout/screen-section/meta.d.ts +1 -1
  150. package/dist/metadata/allowedChildren.d.ts +3 -3
  151. package/dist/metadata/allowedChildren.d.ts.map +1 -1
  152. package/dist/metadata/allowedChildren.js +6 -0
  153. package/dist/metadata/allowedChildren.js.map +1 -1
  154. package/dist/metadata/bindableComponentMeta.d.ts +2 -2
  155. package/dist/metadata/componentMeta.d.ts.map +1 -1
  156. package/dist/metadata/componentMeta.js +14 -9
  157. package/dist/metadata/componentMeta.js.map +1 -1
  158. package/dist/patterns/confirm-dialog/ConfirmDialog.js +3 -3
  159. package/dist/patterns/confirm-dialog/ConfirmDialog.js.map +1 -1
  160. package/dist/patterns/message-bubble/meta.d.ts +1 -1
  161. package/dist/patterns/notice/meta.d.ts +1 -1
  162. package/dist/patterns/panel/meta.d.ts +1 -1
  163. package/dist/patterns/reader/meta.d.ts +2 -2
  164. package/dist/patterns/scanner/meta.d.ts +2 -2
  165. package/dist/patterns/theme-composer/ThemeComposer.d.ts.map +1 -1
  166. package/dist/patterns/theme-composer/ThemeComposer.js +3 -3
  167. package/dist/patterns/theme-composer/ThemeComposer.js.map +1 -1
  168. package/dist/registry.d.ts.map +1 -1
  169. package/dist/registry.js +11 -9
  170. package/dist/registry.js.map +1 -1
  171. package/dist/types/dialog.d.ts +14 -0
  172. package/dist/types/dialog.d.ts.map +1 -0
  173. package/dist/types/dialog.js +2 -0
  174. package/dist/types/dialog.js.map +1 -0
  175. package/dist/types/pagination.d.ts +16 -0
  176. package/dist/types/pagination.d.ts.map +1 -0
  177. package/dist/types/pagination.js +2 -0
  178. package/dist/types/pagination.js.map +1 -0
  179. package/dist/types/rating.d.ts +9 -0
  180. package/dist/types/rating.d.ts.map +1 -0
  181. package/dist/types/rating.js +2 -0
  182. package/dist/types/rating.js.map +1 -0
  183. package/dist/types/search-input.d.ts +14 -0
  184. package/dist/types/search-input.d.ts.map +1 -0
  185. package/dist/types/search-input.js +2 -0
  186. package/dist/types/search-input.js.map +1 -0
  187. package/dist/types/tabs.d.ts +21 -0
  188. package/dist/types/tabs.d.ts.map +1 -0
  189. package/dist/types/tabs.js +2 -0
  190. package/dist/types/tabs.js.map +1 -0
  191. package/dist/types/toolbar.d.ts +8 -0
  192. package/dist/types/toolbar.d.ts.map +1 -0
  193. package/dist/types/toolbar.js +2 -0
  194. package/dist/types/toolbar.js.map +1 -0
  195. package/package.json +1 -1
  196. package/src/audit.test.ts +8 -47
  197. package/src/constants.ts +5 -0
  198. package/src/featureManifest.test.ts +31 -2
  199. package/src/features/dialog/adapters/inbound/Dialog.tsx +70 -0
  200. package/src/features/dialog/dialogMeta.ts +60 -0
  201. package/src/features/dialog/public.ts +2 -0
  202. package/src/features/form/formFieldMeta.ts +8 -1
  203. package/src/{components/search-bar/SearchBar.tsx → features/form/search-input/adapters/inbound/SearchInput.tsx} +10 -15
  204. package/src/features/form/search-input/public.ts +2 -0
  205. package/src/features/form/search-input/searchInputMeta.ts +68 -0
  206. package/src/features/pagination/adapters/inbound/Pagination.tsx +116 -0
  207. package/src/features/pagination/paginationMeta.ts +54 -0
  208. package/src/features/pagination/public.ts +2 -0
  209. package/src/features/pagination/utils/resolvePaginationPage.ts +6 -0
  210. package/src/features/pagination/utils/resolvePaginationState.test.ts +29 -0
  211. package/src/features/pagination/utils/resolvePaginationState.ts +70 -0
  212. package/src/features/rating/adapters/inbound/Rating.tsx +70 -0
  213. package/src/features/rating/public.ts +2 -0
  214. package/src/features/rating/ratingMeta.ts +44 -0
  215. package/src/features/rating/utils/resolveRatingSegments.test.ts +20 -0
  216. package/src/features/rating/utils/resolveRatingSegments.ts +19 -0
  217. package/src/features/tabs/adapters/inbound/Tab.tsx +26 -0
  218. package/src/features/tabs/adapters/inbound/TabList.tsx +18 -0
  219. package/src/features/tabs/adapters/inbound/TabPanel.tsx +23 -0
  220. package/src/features/tabs/adapters/inbound/Tabs.tsx +23 -0
  221. package/src/features/tabs/composition/TabsInteractionPolicyContext.ts +4 -0
  222. package/src/features/tabs/public.ts +5 -0
  223. package/src/features/tabs/tabListMeta.ts +10 -0
  224. package/src/features/tabs/tabMeta.ts +15 -0
  225. package/src/features/tabs/tabPanelMeta.ts +13 -0
  226. package/src/features/tabs/tabsMeta.ts +41 -0
  227. package/src/features/toolbar/adapters/inbound/Toolbar.tsx +31 -0
  228. package/src/features/toolbar/public.ts +2 -0
  229. package/src/features/toolbar/toolbarMeta.ts +24 -0
  230. package/src/{components → features/typography}/contentFallback.test.ts +2 -8
  231. package/src/features/uploader/adapters/inbound/Uploader.tsx +3 -3
  232. package/src/index.ts +15 -12
  233. package/src/metadata/allowedChildren.ts +6 -0
  234. package/src/metadata/componentMeta.test.ts +18 -1
  235. package/src/metadata/componentMeta.ts +14 -9
  236. package/src/patterns/confirm-dialog/ConfirmDialog.tsx +3 -3
  237. package/src/patterns/theme-composer/ThemeComposer.tsx +6 -7
  238. package/src/registry.ts +11 -9
  239. package/src/showcaseCoverage.test.ts +6 -3
  240. package/src/theme/themeScopeStructure.test.ts +16 -11
  241. package/src/types/dialog.ts +15 -0
  242. package/src/{components/pagination/types.ts → types/pagination.ts} +5 -8
  243. package/src/types/rating.ts +9 -0
  244. package/src/types/search-input.ts +14 -0
  245. package/src/types/tabs.ts +25 -0
  246. package/src/types/toolbar.ts +9 -0
  247. package/dist/components/modal/Modal.d.ts +0 -7
  248. package/dist/components/modal/Modal.d.ts.map +0 -1
  249. package/dist/components/modal/Modal.js +0 -39
  250. package/dist/components/modal/Modal.js.map +0 -1
  251. package/dist/components/modal/index.d.ts +0 -3
  252. package/dist/components/modal/index.d.ts.map +0 -1
  253. package/dist/components/modal/index.js +0 -2
  254. package/dist/components/modal/index.js.map +0 -1
  255. package/dist/components/modal/meta.d.ts +0 -9
  256. package/dist/components/modal/meta.d.ts.map +0 -1
  257. package/dist/components/modal/meta.js +0 -9
  258. package/dist/components/modal/meta.js.map +0 -1
  259. package/dist/components/modal/types.d.ts +0 -12
  260. package/dist/components/modal/types.d.ts.map +0 -1
  261. package/dist/components/modal/types.js +0 -2
  262. package/dist/components/modal/types.js.map +0 -1
  263. package/dist/components/pagination/Pagination.d.ts +0 -7
  264. package/dist/components/pagination/Pagination.d.ts.map +0 -1
  265. package/dist/components/pagination/Pagination.js +0 -96
  266. package/dist/components/pagination/Pagination.js.map +0 -1
  267. package/dist/components/pagination/index.d.ts +0 -3
  268. package/dist/components/pagination/index.d.ts.map +0 -1
  269. package/dist/components/pagination/index.js +0 -2
  270. package/dist/components/pagination/index.js.map +0 -1
  271. package/dist/components/pagination/meta.d.ts +0 -9
  272. package/dist/components/pagination/meta.d.ts.map +0 -1
  273. package/dist/components/pagination/meta.js +0 -9
  274. package/dist/components/pagination/meta.js.map +0 -1
  275. package/dist/components/pagination/types.d.ts +0 -18
  276. package/dist/components/pagination/types.d.ts.map +0 -1
  277. package/dist/components/pagination/types.js +0 -2
  278. package/dist/components/pagination/types.js.map +0 -1
  279. package/dist/components/rating/Rating.d.ts +0 -7
  280. package/dist/components/rating/Rating.d.ts.map +0 -1
  281. package/dist/components/rating/Rating.js +0 -26
  282. package/dist/components/rating/Rating.js.map +0 -1
  283. package/dist/components/rating/index.d.ts +0 -3
  284. package/dist/components/rating/index.d.ts.map +0 -1
  285. package/dist/components/rating/index.js +0 -2
  286. package/dist/components/rating/index.js.map +0 -1
  287. package/dist/components/rating/meta.d.ts +0 -9
  288. package/dist/components/rating/meta.d.ts.map +0 -1
  289. package/dist/components/rating/meta.js +0 -9
  290. package/dist/components/rating/meta.js.map +0 -1
  291. package/dist/components/rating/resolveRatingSegments.d.ts +0 -7
  292. package/dist/components/rating/resolveRatingSegments.d.ts.map +0 -1
  293. package/dist/components/rating/resolveRatingSegments.js +0 -22
  294. package/dist/components/rating/resolveRatingSegments.js.map +0 -1
  295. package/dist/components/rating/types.d.ts +0 -11
  296. package/dist/components/rating/types.d.ts.map +0 -1
  297. package/dist/components/rating/types.js +0 -26
  298. package/dist/components/rating/types.js.map +0 -1
  299. package/dist/components/search-bar/SearchBar.d.ts +0 -7
  300. package/dist/components/search-bar/SearchBar.d.ts.map +0 -1
  301. package/dist/components/search-bar/SearchBar.js.map +0 -1
  302. package/dist/components/search-bar/index.d.ts +0 -3
  303. package/dist/components/search-bar/index.d.ts.map +0 -1
  304. package/dist/components/search-bar/index.js +0 -2
  305. package/dist/components/search-bar/index.js.map +0 -1
  306. package/dist/components/search-bar/meta.d.ts +0 -9
  307. package/dist/components/search-bar/meta.d.ts.map +0 -1
  308. package/dist/components/search-bar/meta.js +0 -9
  309. package/dist/components/search-bar/meta.js.map +0 -1
  310. package/dist/components/search-bar/types.d.ts +0 -14
  311. package/dist/components/search-bar/types.d.ts.map +0 -1
  312. package/dist/components/search-bar/types.js +0 -2
  313. package/dist/components/search-bar/types.js.map +0 -1
  314. package/dist/components/tabs/Tabs.d.ts +0 -9
  315. package/dist/components/tabs/Tabs.d.ts.map +0 -1
  316. package/dist/components/tabs/Tabs.js +0 -59
  317. package/dist/components/tabs/Tabs.js.map +0 -1
  318. package/dist/components/tabs/index.d.ts +0 -3
  319. package/dist/components/tabs/index.d.ts.map +0 -1
  320. package/dist/components/tabs/index.js +0 -3
  321. package/dist/components/tabs/index.js.map +0 -1
  322. package/dist/components/tabs/meta.d.ts +0 -9
  323. package/dist/components/tabs/meta.d.ts.map +0 -1
  324. package/dist/components/tabs/meta.js +0 -9
  325. package/dist/components/tabs/meta.js.map +0 -1
  326. package/dist/components/tabs/types.d.ts +0 -22
  327. package/dist/components/tabs/types.d.ts.map +0 -1
  328. package/dist/components/tabs/types.js +0 -2
  329. package/dist/components/tabs/types.js.map +0 -1
  330. package/dist/components/toolbar/Toolbar.d.ts +0 -9
  331. package/dist/components/toolbar/Toolbar.d.ts.map +0 -1
  332. package/dist/components/toolbar/Toolbar.js +0 -26
  333. package/dist/components/toolbar/Toolbar.js.map +0 -1
  334. package/dist/components/toolbar/ToolbarAction.d.ts +0 -9
  335. package/dist/components/toolbar/ToolbarAction.d.ts.map +0 -1
  336. package/dist/components/toolbar/ToolbarAction.js +0 -13
  337. package/dist/components/toolbar/ToolbarAction.js.map +0 -1
  338. package/dist/components/toolbar/index.d.ts +0 -4
  339. package/dist/components/toolbar/index.d.ts.map +0 -1
  340. package/dist/components/toolbar/index.js +0 -4
  341. package/dist/components/toolbar/index.js.map +0 -1
  342. package/dist/components/toolbar/meta.d.ts +0 -17
  343. package/dist/components/toolbar/meta.d.ts.map +0 -1
  344. package/dist/components/toolbar/meta.js +0 -17
  345. package/dist/components/toolbar/meta.js.map +0 -1
  346. package/dist/components/toolbar/types.d.ts +0 -18
  347. package/dist/components/toolbar/types.d.ts.map +0 -1
  348. package/dist/components/toolbar/types.js +0 -2
  349. package/dist/components/toolbar/types.js.map +0 -1
  350. package/src/components/modal/Modal.tsx +0 -63
  351. package/src/components/modal/index.ts +0 -2
  352. package/src/components/modal/meta.ts +0 -10
  353. package/src/components/modal/types.ts +0 -16
  354. package/src/components/pagination/Pagination.tsx +0 -199
  355. package/src/components/pagination/index.ts +0 -2
  356. package/src/components/pagination/meta.ts +0 -10
  357. package/src/components/rating/Rating.tsx +0 -42
  358. package/src/components/rating/index.ts +0 -2
  359. package/src/components/rating/meta.ts +0 -10
  360. package/src/components/rating/resolveRatingSegments.test.ts +0 -60
  361. package/src/components/rating/resolveRatingSegments.ts +0 -34
  362. package/src/components/rating/types.ts +0 -37
  363. package/src/components/search-bar/index.ts +0 -2
  364. package/src/components/search-bar/meta.ts +0 -10
  365. package/src/components/search-bar/types.ts +0 -14
  366. package/src/components/tabs/Tabs.tsx +0 -129
  367. package/src/components/tabs/index.ts +0 -2
  368. package/src/components/tabs/meta.ts +0 -10
  369. package/src/components/tabs/types.ts +0 -25
  370. package/src/components/toolbar/Toolbar.tsx +0 -48
  371. package/src/components/toolbar/ToolbarAction.tsx +0 -28
  372. package/src/components/toolbar/index.ts +0 -3
  373. package/src/components/toolbar/meta.ts +0 -19
  374. package/src/components/toolbar/types.ts +0 -21
@@ -12,13 +12,19 @@ test('every selected feature element is directly authorable through its canonica
12
12
  const source = await Bun.file(`src/features/${family}/public.ts`).text();
13
13
  for (const name of names) {
14
14
  const meta = catalog.get(name);
15
+ const hasAuthorableShape =
16
+ Object.keys(meta?.props ?? {}).length > 0 || (meta?.allowedChildren.length ?? 0) > 0;
15
17
  expect(meta?.directManifestNode, name).toBe(true);
16
- expect(Object.keys(meta?.props ?? {}).length, name).toBeGreaterThan(0);
18
+ expect(hasAuthorableShape, name).toBe(true);
17
19
  expect(source, name).toContain(name);
18
20
  }
19
21
  }
20
22
  });
21
23
 
24
+ test('feature ownership has no remaining legacy components directory', () => {
25
+ expect(existsSync('src/components')).toBe(false);
26
+ });
27
+
22
28
  test('form composition has one canonical feature owner', () => {
23
29
  expect(existsSync('src/components/form')).toBe(false);
24
30
  expect(existsSync('src/patterns/form-field')).toBe(false);
@@ -38,7 +44,7 @@ test('migrated picker and presentation elements have one canonical feature owner
38
44
  }
39
45
  });
40
46
 
41
- test('interactive authoring retains state and event payload bindings after plugin composition', () => {
47
+ test('existing interactive authoring retains bindings after plugin composition', () => {
42
48
  const meta = ZORA_CORE_PLUGIN_METADATA.componentMeta;
43
49
  expect(meta.DataTable?.bindings?.props?.sort?.value.type).toBe('object');
44
50
  expect(meta.DataTable?.bindings?.props?.rows?.value.type).toBe('array');
@@ -48,6 +54,29 @@ test('interactive authoring retains state and event payload bindings after plugi
48
54
  type: 'object',
49
55
  });
50
56
  expect(meta.BottomSheet?.bindings?.props?.open?.value.type).toBe('boolean');
57
+ });
58
+
59
+ test('final ownership data components retain bindings after plugin composition', () => {
60
+ const meta = ZORA_CORE_PLUGIN_METADATA.componentMeta;
61
+ expect(meta.Dialog?.bindings?.props?.visible?.value.type).toBe('boolean');
62
+ expect(meta.Dialog?.bindings?.events?.dismiss?.payload?.eventType).toBe('dialog.dismiss');
63
+ expect(meta.Pagination?.bindings?.props?.page?.value.type).toBe('number');
64
+ expect(meta.Pagination?.bindings?.events?.pageChange?.payload?.eventType).toBe(
65
+ 'pagination.pageChange',
66
+ );
67
+ expect(meta.Rating?.bindings?.props?.value?.value.type).toBe('number');
68
+ });
69
+
70
+ test('final ownership form and tab components retain bindings after plugin composition', () => {
71
+ const meta = ZORA_CORE_PLUGIN_METADATA.componentMeta;
72
+ expect(meta.SearchInput?.bindings?.props?.value?.value.type).toBe('string');
73
+ expect(meta.SearchInput?.bindings?.events?.submit?.payload?.eventType).toBe('searchInput.submit');
74
+ expect(meta.Tabs?.bindings?.props?.value?.value.type).toBe('string');
75
+ expect(meta.Tabs?.bindings?.events?.valueChange?.payload?.eventType).toBe('tabs.valueChange');
76
+ });
77
+
78
+ test('existing scalar authoring bindings remain available after plugin composition', () => {
79
+ const meta = ZORA_CORE_PLUGIN_METADATA.componentMeta;
51
80
  expect(meta.Heading?.bindings?.props?.level?.value.type).toBe('number');
52
81
  expect(meta.Image?.bindings?.props?.radius?.value.type).toBe('unknown');
53
82
  });
@@ -0,0 +1,70 @@
1
+ import { Modal as SurfaceModal } from '@ankhorage/surface';
2
+ import React from 'react';
3
+ import { StyleSheet } from 'react-native';
4
+
5
+ import { resolveDialogWidth } from '../../../../internal/recipes';
6
+ import { withZoraThemeScope } from '../../../../theme/withZoraThemeScope';
7
+ import type { DialogProps } from '../../../../types/dialog';
8
+ import { Box, Stack } from '../../../layout/public';
9
+ import { Heading, Text } from '../../../typography/public';
10
+
11
+ /*** Renders the product-level dialog composition on top of the Surface modal primitive. */
12
+ export const Dialog = withZoraThemeScope(DialogInner);
13
+
14
+ /*** Connects dialog chrome and slots to the generic modal overlay. */
15
+ function DialogInner({
16
+ themeId: _themeId,
17
+ mode: _mode,
18
+ children,
19
+ title,
20
+ description,
21
+ footer,
22
+ width = 'default',
23
+ onDismiss,
24
+ interactionPolicy,
25
+ ...props
26
+ }: DialogProps) {
27
+ const hasHeader = title !== undefined || description !== undefined;
28
+ const stableOnDismiss = useStableCallback(onDismiss);
29
+
30
+ return (
31
+ <SurfaceModal {...props} onDismiss={stableOnDismiss} interactionPolicy={interactionPolicy}>
32
+ <Box maxWidth={resolveDialogWidth(width)} style={styles.content}>
33
+ <Stack gap="m">
34
+ {hasHeader ? (
35
+ <Stack gap="xs">
36
+ {title !== undefined ? <Heading level={3}>{title}</Heading> : null}
37
+ {description !== undefined ? (
38
+ <Text emphasis="muted" variant="bodySmall">
39
+ {description}
40
+ </Text>
41
+ ) : null}
42
+ </Stack>
43
+ ) : null}
44
+ {children ? <Box>{children}</Box> : null}
45
+ {footer ? <Box pt="xs">{footer}</Box> : null}
46
+ </Stack>
47
+ </Box>
48
+ </SurfaceModal>
49
+ );
50
+ }
51
+
52
+ /*** Keeps the dismiss callback identity stable while always invoking the latest handler. */
53
+ function useStableCallback(callback: (() => void) | undefined): (() => void) | undefined {
54
+ const callbackRef = React.useRef(callback);
55
+
56
+ React.useEffect(() => {
57
+ callbackRef.current = callback;
58
+ }, [callback]);
59
+
60
+ return React.useCallback(() => {
61
+ callbackRef.current?.();
62
+ }, []);
63
+ }
64
+
65
+ const styles = StyleSheet.create({
66
+ content: {
67
+ alignSelf: 'center',
68
+ width: '100%',
69
+ },
70
+ });
@@ -0,0 +1,60 @@
1
+ import { CONTAINER_ALLOWED_CHILDREN } from '../../metadata/allowedChildren';
2
+ import type { ZoraComponentMeta } from '../../metadata/types';
3
+
4
+ export const dialogMeta = {
5
+ name: 'Dialog',
6
+ category: 'component',
7
+ directManifestNode: true,
8
+ allowedChildren: [...CONTAINER_ALLOWED_CHILDREN],
9
+ description: 'Modal dialog composition with title, description, content, and optional footer.',
10
+ blueprint: {
11
+ label: 'Dialog',
12
+ defaultProps: { closeOnBackdrop: true, visible: false, width: 'default' },
13
+ },
14
+ bindings: {
15
+ props: {
16
+ visible: {
17
+ label: 'Visible',
18
+ description: 'Whether the dialog is currently visible.',
19
+ value: { type: 'boolean' },
20
+ acceptsFallback: true,
21
+ acceptsTransforms: true,
22
+ },
23
+ },
24
+ events: {
25
+ dismiss: {
26
+ label: 'Dismiss',
27
+ description: 'Runs when the dialog requests dismissal.',
28
+ payload: { eventType: 'dialog.dismiss', fields: [] },
29
+ },
30
+ },
31
+ },
32
+ events: {
33
+ dismiss: { label: 'Dismiss', eventType: 'dialog.dismiss', payloadFields: [] },
34
+ },
35
+ slots: {
36
+ children: { label: 'Content', allowedChildren: [...CONTAINER_ALLOWED_CHILDREN] },
37
+ footer: {
38
+ label: 'Footer',
39
+ allowedChildren: ['Button', 'ButtonGroup', 'Stack', 'Toolbar'],
40
+ },
41
+ },
42
+ props: {
43
+ visible: { type: 'boolean', category: 'State', label: 'Visible', default: false },
44
+ title: { type: 'string', category: 'Content', label: 'Title' },
45
+ description: { type: 'string', category: 'Content', label: 'Description' },
46
+ closeOnBackdrop: {
47
+ type: 'boolean',
48
+ category: 'Behavior',
49
+ label: 'Close on backdrop',
50
+ default: true,
51
+ },
52
+ width: {
53
+ type: 'enum',
54
+ category: 'Layout',
55
+ label: 'Width',
56
+ enum: ['narrow', 'default', 'wide'],
57
+ default: 'default',
58
+ },
59
+ },
60
+ } as const satisfies ZoraComponentMeta;
@@ -0,0 +1,2 @@
1
+ export type { DialogProps } from '../../types/dialog';
2
+ export { Dialog } from './adapters/inbound/Dialog';
@@ -3,7 +3,14 @@ export const formFieldMeta = {
3
3
  name: 'FormField',
4
4
  category: 'component',
5
5
  directManifestNode: true,
6
- allowedChildren: ['Checkbox', 'CheckboxGroup', 'RadioGroup', 'Select', 'TextInput'],
6
+ allowedChildren: [
7
+ 'Checkbox',
8
+ 'CheckboxGroup',
9
+ 'RadioGroup',
10
+ 'SearchInput',
11
+ 'Select',
12
+ 'TextInput',
13
+ ],
7
14
  blueprint: { label: 'Form field', defaultProps: { label: 'Label' } },
8
15
  bindings: {
9
16
  props: {
@@ -1,14 +1,16 @@
1
- import React from 'react';
1
+ import { withZoraThemeScope } from '../../../../../theme/withZoraThemeScope';
2
+ import type { SearchInputProps } from '../../../../../types/search-input';
3
+ import { TextInput, type TextInputTrailingAction } from '../../../text-input/public';
2
4
 
3
- import { TextInput, type TextInputTrailingAction } from '../../features/form/text-input/public';
4
- import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
5
- import type { SearchBarProps } from './types';
5
+ /*** Renders a search-focused text input with clear and submit behavior. */
6
+ export const SearchInput = withZoraThemeScope(SearchInputInner);
6
7
 
7
- function SearchBarInner({
8
+ /*** Connects search semantics to the shared ZORA TextInput control. */
9
+ function SearchInputInner({
8
10
  themeId: _themeId,
9
11
  mode: _mode,
10
12
  testID,
11
- value,
13
+ value = '',
12
14
  onValueChange,
13
15
  placeholder = 'Search',
14
16
  onSubmit,
@@ -18,9 +20,8 @@ function SearchBarInner({
18
20
  disabled,
19
21
  readOnly,
20
22
  interactionPolicy,
21
- }: SearchBarProps) {
23
+ }: SearchInputProps) {
22
24
  const passive = interactionPolicy === 'passive';
23
-
24
25
  const trailingAction: TextInputTrailingAction | undefined =
25
26
  clearable && value.length > 0
26
27
  ? {
@@ -28,8 +29,7 @@ function SearchBarInner({
28
29
  label: 'Clear search',
29
30
  onPress: () => {
30
31
  if (passive) return;
31
-
32
- onValueChange('');
32
+ onValueChange?.('');
33
33
  onClear?.();
34
34
  },
35
35
  }
@@ -52,8 +52,3 @@ function SearchBarInner({
52
52
  />
53
53
  );
54
54
  }
55
-
56
- /***
57
- * Search input with leading icon and optional trailing action.
58
- */
59
- export const SearchBar = withZoraThemeScope(SearchBarInner);
@@ -0,0 +1,2 @@
1
+ export type { SearchInputProps } from '../../../types/search-input';
2
+ export { SearchInput } from './adapters/inbound/SearchInput';
@@ -0,0 +1,68 @@
1
+ import type { ZoraComponentMeta } from '../../../metadata/types';
2
+
3
+ export const searchInputMeta = {
4
+ name: 'SearchInput',
5
+ category: 'component',
6
+ directManifestNode: true,
7
+ allowedChildren: [],
8
+ description: 'Search-focused text input with clear and submit events.',
9
+ blueprint: {
10
+ label: 'Search input',
11
+ defaultProps: { clearable: true, placeholder: 'Search', size: 'l', value: '' },
12
+ },
13
+ bindings: {
14
+ props: {
15
+ value: {
16
+ label: 'Value',
17
+ description: 'Current search query.',
18
+ value: { type: 'string' },
19
+ acceptsFallback: true,
20
+ acceptsTransforms: true,
21
+ },
22
+ },
23
+ events: {
24
+ valueChange: {
25
+ label: 'Value change',
26
+ description: 'Runs whenever the search query changes.',
27
+ payload: {
28
+ eventType: 'searchInput.valueChange',
29
+ fields: [{ path: 'value', type: 'string', label: 'Value' }],
30
+ },
31
+ },
32
+ submit: {
33
+ label: 'Submit',
34
+ description: 'Runs when the user submits the search query.',
35
+ payload: {
36
+ eventType: 'searchInput.submit',
37
+ fields: [{ path: 'value', type: 'string', label: 'Value' }],
38
+ },
39
+ },
40
+ clear: {
41
+ label: 'Clear',
42
+ description: 'Runs when the search query is cleared.',
43
+ payload: { eventType: 'searchInput.clear', fields: [] },
44
+ },
45
+ },
46
+ },
47
+ events: {
48
+ valueChange: {
49
+ label: 'Value change',
50
+ eventType: 'searchInput.valueChange',
51
+ payloadFields: [{ path: 'value', type: 'string', label: 'Value' }],
52
+ },
53
+ submit: {
54
+ label: 'Submit',
55
+ eventType: 'searchInput.submit',
56
+ payloadFields: [{ path: 'value', type: 'string', label: 'Value' }],
57
+ },
58
+ clear: { label: 'Clear', eventType: 'searchInput.clear', payloadFields: [] },
59
+ },
60
+ props: {
61
+ value: { type: 'string', category: 'Content', label: 'Value', default: '' },
62
+ placeholder: { type: 'string', category: 'Content', label: 'Placeholder', default: 'Search' },
63
+ clearable: { type: 'boolean', category: 'Behavior', label: 'Clearable', default: true },
64
+ size: { type: 'enum', category: 'Style', label: 'Size', enum: ['s', 'm', 'l'], default: 'l' },
65
+ disabled: { type: 'boolean', category: 'State', label: 'Disabled' },
66
+ readOnly: { type: 'boolean', category: 'State', label: 'Read only' },
67
+ },
68
+ } as const satisfies ZoraComponentMeta;
@@ -0,0 +1,116 @@
1
+ import React from 'react';
2
+
3
+ import { withZoraThemeScope } from '../../../../theme/withZoraThemeScope';
4
+ import type { PaginationProps } from '../../../../types/pagination';
5
+ import { Button } from '../../../button/public';
6
+ import { Stack } from '../../../layout/public';
7
+ import { Text } from '../../../typography/public';
8
+ import { resolvePaginationPage } from '../../utils/resolvePaginationPage';
9
+ import { resolvePaginationState } from '../../utils/resolvePaginationState';
10
+
11
+ /*** Renders controls for navigating between pages of a finite result set. */
12
+ export const Pagination = withZoraThemeScope(PaginationInner);
13
+
14
+ /*** Connects normalized pagination state to visible page navigation controls. */
15
+ function PaginationInner({
16
+ themeId: _themeId,
17
+ mode: _mode,
18
+ page,
19
+ pageCount,
20
+ onPageChange,
21
+ disabled = false,
22
+ siblingCount = 1,
23
+ boundaryCount = 1,
24
+ showFirstLast = false,
25
+ previousLabel = 'Previous',
26
+ nextLabel = 'Next',
27
+ firstLabel = 'First',
28
+ lastLabel = 'Last',
29
+ compact = false,
30
+ testID,
31
+ interactionPolicy,
32
+ }: PaginationProps) {
33
+ const passive = interactionPolicy === 'passive';
34
+ const state = resolvePaginationState({ boundaryCount, compact, page, pageCount, siblingCount });
35
+ const canGoPrevious = state.currentPage > 1;
36
+ const canGoNext = state.currentPage < state.pageCount;
37
+ const navigationDisabled = disabled || state.pageCount <= 1;
38
+
39
+ const changePage = React.useCallback(
40
+ (nextPage: number) => {
41
+ const clampedPage = resolvePaginationPage(nextPage, state.pageCount);
42
+ if (passive || disabled || clampedPage === state.currentPage) return;
43
+ onPageChange?.(clampedPage);
44
+ },
45
+ [disabled, onPageChange, passive, state.currentPage, state.pageCount],
46
+ );
47
+
48
+ return (
49
+ <Stack align="center" direction="row" gap="xs" testID={testID}>
50
+ {showFirstLast ? (
51
+ <Button
52
+ disabled={navigationDisabled || state.currentPage === 1}
53
+ interactionPolicy={interactionPolicy}
54
+ onPress={() => changePage(1)}
55
+ size="s"
56
+ testID={testID ? `${testID}-first` : undefined}
57
+ variant="ghost"
58
+ >
59
+ {firstLabel}
60
+ </Button>
61
+ ) : null}
62
+ <Button
63
+ disabled={navigationDisabled || !canGoPrevious}
64
+ interactionPolicy={interactionPolicy}
65
+ onPress={() => changePage(state.currentPage - 1)}
66
+ size="s"
67
+ testID={testID ? `${testID}-previous` : undefined}
68
+ variant="ghost"
69
+ >
70
+ {previousLabel}
71
+ </Button>
72
+ {state.items.map((item, index) =>
73
+ item === 'ellipsis' ? (
74
+ <Text key={`ellipsis-${index}`} emphasis="muted" variant="bodySmall">
75
+ …
76
+ </Text>
77
+ ) : (
78
+ <Button
79
+ color={item === state.currentPage ? 'primary' : 'neutral'}
80
+ disabled={disabled}
81
+ interactionPolicy={interactionPolicy}
82
+ key={item}
83
+ onPress={() => changePage(item)}
84
+ size="s"
85
+ testID={testID ? `${testID}-page-${item}` : undefined}
86
+ variant={item === state.currentPage ? 'solid' : 'ghost'}
87
+ >
88
+ {item}
89
+ </Button>
90
+ ),
91
+ )}
92
+ <Button
93
+ disabled={navigationDisabled || !canGoNext}
94
+ interactionPolicy={interactionPolicy}
95
+ onPress={() => changePage(state.currentPage + 1)}
96
+ size="s"
97
+ testID={testID ? `${testID}-next` : undefined}
98
+ variant="ghost"
99
+ >
100
+ {nextLabel}
101
+ </Button>
102
+ {showFirstLast ? (
103
+ <Button
104
+ disabled={navigationDisabled || state.currentPage === state.pageCount}
105
+ interactionPolicy={interactionPolicy}
106
+ onPress={() => changePage(state.pageCount)}
107
+ size="s"
108
+ testID={testID ? `${testID}-last` : undefined}
109
+ variant="ghost"
110
+ >
111
+ {lastLabel}
112
+ </Button>
113
+ ) : null}
114
+ </Stack>
115
+ );
116
+ }
@@ -0,0 +1,54 @@
1
+ import type { ZoraComponentMeta } from '../../metadata/types';
2
+
3
+ export const paginationMeta = {
4
+ name: 'Pagination',
5
+ category: 'component',
6
+ directManifestNode: true,
7
+ allowedChildren: [],
8
+ description: 'Navigates between pages of a finite result set without changing app routes.',
9
+ blueprint: {
10
+ label: 'Pagination',
11
+ defaultProps: { boundaryCount: 1, compact: false, page: 1, pageCount: 10, siblingCount: 1 },
12
+ },
13
+ bindings: {
14
+ props: {
15
+ page: {
16
+ label: 'Page',
17
+ description: 'Current one-based page.',
18
+ value: { type: 'number' },
19
+ acceptsFallback: true,
20
+ acceptsTransforms: true,
21
+ },
22
+ },
23
+ events: {
24
+ pageChange: {
25
+ label: 'Page change',
26
+ description: 'Runs when a new page is requested.',
27
+ payload: {
28
+ eventType: 'pagination.pageChange',
29
+ fields: [{ path: 'page', type: 'number', label: 'Page' }],
30
+ },
31
+ },
32
+ },
33
+ },
34
+ events: {
35
+ pageChange: {
36
+ label: 'Page change',
37
+ eventType: 'pagination.pageChange',
38
+ payloadFields: [{ path: 'page', type: 'number', label: 'Page' }],
39
+ },
40
+ },
41
+ props: {
42
+ page: { type: 'number', category: 'State', label: 'Page', default: 1 },
43
+ pageCount: { type: 'number', category: 'Data', label: 'Page count', default: 10 },
44
+ siblingCount: { type: 'number', category: 'Layout', label: 'Sibling count', default: 1 },
45
+ boundaryCount: { type: 'number', category: 'Layout', label: 'Boundary count', default: 1 },
46
+ showFirstLast: { type: 'boolean', category: 'Behavior', label: 'Show first/last' },
47
+ compact: { type: 'boolean', category: 'Layout', label: 'Compact', default: false },
48
+ disabled: { type: 'boolean', category: 'State', label: 'Disabled' },
49
+ previousLabel: { type: 'string', category: 'Content', label: 'Previous label' },
50
+ nextLabel: { type: 'string', category: 'Content', label: 'Next label' },
51
+ firstLabel: { type: 'string', category: 'Content', label: 'First label' },
52
+ lastLabel: { type: 'string', category: 'Content', label: 'Last label' },
53
+ },
54
+ } as const satisfies ZoraComponentMeta;
@@ -0,0 +1,2 @@
1
+ export type { PaginationProps } from '../../types/pagination';
2
+ export { Pagination } from './adapters/inbound/Pagination';
@@ -0,0 +1,6 @@
1
+ /*** Clamps a requested pagination page to the valid one-based page range. */
2
+ export function resolvePaginationPage(value: number, pageCount: number): number {
3
+ if (!Number.isFinite(value)) return 1;
4
+
5
+ return Math.min(Math.max(Math.trunc(value), 1), Math.max(pageCount, 1));
6
+ }
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+
3
+ import { resolvePaginationState } from './resolvePaginationState';
4
+
5
+ describe('resolvePaginationState', () => {
6
+ it('inserts ellipses between boundaries and siblings', () => {
7
+ expect(
8
+ resolvePaginationState({
9
+ boundaryCount: 1,
10
+ compact: false,
11
+ page: 5,
12
+ pageCount: 10,
13
+ siblingCount: 1,
14
+ }).items,
15
+ ).toEqual([1, 'ellipsis', 4, 5, 6, 'ellipsis', 10]);
16
+ });
17
+
18
+ it('returns only the active page in compact mode', () => {
19
+ expect(
20
+ resolvePaginationState({
21
+ boundaryCount: 1,
22
+ compact: true,
23
+ page: 3,
24
+ pageCount: 8,
25
+ siblingCount: 1,
26
+ }).items,
27
+ ).toEqual([3]);
28
+ });
29
+ });
@@ -0,0 +1,70 @@
1
+ import { resolvePaginationPage } from './resolvePaginationPage';
2
+
3
+ /*** Normalizes pagination input and resolves visible page and ellipsis items. */
4
+ export function resolvePaginationState({
5
+ page,
6
+ pageCount,
7
+ siblingCount,
8
+ boundaryCount,
9
+ compact,
10
+ }: PaginationStateInput): PaginationState {
11
+ const normalizedPageCount = Math.max(0, Math.trunc(Number.isFinite(pageCount) ? pageCount : 0));
12
+ const currentPage = resolvePaginationPage(page, normalizedPageCount);
13
+ const safeSiblingCount = normalizeCount(siblingCount, 1);
14
+ const safeBoundaryCount = normalizeCount(boundaryCount, 1);
15
+
16
+ if (normalizedPageCount <= 0) {
17
+ return { currentPage, items: [], pageCount: normalizedPageCount };
18
+ }
19
+
20
+ if (compact) {
21
+ return { currentPage, items: [currentPage], pageCount: normalizedPageCount };
22
+ }
23
+
24
+ const boundaries = createRange(1, Math.min(safeBoundaryCount, normalizedPageCount));
25
+ const trailingBoundaries = createRange(
26
+ Math.max(normalizedPageCount - safeBoundaryCount + 1, 1),
27
+ normalizedPageCount,
28
+ );
29
+ const siblings = createRange(
30
+ Math.max(currentPage - safeSiblingCount, 1),
31
+ Math.min(currentPage + safeSiblingCount, normalizedPageCount),
32
+ );
33
+ const pages = [...new Set([...boundaries, ...siblings, ...trailingBoundaries])].sort(
34
+ (left, right) => left - right,
35
+ );
36
+ const items = pages.flatMap<PaginationItem>((nextPage, index) => {
37
+ const previousPage = index > 0 ? pages.at(index - 1) : undefined;
38
+ return previousPage !== undefined && nextPage - previousPage > 1
39
+ ? ['ellipsis', nextPage]
40
+ : [nextPage];
41
+ });
42
+
43
+ return { currentPage, items, pageCount: normalizedPageCount };
44
+ }
45
+
46
+ type PaginationItem = number | 'ellipsis';
47
+
48
+ interface PaginationStateInput {
49
+ page: number;
50
+ pageCount: number;
51
+ siblingCount: number | undefined;
52
+ boundaryCount: number | undefined;
53
+ compact: boolean;
54
+ }
55
+
56
+ interface PaginationState {
57
+ currentPage: number;
58
+ pageCount: number;
59
+ items: readonly PaginationItem[];
60
+ }
61
+
62
+ /*** Creates an inclusive numeric range for pagination boundaries and siblings. */
63
+ function createRange(start: number, end: number): number[] {
64
+ return end < start ? [] : Array.from({ length: end - start + 1 }, (_, index) => start + index);
65
+ }
66
+
67
+ /*** Normalizes optional pagination counts to finite non-negative integers. */
68
+ function normalizeCount(value: number | undefined, fallback: number): number {
69
+ return value === undefined || !Number.isFinite(value) ? fallback : Math.max(0, Math.trunc(value));
70
+ }