@pihanga2/shadcn 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 (399) hide show
  1. package/README.md +114 -0
  2. package/cards/badge/badge.component.d.ts +14 -0
  3. package/cards/badge/badge.component.js +18 -0
  4. package/cards/badge/badge.component.js.map +1 -0
  5. package/cards/badge/badge.types.d.ts +37 -0
  6. package/cards/badge/badge.types.js +7 -0
  7. package/cards/badge/badge.types.js.map +1 -0
  8. package/cards/badge/index.d.ts +1 -0
  9. package/cards/badge/index.js +12 -0
  10. package/cards/badge/index.js.map +1 -0
  11. package/cards/box/box.component.d.ts +4 -0
  12. package/cards/box/box.component.js +24 -0
  13. package/cards/box/box.component.js.map +1 -0
  14. package/cards/box/box.types.d.ts +71 -0
  15. package/cards/box/box.types.js +7 -0
  16. package/cards/box/box.types.js.map +1 -0
  17. package/cards/box/index.d.ts +1 -0
  18. package/cards/box/index.js +12 -0
  19. package/cards/box/index.js.map +1 -0
  20. package/cards/button/button.component.d.ts +4 -0
  21. package/cards/button/button.component.js +71 -0
  22. package/cards/button/button.component.js.map +1 -0
  23. package/cards/button/button.types.d.ts +106 -0
  24. package/cards/button/button.types.js +7 -0
  25. package/cards/button/button.types.js.map +1 -0
  26. package/cards/button/index.d.ts +1 -0
  27. package/cards/button/index.js +13 -0
  28. package/cards/button/index.js.map +1 -0
  29. package/cards/checkbox/checkbox.component.d.ts +4 -0
  30. package/cards/checkbox/checkbox.component.js +36 -0
  31. package/cards/checkbox/checkbox.component.js.map +1 -0
  32. package/cards/checkbox/checkbox.types.d.ts +37 -0
  33. package/cards/checkbox/checkbox.types.js +7 -0
  34. package/cards/checkbox/checkbox.types.js.map +1 -0
  35. package/cards/checkbox/index.d.ts +1 -0
  36. package/cards/checkbox/index.js +13 -0
  37. package/cards/checkbox/index.js.map +1 -0
  38. package/cards/conditional/conditional.component.d.ts +11 -0
  39. package/cards/conditional/conditional.component.js +15 -0
  40. package/cards/conditional/conditional.component.js.map +1 -0
  41. package/cards/conditional/conditional.types.d.ts +29 -0
  42. package/cards/conditional/conditional.types.js +7 -0
  43. package/cards/conditional/conditional.types.js.map +1 -0
  44. package/cards/conditional/index.d.ts +1 -0
  45. package/cards/conditional/index.js +12 -0
  46. package/cards/conditional/index.js.map +1 -0
  47. package/cards/core-index.d.ts +30 -0
  48. package/cards/core-index.js +61 -0
  49. package/cards/dataTable/dataTable.component.d.ts +4 -0
  50. package/cards/dataTable/dataTable.component.js +209 -0
  51. package/cards/dataTable/dataTable.component.js.map +1 -0
  52. package/cards/dataTable/dataTable.types.d.ts +196 -0
  53. package/cards/dataTable/dataTable.types.js +13 -0
  54. package/cards/dataTable/dataTable.types.js.map +1 -0
  55. package/cards/dataTable/dataTableRowDetail.component.d.ts +26 -0
  56. package/cards/dataTable/dataTableRowDetail.component.js +47 -0
  57. package/cards/dataTable/dataTableRowDetail.component.js.map +1 -0
  58. package/cards/dataTable/index.d.ts +1 -0
  59. package/cards/dataTable/index.js +16 -0
  60. package/cards/dataTable/index.js.map +1 -0
  61. package/cards/dialog/dialog.component.d.ts +4 -0
  62. package/cards/dialog/dialog.component.js +89 -0
  63. package/cards/dialog/dialog.component.js.map +1 -0
  64. package/cards/dialog/dialog.types.d.ts +115 -0
  65. package/cards/dialog/dialog.types.js +11 -0
  66. package/cards/dialog/dialog.types.js.map +1 -0
  67. package/cards/dialog/index.d.ts +1 -0
  68. package/cards/dialog/index.js +13 -0
  69. package/cards/dialog/index.js.map +1 -0
  70. package/cards/dropDownMenu/drop-down.component.d.ts +4 -0
  71. package/cards/dropDownMenu/drop-down.component.js +205 -0
  72. package/cards/dropDownMenu/drop-down.component.js.map +1 -0
  73. package/cards/dropDownMenu/drop-down.types.d.ts +131 -0
  74. package/cards/dropDownMenu/drop-down.types.js +7 -0
  75. package/cards/dropDownMenu/drop-down.types.js.map +1 -0
  76. package/cards/dropDownMenu/dropdown-context.d.ts +7 -0
  77. package/cards/dropDownMenu/dropdown-context.js +7 -0
  78. package/cards/dropDownMenu/dropdown-context.js.map +1 -0
  79. package/cards/dropDownMenu/dropdown-menu.ui.d.ts +42 -0
  80. package/cards/dropDownMenu/dropdown-menu.ui.js +111 -0
  81. package/cards/dropDownMenu/dropdown-menu.ui.js.map +1 -0
  82. package/cards/dropDownMenu/index.d.ts +1 -0
  83. package/cards/dropDownMenu/index.js +13 -0
  84. package/cards/dropDownMenu/index.js.map +1 -0
  85. package/cards/emptyCard.d.ts +7 -0
  86. package/cards/field/field.component.d.ts +4 -0
  87. package/cards/field/field.component.js +38 -0
  88. package/cards/field/field.component.js.map +1 -0
  89. package/cards/field/field.types.d.ts +30 -0
  90. package/cards/field/field.types.js +7 -0
  91. package/cards/field/field.types.js.map +1 -0
  92. package/cards/field/index.d.ts +1 -0
  93. package/cards/field/index.js +12 -0
  94. package/cards/field/index.js.map +1 -0
  95. package/cards/flexGrid/flexGrid.component.d.ts +4 -0
  96. package/cards/flexGrid/flexGrid.component.js +40 -0
  97. package/cards/flexGrid/flexGrid.component.js.map +1 -0
  98. package/cards/flexGrid/flexGrid.types.d.ts +23 -0
  99. package/cards/flexGrid/flexGrid.types.js +7 -0
  100. package/cards/flexGrid/flexGrid.types.js.map +1 -0
  101. package/cards/flexGrid/index.d.ts +1 -0
  102. package/cards/flexGrid/index.js +12 -0
  103. package/cards/flexGrid/index.js.map +1 -0
  104. package/cards/form/form.component.d.ts +4 -0
  105. package/cards/form/form.component.js +64 -0
  106. package/cards/form/form.component.js.map +1 -0
  107. package/cards/form/form.context.d.ts +23 -0
  108. package/cards/form/form.context.js +13 -0
  109. package/cards/form/form.context.js.map +1 -0
  110. package/cards/form/form.types.d.ts +43 -0
  111. package/cards/form/form.types.js +7 -0
  112. package/cards/form/form.types.js.map +1 -0
  113. package/cards/form/index.d.ts +2 -0
  114. package/cards/form/index.js +14 -0
  115. package/cards/form/index.js.map +1 -0
  116. package/cards/framework/framework.component.d.ts +3 -0
  117. package/cards/framework/framework.component.js +21 -0
  118. package/cards/framework/framework.component.js.map +1 -0
  119. package/cards/framework/index.d.ts +2 -0
  120. package/cards/framework/index.js +12 -0
  121. package/cards/framework/index.js.map +1 -0
  122. package/cards/graphin/graphin.component.d.ts +4 -0
  123. package/cards/graphin/graphin.types.d.ts +18 -0
  124. package/cards/graphin/index.d.ts +2 -0
  125. package/cards/graphin/tooltip.component.d.ts +10 -0
  126. package/cards/icons.d.ts +15 -0
  127. package/cards/icons.js +15 -0
  128. package/cards/icons.js.map +1 -0
  129. package/cards/input/index.d.ts +1 -0
  130. package/cards/input/index.js +13 -0
  131. package/cards/input/index.js.map +1 -0
  132. package/cards/input/input.component.d.ts +4 -0
  133. package/cards/input/input.component.js +69 -0
  134. package/cards/input/input.component.js.map +1 -0
  135. package/cards/input/input.types.d.ts +80 -0
  136. package/cards/input/input.types.js +7 -0
  137. package/cards/input/input.types.js.map +1 -0
  138. package/cards/jsonViewer/index.d.ts +1 -0
  139. package/cards/jsonViewer/jsonViewer.component.d.ts +4 -0
  140. package/cards/jsonViewer/jsonViewer.types.d.ts +76 -0
  141. package/cards/list/index.d.ts +1 -0
  142. package/cards/list/index.js +13 -0
  143. package/cards/list/index.js.map +1 -0
  144. package/cards/list/list.component.d.ts +4 -0
  145. package/cards/list/list.component.js +102 -0
  146. package/cards/list/list.component.js.map +1 -0
  147. package/cards/list/list.types.d.ts +65 -0
  148. package/cards/list/list.types.js +7 -0
  149. package/cards/list/list.types.js.map +1 -0
  150. package/cards/loadingOverlay/index.d.ts +1 -0
  151. package/cards/loadingOverlay/index.js +12 -0
  152. package/cards/loadingOverlay/index.js.map +1 -0
  153. package/cards/loadingOverlay/loadingOverlay.component.d.ts +4 -0
  154. package/cards/loadingOverlay/loadingOverlay.component.js +31 -0
  155. package/cards/loadingOverlay/loadingOverlay.component.js.map +1 -0
  156. package/cards/loadingOverlay/loadingOverlay.types.d.ts +13 -0
  157. package/cards/loadingOverlay/loadingOverlay.types.js +7 -0
  158. package/cards/loadingOverlay/loadingOverlay.types.js.map +1 -0
  159. package/cards/loadingSkeleton/index.d.ts +1 -0
  160. package/cards/loadingSkeleton/index.js +12 -0
  161. package/cards/loadingSkeleton/index.js.map +1 -0
  162. package/cards/loadingSkeleton/loading-skeleton.component.d.ts +19 -0
  163. package/cards/loadingSkeleton/loading-skeleton.component.js +33 -0
  164. package/cards/loadingSkeleton/loading-skeleton.component.js.map +1 -0
  165. package/cards/loadingSkeleton/loading-skeleton.types.d.ts +94 -0
  166. package/cards/loadingSkeleton/loading-skeleton.types.js +7 -0
  167. package/cards/loadingSkeleton/loading-skeleton.types.js.map +1 -0
  168. package/cards/markdownViewer/index.d.ts +1 -0
  169. package/cards/markdownViewer/markdownViewer.component.d.ts +4 -0
  170. package/cards/markdownViewer/markdownViewer.types.d.ts +28 -0
  171. package/cards/menu/index.d.ts +1 -0
  172. package/cards/menu/index.js +13 -0
  173. package/cards/menu/index.js.map +1 -0
  174. package/cards/menu/menu.component.d.ts +4 -0
  175. package/cards/menu/menu.component.js +23 -0
  176. package/cards/menu/menu.component.js.map +1 -0
  177. package/cards/menu/menu.types.d.ts +53 -0
  178. package/cards/menu/menu.types.js +7 -0
  179. package/cards/menu/menu.types.js.map +1 -0
  180. package/cards/modeToggle/index.d.ts +1 -0
  181. package/cards/modeToggle/index.js +13 -0
  182. package/cards/modeToggle/index.js.map +1 -0
  183. package/cards/modeToggle/mode-toggle.component.d.ts +4 -0
  184. package/cards/modeToggle/mode-toggle.component.js +32 -0
  185. package/cards/modeToggle/mode-toggle.component.js.map +1 -0
  186. package/cards/modeToggle/mode-toggle.types.d.ts +20 -0
  187. package/cards/modeToggle/mode-toggle.types.js +7 -0
  188. package/cards/modeToggle/mode-toggle.types.js.map +1 -0
  189. package/cards/navbarSearch/index.d.ts +1 -0
  190. package/cards/navbarSearch/index.js +13 -0
  191. package/cards/navbarSearch/index.js.map +1 -0
  192. package/cards/navbarSearch/navbarSearch.component.d.ts +3 -0
  193. package/cards/navbarSearch/navbarSearch.component.js +88 -0
  194. package/cards/navbarSearch/navbarSearch.component.js.map +1 -0
  195. package/cards/navbarSearch/navbarSearch.type.d.ts +32 -0
  196. package/cards/navbarSearch/navbarSearch.type.js +11 -0
  197. package/cards/navbarSearch/navbarSearch.type.js.map +1 -0
  198. package/cards/pageWithNavbar/index.d.ts +2 -0
  199. package/cards/pageWithNavbar/index.js +14 -0
  200. package/cards/pageWithNavbar/index.js.map +1 -0
  201. package/cards/pageWithNavbar/pageWithNavbar.component.d.ts +12 -0
  202. package/cards/pageWithNavbar/pageWithNavbar.component.js +153 -0
  203. package/cards/pageWithNavbar/pageWithNavbar.component.js.map +1 -0
  204. package/cards/pageWithNavbar/pageWithNavbar.type.d.ts +81 -0
  205. package/cards/pageWithNavbar/pageWithNavbar.type.js +7 -0
  206. package/cards/pageWithNavbar/pageWithNavbar.type.js.map +1 -0
  207. package/cards/pasteTarget/index.d.ts +1 -0
  208. package/cards/pasteTarget/index.js +13 -0
  209. package/cards/pasteTarget/index.js.map +1 -0
  210. package/cards/pasteTarget/pasteTarget.component.d.ts +4 -0
  211. package/cards/pasteTarget/pasteTarget.component.js +158 -0
  212. package/cards/pasteTarget/pasteTarget.component.js.map +1 -0
  213. package/cards/pasteTarget/pasteTarget.types.d.ts +46 -0
  214. package/cards/pasteTarget/pasteTarget.types.js +11 -0
  215. package/cards/pasteTarget/pasteTarget.types.js.map +1 -0
  216. package/cards/resizable/index.d.ts +1 -0
  217. package/cards/resizable/resizable.component.d.ts +4 -0
  218. package/cards/resizable/resizable.types.d.ts +49 -0
  219. package/cards/select/index.d.ts +1 -0
  220. package/cards/select/index.js +13 -0
  221. package/cards/select/index.js.map +1 -0
  222. package/cards/select/select.component.d.ts +4 -0
  223. package/cards/select/select.component.js +41 -0
  224. package/cards/select/select.component.js.map +1 -0
  225. package/cards/select/select.types.d.ts +73 -0
  226. package/cards/select/select.types.js +11 -0
  227. package/cards/select/select.types.js.map +1 -0
  228. package/cards/stack/index.d.ts +1 -0
  229. package/cards/stack/index.js +12 -0
  230. package/cards/stack/index.js.map +1 -0
  231. package/cards/stack/stack.component.d.ts +7 -0
  232. package/cards/stack/stack.component.js +83 -0
  233. package/cards/stack/stack.component.js.map +1 -0
  234. package/cards/stack/stack.types.d.ts +47 -0
  235. package/cards/stack/stack.types.js +7 -0
  236. package/cards/stack/stack.types.js.map +1 -0
  237. package/cards/stepper/index.d.ts +1 -0
  238. package/cards/stepper/index.js +13 -0
  239. package/cards/stepper/index.js.map +1 -0
  240. package/cards/stepper/stepper.component.d.ts +4 -0
  241. package/cards/stepper/stepper.component.js +48 -0
  242. package/cards/stepper/stepper.component.js.map +1 -0
  243. package/cards/stepper/stepper.types.d.ts +96 -0
  244. package/cards/stepper/stepper.types.js +7 -0
  245. package/cards/stepper/stepper.types.js.map +1 -0
  246. package/cards/switch/index.d.ts +1 -0
  247. package/cards/switch/index.js +13 -0
  248. package/cards/switch/index.js.map +1 -0
  249. package/cards/switch/switch.component.d.ts +4 -0
  250. package/cards/switch/switch.component.js +34 -0
  251. package/cards/switch/switch.component.js.map +1 -0
  252. package/cards/switch/switch.types.d.ts +39 -0
  253. package/cards/switch/switch.types.js +7 -0
  254. package/cards/switch/switch.types.js.map +1 -0
  255. package/cards/tabs/index.d.ts +1 -0
  256. package/cards/tabs/index.js +13 -0
  257. package/cards/tabs/index.js.map +1 -0
  258. package/cards/tabs/tabs.component.d.ts +4 -0
  259. package/cards/tabs/tabs.component.js +42 -0
  260. package/cards/tabs/tabs.component.js.map +1 -0
  261. package/cards/tabs/tabs.types.d.ts +72 -0
  262. package/cards/tabs/tabs.types.js +7 -0
  263. package/cards/tabs/tabs.types.js.map +1 -0
  264. package/cards/textField/index.d.ts +1 -0
  265. package/cards/textField/index.js +13 -0
  266. package/cards/textField/index.js.map +1 -0
  267. package/cards/textField/textField.component.d.ts +4 -0
  268. package/cards/textField/textField.component.js +29 -0
  269. package/cards/textField/textField.component.js.map +1 -0
  270. package/cards/textField/textField.types.d.ts +36 -0
  271. package/cards/textField/textField.types.js +7 -0
  272. package/cards/textField/textField.types.js.map +1 -0
  273. package/cards/toast/index.d.ts +1 -0
  274. package/cards/toast/index.js +13 -0
  275. package/cards/toast/index.js.map +1 -0
  276. package/cards/toast/toast.component.d.ts +4 -0
  277. package/cards/toast/toast.component.js +76 -0
  278. package/cards/toast/toast.component.js.map +1 -0
  279. package/cards/toast/toast.types.d.ts +100 -0
  280. package/cards/toast/toast.types.js +12 -0
  281. package/cards/toast/toast.types.js.map +1 -0
  282. package/cards/toggleGroup/index.d.ts +1 -0
  283. package/cards/toggleGroup/index.js +13 -0
  284. package/cards/toggleGroup/index.js.map +1 -0
  285. package/cards/toggleGroup/toggleGroup.component.d.ts +4 -0
  286. package/cards/toggleGroup/toggleGroup.component.js +55 -0
  287. package/cards/toggleGroup/toggleGroup.component.js.map +1 -0
  288. package/cards/toggleGroup/toggleGroup.types.d.ts +96 -0
  289. package/cards/toggleGroup/toggleGroup.types.js +7 -0
  290. package/cards/toggleGroup/toggleGroup.types.js.map +1 -0
  291. package/cards/types.d.ts +72 -0
  292. package/cards/types.js +22 -0
  293. package/cards/types.js.map +1 -0
  294. package/cards/typography/index.d.ts +1 -0
  295. package/cards/typography/index.js +12 -0
  296. package/cards/typography/index.js.map +1 -0
  297. package/cards/typography/typography.component.d.ts +4 -0
  298. package/cards/typography/typography.component.js +44 -0
  299. package/cards/typography/typography.component.js.map +1 -0
  300. package/cards/typography/typography.types.d.ts +23 -0
  301. package/cards/typography/typography.types.js +7 -0
  302. package/cards/typography/typography.types.js.map +1 -0
  303. package/components/hooks/use-is-touch-device.d.ts +1 -0
  304. package/components/lib/utils.js +10 -0
  305. package/components/lib/utils.js.map +1 -0
  306. package/components/theme-provider/index.d.ts +4 -0
  307. package/components/theme-provider/index.js +12 -0
  308. package/components/theme-provider/index.js.map +1 -0
  309. package/components/theme-provider/theme-provider.component.d.ts +2 -0
  310. package/components/theme-provider/theme-provider.component.js +31 -0
  311. package/components/theme-provider/theme-provider.component.js.map +1 -0
  312. package/components/theme-provider/theme-provider.types.d.ts +12 -0
  313. package/components/theme-provider/theme-provider.types.js +9 -0
  314. package/components/theme-provider/theme-provider.types.js.map +1 -0
  315. package/components/ui/avatar.js +30 -0
  316. package/components/ui/avatar.js.map +1 -0
  317. package/components/ui/badge.js +26 -0
  318. package/components/ui/badge.js.map +1 -0
  319. package/components/ui/button.js +98 -0
  320. package/components/ui/button.js.map +1 -0
  321. package/components/ui/dialog.js +109 -0
  322. package/components/ui/dialog.js.map +1 -0
  323. package/components/ui/field.js +68 -0
  324. package/components/ui/field.js.map +1 -0
  325. package/components/ui/input.js +16 -0
  326. package/components/ui/input.js.map +1 -0
  327. package/components/ui/label.js +16 -0
  328. package/components/ui/label.js.map +1 -0
  329. package/components/ui/menubar.js +62 -0
  330. package/components/ui/menubar.js.map +1 -0
  331. package/components/ui/select.js +84 -0
  332. package/components/ui/select.js.map +1 -0
  333. package/components/ui/separator.js +5 -0
  334. package/components/ui/sheet.js +49 -0
  335. package/components/ui/sheet.js.map +1 -0
  336. package/components/ui/spinner.js +35 -0
  337. package/components/ui/spinner.js.map +1 -0
  338. package/components/ui/stepper.js +145 -0
  339. package/components/ui/stepper.js.map +1 -0
  340. package/components/ui/switch.js +20 -0
  341. package/components/ui/switch.js.map +1 -0
  342. package/components/ui/table.js +61 -0
  343. package/components/ui/table.js.map +1 -0
  344. package/components/ui/tabs.js +38 -0
  345. package/components/ui/tabs.js.map +1 -0
  346. package/components/ui/toggle-group.js +50 -0
  347. package/components/ui/toggle-group.js.map +1 -0
  348. package/components/ui/toggle.js +27 -0
  349. package/components/ui/toggle.js.map +1 -0
  350. package/components/ui/tooltip.js +38 -0
  351. package/components/ui/tooltip.js.map +1 -0
  352. package/lib/utils.d.ts +2 -0
  353. package/lib/utils.js +10 -0
  354. package/lib/utils.js.map +1 -0
  355. package/mountain-snow.svg +4 -0
  356. package/package.json +203 -0
  357. package/pihanga-shadcn.css +2 -0
  358. package/r/badge.json +35 -0
  359. package/r/box.json +26 -0
  360. package/r/button.json +39 -0
  361. package/r/checkbox.json +31 -0
  362. package/r/conditional.json +30 -0
  363. package/r/dataTable.json +43 -0
  364. package/r/dialog.json +36 -0
  365. package/r/dropDownMenu.json +47 -0
  366. package/r/field.json +35 -0
  367. package/r/flexGrid.json +32 -0
  368. package/r/form.json +37 -0
  369. package/r/framework.json +28 -0
  370. package/r/graphin.json +42 -0
  371. package/r/input.json +35 -0
  372. package/r/jsonViewer.json +40 -0
  373. package/r/list.json +39 -0
  374. package/r/loadingOverlay.json +39 -0
  375. package/r/loadingSkeleton.json +30 -0
  376. package/r/markdownViewer.json +51 -0
  377. package/r/menu.json +34 -0
  378. package/r/modeToggle.json +36 -0
  379. package/r/navbarSearch.json +31 -0
  380. package/r/pageWithNavbar.json +46 -0
  381. package/r/pasteTarget.json +41 -0
  382. package/r/pihanga-base.json +11 -0
  383. package/r/pihanga-cards-icons.json +16 -0
  384. package/r/pihanga-cards-types.json +16 -0
  385. package/r/pihanga-hook-use-is-touch-device.json +15 -0
  386. package/r/pihanga-lib-utils.json +18 -0
  387. package/r/pihanga-theme-provider.json +25 -0
  388. package/r/pihanga-ui-extras.json +68 -0
  389. package/r/registry.json +171 -0
  390. package/r/resizable.json +35 -0
  391. package/r/select.json +35 -0
  392. package/r/stack.json +27 -0
  393. package/r/stepper.json +39 -0
  394. package/r/switch.json +36 -0
  395. package/r/tabs.json +33 -0
  396. package/r/textField.json +32 -0
  397. package/r/toast.json +32 -0
  398. package/r/toggleGroup.json +35 -0
  399. package/r/typography.json +31 -0
package/r/switch.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "switch",
4
+ "type": "registry:component",
5
+ "description": "Pihanga switch card component",
6
+ "dependencies": [
7
+ "@radix-ui/react-switch@UNKNOWN - add to root package.json",
8
+ "radix-ui@^1.4.3"
9
+ ],
10
+ "registryDependencies": [
11
+ "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json",
12
+ "switch",
13
+ "label",
14
+ "https://ivcap-works.github.io/pihanga-shadcn/r/form.json"
15
+ ],
16
+ "files": [
17
+ {
18
+ "path": "cards/switch/index.ts",
19
+ "content": "import {actionTypesToEvents, registerCardComponent} from \"@pihanga2/core\";\n\nimport {SwitchComponent} from \"./switch.component\";\nimport {PI_SWITCH_ACTION, PI_SWITCH_CARD} from \"./switch.types\";\n\nexport * from \"./switch.types\";\n\nregisterCardComponent({\n name: PI_SWITCH_CARD,\n component: SwitchComponent,\n events: actionTypesToEvents(PI_SWITCH_ACTION),\n});\n",
20
+ "type": "registry:component",
21
+ "target": "src/cards/switch/index.ts"
22
+ },
23
+ {
24
+ "path": "cards/switch/switch.component.tsx",
25
+ "content": "import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Switch as SwitchUI} from \"@/components/ui/switch\";\nimport {Label} from \"@/components/ui/label\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {PiSwitchEvents, PiSwitchProps} from \"./switch.types\";\n\nexport const SwitchComponent = (\n props: PiCardProps<PiSwitchProps, PiSwitchEvents>,\n): React.ReactNode => {\n const {\n name,\n checked: propChecked = false,\n disabled,\n label,\n className,\n cardName,\n onChanged,\n } = props;\n\n // `id` and `invalid` may be injected by a parent pi/field card via\n // Pihanga's extra-prop forwarding. They are not in the official type so\n // we read them through an escape hatch.\n const injectedId = (props as {id?: string}).id;\n\n // Detect if we are inside a pi/form card via React context.\n const form = useFormContext();\n const useFormData = form.isInForm && Boolean(name);\n\n const checked = useFormData\n ? Boolean(form.formData[name!] ?? false)\n : propChecked;\n\n function handleCheckedChange(newChecked: boolean) {\n if (useFormData) {\n form.handleChange(name!, newChecked);\n } else {\n onChanged({name, checked: newChecked});\n }\n }\n\n // Use the id injected by pi/field; fall back to a local id when standalone.\n const selfId = `${cardName}-${name ?? \"switch\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <div\n data-pihanga={cardName}\n className={`flex items-center gap-2 ${className ?? \"\"}`}\n >\n <SwitchUI\n id={fieldId}\n checked={checked}\n onCheckedChange={handleCheckedChange}\n disabled={disabled}\n />\n {label && (\n <Label htmlFor={fieldId} className=\"cursor-pointer select-none\">\n {label}\n </Label>\n )}\n </div>\n );\n};\n",
26
+ "type": "registry:component",
27
+ "target": "src/cards/switch/switch.component.tsx"
28
+ },
29
+ {
30
+ "path": "cards/switch/switch.types.ts",
31
+ "content": "import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_SWITCH_CARD = \"pi/switch\";\n\nexport const Switch = createCardDeclaration<PiSwitchProps, PiSwitchEvents>(\n PI_SWITCH_CARD,\n);\n\nexport const PI_SWITCH_ACTION = registerActions(PI_SWITCH_CARD, [\"changed\"]);\n\nexport const onPiSwitchChanged = createOnAction<PiSwitchChangedEvent>(\n PI_SWITCH_ACTION.CHANGED,\n);\n\n// ---------------------------------------------------------------------------\n// Props & Events\n// ---------------------------------------------------------------------------\n\nexport type PiSwitchProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its checked state from form data and\n * writes back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled checked state used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n checked?: boolean;\n\n /** When true, the switch is disabled and non-interactive. */\n disabled?: boolean;\n\n /**\n * Optional label text rendered beside the switch.\n * The label is automatically associated with the switch via `htmlFor`.\n */\n label?: string;\n\n /** Extra Tailwind / CSS classes forwarded to the root wrapper element. */\n className?: string;\n};\n\nexport type PiSwitchChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New checked state after the toggle. */\n checked: boolean;\n};\n\nexport type PiSwitchEvents = {\n onChanged: PiSwitchChangedEvent;\n};\n",
32
+ "type": "registry:component",
33
+ "target": "src/cards/switch/switch.types.ts"
34
+ }
35
+ ]
36
+ }
package/r/tabs.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "tabs",
4
+ "type": "registry:component",
5
+ "description": "Pihanga tabs card component",
6
+ "dependencies": [
7
+ "@radix-ui/react-tabs@^1.1.13"
8
+ ],
9
+ "registryDependencies": [
10
+ "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json",
11
+ "tabs"
12
+ ],
13
+ "files": [
14
+ {
15
+ "path": "cards/tabs/index.ts",
16
+ "content": "import {registerCardComponent} from \"@pihanga2/core\";\n\nimport {TabsComponent} from \"./tabs.component\";\nimport {TABS_ACTION, TABS_CARD} from \"./tabs.types\";\n\nexport * from \"./tabs.types\";\n\nregisterCardComponent({\n name: TABS_CARD,\n component: TabsComponent,\n // Explicit mapping avoids CamelCase normalisation issues:\n // TABCHANGED → onTabChanged (lowercase 'c' would break with actionTypesToEvents)\n events: {\n onTabChanged: TABS_ACTION.TABCHANGED,\n },\n});\n",
17
+ "type": "registry:component",
18
+ "target": "src/cards/tabs/index.ts"
19
+ },
20
+ {
21
+ "path": "cards/tabs/tabs.component.tsx",
22
+ "content": "import React, {useState} from \"react\";\nimport {Card, isCardRef, type PiCardProps} from \"@pihanga2/core\";\nimport {Tabs, TabsContent, TabsList, TabsTrigger} from \"@/components/ui/tabs\";\nimport type {TabsEvents, TabsProps} from \"./tabs.types\";\n\nexport const TabsComponent = (\n props: PiCardProps<TabsProps, TabsEvents>,\n): React.ReactNode => {\n const {\n tabs,\n value: propValue,\n defaultValue,\n selfManaged = false,\n orientation = \"horizontal\",\n className,\n listClassName,\n contentClassName,\n cardName,\n onTabChanged,\n } = props;\n\n // Resolve the initial value for self-managed mode:\n // prefer propValue, then defaultValue, then first tab's id.\n const initialValue = propValue ?? defaultValue ?? tabs[0]?.id ?? \"\";\n\n // Internal state used only when selfManaged=true.\n const [managedValue, setManagedValue] = useState<string>(initialValue);\n\n // Effective active tab:\n // selfManaged → use internal state\n // controlled → use the prop (fall back to first tab if not set)\n const activeValue = selfManaged\n ? managedValue\n : (propValue ?? defaultValue ?? tabs[0]?.id ?? \"\");\n\n function handleValueChange(tabId: string) {\n if (selfManaged) {\n setManagedValue(tabId);\n }\n // Always dispatch the Pihanga event so reducers can observe the change\n // even in self-managed mode.\n if (typeof onTabChanged === \"function\") {\n onTabChanged({tabId});\n }\n }\n\n return (\n <div data-pihanga={cardName}>\n <Tabs\n value={activeValue}\n onValueChange={handleValueChange}\n orientation={orientation}\n className={className}\n >\n <TabsList className={listClassName}>\n {tabs.map((tab) => (\n <TabsTrigger\n key={tab.id}\n value={tab.id}\n disabled={tab.disabled}\n >\n {isCardRef(tab.title) ? (\n <Card cardName={tab.title} parentCard={cardName} />\n ) : (\n (tab.title as string)\n )}\n </TabsTrigger>\n ))}\n </TabsList>\n\n {tabs.map((tab) => (\n <TabsContent\n key={tab.id}\n value={tab.id}\n className={contentClassName}\n >\n <Card cardName={tab.contentCard} parentCard={cardName} />\n </TabsContent>\n ))}\n </Tabs>\n </div>\n );\n};\n",
23
+ "type": "registry:component",
24
+ "target": "src/cards/tabs/tabs.component.tsx"
25
+ },
26
+ {
27
+ "path": "cards/tabs/tabs.types.ts",
28
+ "content": "import {\n createCardDeclaration,\n createOnAction,\n type PiCardRef,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const TABS_CARD = \"shad/tabs\";\n\nexport const SdTabs = createCardDeclaration<TabsProps, TabsEvents>(TABS_CARD);\n\nexport const TABS_ACTION = registerActions(TABS_CARD, [\"tabChanged\"]);\n\nexport const onTabsTabChanged = createOnAction<TabsTabChangedEvent>(\n TABS_ACTION.TABCHANGED,\n);\n\n// ─── Tab item definition ──────────────────────────────────────────────────────\n\n/**\n * A single tab entry in the tabs component.\n */\nexport type TabItem = {\n /** Unique identifier used for controlled value and events. */\n id: string;\n\n /**\n * The label displayed on the tab trigger.\n * Can be a plain string or a PiCardRef for custom/rich tab labels.\n */\n title: string | PiCardRef;\n\n /**\n * The Pihanga card rendered as the body of this tab when it is active.\n */\n contentCard: PiCardRef;\n\n /** When true the tab trigger is rendered as disabled. */\n disabled?: boolean;\n};\n\n// ─── Card props ───────────────────────────────────────────────────────────────\n\nexport type TabsProps = {\n /** Ordered list of tab definitions. */\n tabs: TabItem[];\n\n /**\n * Controlled: the currently active tab id.\n * Must be provided (or supplied via a state mapper) when selfManaged is\n * false (the default).\n */\n value?: string;\n\n /**\n * Uncontrolled initial active tab id.\n * Used as the initial value in self-managed mode when value is not set;\n * falls back to the first tab id if omitted.\n */\n defaultValue?: string;\n\n /**\n * When true, the component manages its own active tab state internally.\n * The onTabChanged event is still dispatched on every change so external\n * reducers can observe the selection.\n *\n * When false (default), value fully controls the displayed tab.\n * @default false\n */\n selfManaged?: boolean;\n\n /**\n * Layout orientation of the tab list.\n * Passed directly to the Radix Tabs primitive.\n * @default \"horizontal\"\n */\n orientation?: \"horizontal\" | \"vertical\";\n\n /** Additional Tailwind/CSS classes applied to the root Tabs element. */\n className?: string;\n\n /** Additional classes applied to the TabsList element. */\n listClassName?: string;\n\n /** Additional classes applied to each TabsContent element. */\n contentClassName?: string;\n};\n\n// ─── Events ───────────────────────────────────────────────────────────────────\n\nexport type TabsTabChangedEvent = {\n /** The id of the newly selected tab. */\n tabId: string;\n};\n\nexport type TabsEvents = {\n /** Fired whenever the user selects a different tab. */\n onTabChanged: TabsTabChangedEvent;\n};\n",
29
+ "type": "registry:component",
30
+ "target": "src/cards/tabs/tabs.types.ts"
31
+ }
32
+ ]
33
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "textField",
4
+ "type": "registry:component",
5
+ "description": "Pihanga textField card component",
6
+ "dependencies": [],
7
+ "registryDependencies": [
8
+ "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json",
9
+ "input",
10
+ "https://ivcap-works.github.io/pihanga-shadcn/r/form.json"
11
+ ],
12
+ "files": [
13
+ {
14
+ "path": "cards/textField/index.ts",
15
+ "content": "import {actionTypesToEvents, registerCardComponent} from \"@pihanga2/core\";\n\nimport {TextFieldComponent} from \"./textField.component\";\nimport {PI_TEXT_FIELD_ACTION, PI_TEXT_FIELD_CARD} from \"./textField.types\";\n\nexport * from \"./textField.types\";\n\nregisterCardComponent({\n name: PI_TEXT_FIELD_CARD,\n component: TextFieldComponent,\n events: actionTypesToEvents(PI_TEXT_FIELD_ACTION),\n});\n",
16
+ "type": "registry:component",
17
+ "target": "src/cards/textField/index.ts"
18
+ },
19
+ {
20
+ "path": "cards/textField/textField.component.tsx",
21
+ "content": "import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {Input} from \"@/components/ui/input\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {PiTextFieldEvents, PiTextFieldProps} from \"./textField.types\";\n\nexport const TextFieldComponent = (\n props: PiCardProps<PiTextFieldProps, PiTextFieldEvents>,\n): React.ReactNode => {\n const {\n name,\n value: propValue = \"\",\n type = \"text\",\n placeholder,\n disabled,\n cardName,\n onChanged,\n } = props;\n\n // `id` and `invalid` may be injected by a parent pi/field card via\n // Pihanga's extra-prop forwarding. They are not in the official type so\n // we read them through an escape hatch.\n const injectedId = (props as {id?: string}).id;\n const invalid = Boolean((props as {invalid?: boolean}).invalid);\n\n // Detect if we are inside a pi/form card via React context.\n const form = useFormContext();\n const useFormData = form.isInForm && Boolean(name);\n\n const value = useFormData\n ? ((form.formData[name!] as string | undefined) ?? \"\")\n : propValue;\n\n function handleChange(e: React.ChangeEvent<HTMLInputElement>) {\n const newValue = e.target.value;\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n onChanged({name, value: newValue});\n }\n }\n\n // Use the id injected by pi/field (for label↔control linking); fall back\n // to a locally-generated id when used standalone.\n const selfId = `${cardName}-${name ?? \"field\"}`;\n const fieldId = injectedId ?? selfId;\n\n return (\n <Input\n id={fieldId}\n type={type}\n value={value}\n onChange={handleChange}\n placeholder={placeholder}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n />\n );\n};\n",
22
+ "type": "registry:component",
23
+ "target": "src/cards/textField/textField.component.tsx"
24
+ },
25
+ {
26
+ "path": "cards/textField/textField.types.ts",
27
+ "content": "import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_TEXT_FIELD_CARD = \"pi/text-field\";\n\nexport const TextField = createCardDeclaration<\n PiTextFieldProps,\n PiTextFieldEvents\n>(PI_TEXT_FIELD_CARD);\n\nexport const PI_TEXT_FIELD_ACTION = registerActions(PI_TEXT_FIELD_CARD, [\n \"changed\",\n]);\n\nexport const onPiTextFieldChanged = createOnAction<PiTextFieldChangedEvent>(\n PI_TEXT_FIELD_ACTION.CHANGED,\n);\n\nexport type PiTextFieldProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its value from form state and writes\n * back via form.handleChange.\n */\n name?: string;\n\n /**\n * Controlled value used in standalone mode (outside a Form).\n * Ignored when `name` is set and the component is inside a pi/form.\n */\n value?: string;\n\n /** HTML input type (e.g. \"text\", \"email\", \"password\", \"number\"). */\n type?: string;\n\n /** Placeholder text shown when the input is empty. */\n placeholder?: string;\n\n /** When true, the input is disabled and non-interactive. */\n disabled?: boolean;\n};\n\nexport type PiTextFieldChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /** New value after the change. */\n value: string;\n};\n\nexport type PiTextFieldEvents = {\n onChanged: PiTextFieldChangedEvent;\n};\n",
28
+ "type": "registry:component",
29
+ "target": "src/cards/textField/textField.types.ts"
30
+ }
31
+ ]
32
+ }
package/r/toast.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "toast",
4
+ "type": "registry:component",
5
+ "description": "Pihanga toast card component",
6
+ "dependencies": [
7
+ "sonner@^2.0.7"
8
+ ],
9
+ "registryDependencies": [
10
+ "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json"
11
+ ],
12
+ "files": [
13
+ {
14
+ "path": "cards/toast/index.ts",
15
+ "content": "import {actionTypesToEvents, registerCardComponent} from \"@pihanga2/core\";\n\nimport {ToastComponent} from \"./toast.component\";\nimport {PI_TOAST_ACTION, PI_TOAST_CARD} from \"./toast.types\";\n\nexport * from \"./toast.types\";\n\nregisterCardComponent({\n name: PI_TOAST_CARD,\n component: ToastComponent,\n events: actionTypesToEvents(PI_TOAST_ACTION),\n});\n",
16
+ "type": "registry:component",
17
+ "target": "src/cards/toast/index.ts"
18
+ },
19
+ {
20
+ "path": "cards/toast/toast.component.tsx",
21
+ "content": "import React, {useEffect, useRef, useState} from \"react\";\nimport {\n Card,\n type PiCardProps,\n type PiCardRef,\n usePiReducer,\n type ReduxAction,\n type ReduxState,\n} from \"@pihanga2/core\";\nimport {toast} from \"sonner\";\n\nimport {\n ShowToastEvent,\n TOAST_OP_ACTION,\n ToastPosition,\n ToastType,\n type PiToastEvents,\n type PiToastProps,\n} from \"./toast.types\";\n\nexport const ToastComponent = (\n props: PiCardProps<PiToastProps, PiToastEvents>,\n): React.ReactNode => {\n const {\n variant: defaultVariant = \"default\",\n duration: defaultDuration = 4000,\n dismissible: defaultDismissible = true,\n className: defaultClassName,\n onClosed,\n cardName,\n } = props;\n\n // State for tracking Redux-triggered toast messages\n const [currentToast, setCurrentToast] = useState<{\n message?: string;\n description?: string;\n contentCard?: PiCardRef;\n variant: ToastType;\n position?: ToastPosition;\n duration: number;\n } | null>(null);\n\n // Listen for showToast Redux messages\n // This allows triggering toasts from anywhere via dispatchShowToast\n usePiReducer<ReduxState, ShowToastEvent & ReduxAction>(\n TOAST_OP_ACTION.SHOW,\n (_, action) => {\n // Only respond if message is for this card or no specific cardName is set\n if (action.cardName && action.cardName !== cardName) {\n return;\n }\n setCurrentToast({\n message: action.message,\n description: action.description,\n contentCard: action.contentCard,\n variant: action.variant ?? defaultVariant,\n position: action.position,\n duration: action.duration ?? defaultDuration,\n });\n },\n cardName,\n );\n\n // Setup hooks before conditional rendering\n const toastIdRef = useRef<string | number | undefined>(undefined);\n\n useEffect(() => {\n // Only show toast if Redux message was received\n if (!currentToast) {\n return;\n }\n\n // Map our toast types to Sonner's toast function\n const toastFn =\n {\n success: toast.success,\n error: toast.error,\n info: toast.info,\n warning: toast.warning,\n default: toast,\n }[currentToast.variant] || toast;\n\n // Build className: combine default + variant-based class\n const className = [defaultClassName, `toast-${currentToast.variant}`]\n .filter(Boolean)\n .join(\" \");\n\n // If contentCard is provided, render it as custom JSX content\n if (currentToast.contentCard) {\n const contentCard = currentToast.contentCard;\n const CustomToastContent = () => (\n <Card cardName={contentCard} parentCard={cardName} />\n );\n\n // Show the toast with custom card content\n toastIdRef.current = toastFn(CustomToastContent, {\n duration: currentToast.duration,\n position: currentToast.position || \"bottom-right\",\n dismissible: defaultDismissible,\n className,\n onDismiss: () => {\n setCurrentToast(null);\n onClosed({});\n },\n onAutoClose: () => {\n setCurrentToast(null);\n onClosed({});\n },\n });\n } else {\n // Show the toast with message and optional description\n toastIdRef.current = toastFn(currentToast.message, {\n description: currentToast.description,\n duration: currentToast.duration,\n position: currentToast.position || \"bottom-right\",\n dismissible: defaultDismissible,\n className,\n onDismiss: () => {\n setCurrentToast(null);\n onClosed({});\n },\n onAutoClose: () => {\n setCurrentToast(null);\n onClosed({});\n },\n });\n }\n\n // Cleanup on unmount\n return () => {\n if (toastIdRef.current !== undefined) {\n toast.dismiss(toastIdRef.current);\n }\n };\n }, [currentToast, defaultDismissible, defaultClassName, onClosed, cardName]);\n\n // This component doesn't render visible DOM itself\n // Sonner renders toasts in a portal via its Toaster component\n return <div data-pihanga={cardName} style={{display: \"none\"}} />;\n};\n",
22
+ "type": "registry:component",
23
+ "target": "src/cards/toast/toast.component.tsx"
24
+ },
25
+ {
26
+ "path": "cards/toast/toast.types.ts",
27
+ "content": "import {\n createCardDeclaration,\n createOnAction,\n PiCardRef,\n registerActions,\n type DispatchF,\n} from \"@pihanga2/core\";\n\nexport const PI_TOAST_CARD = \"pi/toast\";\n\nexport const Toast = createCardDeclaration<PiToastProps, PiToastEvents>(\n PI_TOAST_CARD,\n);\n\nexport const TOAST_OP_ACTION = registerActions(\"toast/op\", [\"show\"]);\n\n/**\n * Dispatch helper to show a toast\n *\n * @param d - Dispatch function from Pihanga\n * @param ev - Toast event data\n *\n * @example\n * ```typescript\n * import {dispatchShowToast} from \"@/cards/toast\";\n *\n * dispatchShowToast(_dispatch, {\n * message: \"Success!\",\n * description: \"Your changes were saved.\",\n * type: \"success\",\n * duration: 3000,\n * });\n * ```\n */\nexport const dispatchShowToast = (d: DispatchF, ev: ShowToastEvent) => {\n d({...ev, type: TOAST_OP_ACTION.SHOW});\n};\n\n/**\n * Action handler for when a toast is shown\n *\n * Use this in your reducers or effects to handle toast display events:\n *\n * @example\n * ```typescript\n * import {onShowToast} from \"@/cards/toast\";\n *\n * export const handleShowToast = onShowToast((state, action) => {\n * console.log(\"Toast shown:\", action.payload.message);\n * return state;\n * });\n * ```\n */\nexport const onShowToast = createOnAction<ShowToastEvent>(TOAST_OP_ACTION.SHOW);\n\nexport const PI_TOAST_ACTION = registerActions(PI_TOAST_CARD, [\"closed\"]);\n\nexport const onPiToastClosed = createOnAction<PiToastClosedEvent>(\n PI_TOAST_ACTION.CLOSED,\n);\n\n/**\n * Toast notification type/variant.\n */\nexport type ToastType = \"default\" | \"success\" | \"error\" | \"info\" | \"warning\";\n\n/**\n * Position of the toast on the screen.\n */\nexport type ToastPosition =\n | \"top-left\"\n | \"top-center\"\n | \"top-right\"\n | \"bottom-left\"\n | \"bottom-center\"\n | \"bottom-right\";\n\nexport type PiToastProps = {\n /**\n * Default type/variant for toasts.\n * Can be overridden per toast via ShowToastEvent.type\n * @default 'default'\n */\n variant?: ToastType;\n\n /**\n * Default duration in milliseconds before the toast auto-closes.\n * Can be overridden per toast via ShowToastEvent.duration\n * Set to `Infinity` to disable auto-close.\n * @default 4000\n */\n duration?: number;\n\n /**\n * Default: whether toasts are dismissible.\n * Can be overridden per toast via ShowToastEvent.dismissible\n * @default true\n */\n dismissible?: boolean;\n\n /**\n * Custom CSS class to apply to all toasts from this card.\n */\n className?: string;\n};\n\nexport type PiToastClosedEvent = {\n id?: string;\n};\n\nexport type PiToastEvents = {\n onClosed: PiToastClosedEvent;\n};\n\n/**\n * Event payload for showing a toast\n */\nexport type ShowToastEvent = {\n cardName?: string;\n message: string;\n description?: string;\n contentCard?: PiCardRef; // Alternative: custom card for richer content\n variant?: ToastType;\n position?: ToastPosition; // Toast position on screen\n duration?: number;\n};\n",
28
+ "type": "registry:component",
29
+ "target": "src/cards/toast/toast.types.ts"
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "toggleGroup",
4
+ "type": "registry:component",
5
+ "description": "Pihanga toggleGroup card component",
6
+ "dependencies": [
7
+ "class-variance-authority@^0.7.1",
8
+ "radix-ui@^1.4.3"
9
+ ],
10
+ "registryDependencies": [
11
+ "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json",
12
+ "toggle-group",
13
+ "https://ivcap-works.github.io/pihanga-shadcn/r/form.json"
14
+ ],
15
+ "files": [
16
+ {
17
+ "path": "cards/toggleGroup/index.ts",
18
+ "content": "import {actionTypesToEvents, registerCardComponent} from \"@pihanga2/core\";\n\nimport {ToggleGroupComponent} from \"./toggleGroup.component\";\nimport {\n PI_TOGGLE_GROUP_ACTION,\n PI_TOGGLE_GROUP_CARD,\n} from \"./toggleGroup.types\";\n\nexport * from \"./toggleGroup.types\";\n\nregisterCardComponent({\n name: PI_TOGGLE_GROUP_CARD,\n component: ToggleGroupComponent,\n events: actionTypesToEvents(PI_TOGGLE_GROUP_ACTION),\n});\n",
19
+ "type": "registry:component",
20
+ "target": "src/cards/toggleGroup/index.ts"
21
+ },
22
+ {
23
+ "path": "cards/toggleGroup/toggleGroup.component.tsx",
24
+ "content": "import React from \"react\";\nimport {type PiCardProps} from \"@pihanga2/core\";\nimport {\n ToggleGroup as ToggleGroupUI,\n ToggleGroupItem,\n} from \"@/components/ui/toggle-group\";\nimport {useFormContext} from \"@/cards/form/form.context\";\nimport type {\n PiToggleGroupEvents,\n PiToggleGroupProps,\n} from \"./toggleGroup.types\";\n\nexport const ToggleGroupComponent = (\n props: PiCardProps<PiToggleGroupProps, PiToggleGroupEvents>,\n): React.ReactNode => {\n const {\n name,\n items,\n type = \"single\",\n value: propValue,\n selfManaged = false,\n variant = \"default\",\n size = \"default\",\n spacing = 0,\n disabled,\n className,\n cardName,\n onChanged,\n } = props;\n\n // Detect if we are inside a pi/form card via React context.\n const form = useFormContext();\n const useFormData = form.isInForm && Boolean(name);\n\n // ---------------------------------------------------------------------------\n // Self-managed (internal) state — only active when selfManaged=true and we\n // are NOT inside a pi/form card.\n // ---------------------------------------------------------------------------\n const initialSelfValue: string | string[] =\n type === \"multiple\"\n ? Array.isArray(propValue)\n ? propValue\n : propValue != null\n ? [String(propValue)]\n : []\n : typeof propValue === \"string\"\n ? propValue\n : \"\";\n\n const [internalValue, setInternalValue] = React.useState<string | string[]>(\n initialSelfValue,\n );\n\n // ---------------------------------------------------------------------------\n // Derive the effective value from the appropriate source.\n // 1. Form context (highest priority)\n // 2. Self-managed internal state\n // 3. Externally controlled prop value\n // ---------------------------------------------------------------------------\n const formRawValue = useFormData ? form.formData[name!] : undefined;\n const value: string | string[] = useFormData\n ? type === \"multiple\"\n ? Array.isArray(formRawValue)\n ? (formRawValue as string[])\n : formRawValue != null\n ? [String(formRawValue)]\n : []\n : formRawValue != null\n ? String(formRawValue)\n : \"\"\n : selfManaged\n ? internalValue\n : (propValue ?? (type === \"multiple\" ? [] : \"\"));\n\n function handleSingleChange(newValue: string) {\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n if (selfManaged) {\n setInternalValue(newValue);\n }\n onChanged({name: name ?? cardName, value: newValue});\n }\n }\n\n function handleMultipleChange(newValue: string[]) {\n if (useFormData) {\n form.handleChange(name!, newValue);\n } else {\n if (selfManaged) {\n setInternalValue(newValue);\n }\n onChanged({name: name ?? cardName, value: newValue});\n }\n }\n\n // Render single-selection group\n if (type === \"single\") {\n return (\n <ToggleGroupUI\n data-pihanga={cardName}\n type=\"single\"\n value={typeof value === \"string\" ? value : \"\"}\n onValueChange={handleSingleChange}\n variant={variant}\n size={size}\n spacing={spacing}\n disabled={disabled}\n className={className}\n >\n {items.map((item) => (\n <ToggleGroupItem\n key={item.value}\n value={item.value}\n disabled={item.disabled}\n >\n {item.label}\n </ToggleGroupItem>\n ))}\n </ToggleGroupUI>\n );\n }\n\n // Render multiple-selection group\n return (\n <ToggleGroupUI\n data-pihanga={cardName}\n type=\"multiple\"\n value={Array.isArray(value) ? value : value ? [value] : []}\n onValueChange={handleMultipleChange}\n variant={variant}\n size={size}\n spacing={spacing}\n disabled={disabled}\n className={className}\n >\n {items.map((item) => (\n <ToggleGroupItem\n key={item.value}\n value={item.value}\n disabled={item.disabled}\n >\n {item.label}\n </ToggleGroupItem>\n ))}\n </ToggleGroupUI>\n );\n};\n",
25
+ "type": "registry:component",
26
+ "target": "src/cards/toggleGroup/toggleGroup.component.tsx"
27
+ },
28
+ {
29
+ "path": "cards/toggleGroup/toggleGroup.types.ts",
30
+ "content": "import {\n createCardDeclaration,\n createOnAction,\n registerActions,\n} from \"@pihanga2/core\";\n\nexport const PI_TOGGLE_GROUP_CARD = \"pi/toggle-group\";\n\nexport const ToggleGroup = createCardDeclaration<\n PiToggleGroupProps,\n PiToggleGroupEvents\n>(PI_TOGGLE_GROUP_CARD);\n\nexport const PI_TOGGLE_GROUP_ACTION = registerActions(PI_TOGGLE_GROUP_CARD, [\n \"changed\",\n]);\n\nexport const onPiToggleGroupChanged = createOnAction<PiToggleGroupChangedEvent>(\n PI_TOGGLE_GROUP_ACTION.CHANGED,\n);\n\n// ---------------------------------------------------------------------------\n// Item type\n// ---------------------------------------------------------------------------\n\nexport type PiToggleGroupItem = {\n /** The value associated with this toggle item. */\n value: string;\n /** Human-readable label rendered inside the toggle button. */\n label: string;\n /** When true, this individual item is disabled. */\n disabled?: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// Props & Events\n// ---------------------------------------------------------------------------\n\nexport type PiToggleGroupProps = {\n /**\n * Field name used to bind to FormContext when inside a pi/form card.\n * When provided the component reads its selected value from form data and\n * writes back via form.handleChange.\n */\n name?: string;\n\n /**\n * The list of toggle items to display.\n */\n items: PiToggleGroupItem[];\n\n /**\n * Selection mode.\n * - `\"single\"` — at most one item can be active at a time.\n * - `\"multiple\"` — any number of items can be active simultaneously.\n *\n * @default \"single\"\n */\n type?: \"single\" | \"multiple\";\n\n /**\n * Controlled selected value(s).\n * - In `\"single\"` mode: a `string` (or `undefined` for nothing selected).\n * - In `\"multiple\"` mode: an array of `string`.\n *\n * Ignored when `name` is set and the component is inside a pi/form.\n * Also ignored when `selfManaged` is `true`.\n */\n value?: string | string[];\n\n /**\n * When `true`, the component manages its own selection state internally\n * using `React.useState`. The `value` prop is used only as the initial\n * value (i.e. `defaultValue`) and subsequent changes do not require an\n * external state update. `onChanged` is still fired so callers can\n * observe changes without owning the state.\n *\n * Has no effect when inside a pi/form (form context always takes\n * precedence).\n *\n * @default false\n */\n selfManaged?: boolean;\n\n /**\n * Visual style variant of the toggle buttons.\n * - `\"default\"` — transparent background, highlights on active.\n * - `\"outline\"` — bordered buttons, grouped or spaced.\n *\n * @default \"default\"\n */\n variant?: \"default\" | \"outline\";\n\n /**\n * Size of each toggle button.\n * @default \"default\"\n */\n size?: \"default\" | \"sm\" | \"lg\";\n\n /**\n * Gap between toggle buttons (in Tailwind spacing units).\n * `0` = buttons are joined (no gap, rounded ends only).\n * Positive values add space between each button.\n *\n * @default 0\n */\n spacing?: number;\n\n /** When true, the entire group is disabled and non-interactive. */\n disabled?: boolean;\n\n /** Extra Tailwind / CSS classes forwarded to the root element. */\n className?: string;\n};\n\nexport type PiToggleGroupChangedEvent = {\n /** Field name, mirrors the `name` prop if provided. */\n name?: string;\n /**\n * New selected value(s).\n * - In `\"single\"` mode: a `string` (empty string when nothing selected).\n * - In `\"multiple\"` mode: an array of `string`.\n */\n value: string | string[];\n};\n\nexport type PiToggleGroupEvents = {\n onChanged: PiToggleGroupChangedEvent;\n};\n",
31
+ "type": "registry:component",
32
+ "target": "src/cards/toggleGroup/toggleGroup.types.ts"
33
+ }
34
+ ]
35
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "typography",
4
+ "type": "registry:component",
5
+ "description": "Pihanga typography card component",
6
+ "dependencies": [],
7
+ "registryDependencies": [
8
+ "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-base.json",
9
+ "https://ivcap-works.github.io/pihanga-shadcn/r/pihanga-lib-utils.json"
10
+ ],
11
+ "files": [
12
+ {
13
+ "path": "cards/typography/index.ts",
14
+ "content": "import {registerCardComponent} from \"@pihanga2/core\";\n\nimport {TypographyComponent} from \"./typography.component\";\nimport {TYPOGRAPHY_CARD} from \"./typography.types\";\n\nexport * from \"./typography.types\";\n\nregisterCardComponent({\n name: TYPOGRAPHY_CARD,\n component: TypographyComponent,\n});\n",
15
+ "type": "registry:component",
16
+ "target": "src/cards/typography/index.ts"
17
+ },
18
+ {
19
+ "path": "cards/typography/typography.component.tsx",
20
+ "content": "import * as React from \"react\";\nimport {Card, type PiCardProps} from \"@pihanga2/core\";\nimport {cn} from \"@/lib/utils\";\nimport type {TypographyLevel, TypographyProps} from \"./typography.types\";\n\n/** Maps each level to [html element, tailwind classes] */\nconst LEVEL_CONFIG: Record<\n TypographyLevel,\n [keyof React.JSX.IntrinsicElements, string]\n> = {\n h1: [\"h1\", \"scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl\"],\n h2: [\n \"h2\",\n \"scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0\",\n ],\n h3: [\"h3\", \"scroll-m-20 text-2xl font-semibold tracking-tight\"],\n h4: [\"h4\", \"scroll-m-20 text-xl font-semibold tracking-tight\"],\n p: [\"p\", \"leading-7 [&:not(:first-child)]:mt-6\"],\n blockquote: [\"blockquote\", \"mt-6 border-l-2 pl-6 italic\"],\n code: [\n \"code\",\n \"relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold\",\n ],\n lead: [\"p\", \"text-xl text-muted-foreground\"],\n large: [\"div\", \"text-lg font-semibold\"],\n small: [\"small\", \"text-sm font-medium leading-none\"],\n muted: [\"p\", \"text-sm text-muted-foreground\"],\n};\n\nexport const TypographyComponent = (\n props: PiCardProps<TypographyProps>,\n): React.ReactNode => {\n const {\n text,\n childCard,\n paragraph,\n level,\n className,\n style,\n cardName,\n _dispatch,\n _cls,\n } = props;\n\n const [el, levelClass] = level ? LEVEL_CONFIG[level] : [\"div\", \"\"];\n\n function renderChildren(): React.ReactNode {\n if (childCard) {\n return <Card cardName={childCard} parentCard={cardName} />;\n }\n if (paragraph) {\n return <>{paragraph.map((item, i) => renderParaItem(item, i))}</>;\n }\n return text;\n }\n\n function renderParaItem(\n item: string | TypographyProps,\n key: number,\n ): React.ReactNode {\n if (typeof item === \"string\") {\n return item;\n }\n if (item && typeof item === \"object\") {\n return TypographyComponent({\n ...item,\n _dispatch,\n _cls,\n cardName,\n key,\n } as PiCardProps<TypographyProps> & {key: number});\n }\n return null;\n }\n\n return React.createElement(\n el,\n {\n className: cn(levelClass, className),\n style,\n \"data-pihanga\": cardName,\n },\n renderChildren(),\n );\n};\n",
21
+ "type": "registry:component",
22
+ "target": "src/cards/typography/typography.component.tsx"
23
+ },
24
+ {
25
+ "path": "cards/typography/typography.types.ts",
26
+ "content": "import * as React from \"react\";\nimport {PiCardRef, createCardDeclaration} from \"@pihanga2/core\";\n\nexport const TYPOGRAPHY_CARD = \"shad/typography\";\n\nexport const Typography =\n createCardDeclaration<TypographyProps>(TYPOGRAPHY_CARD);\n\n/**\n * Semantic level controls both the rendered HTML element and default\n * Tailwind prose styling (following shadcn/ui typography conventions).\n */\nexport type TypographyLevel =\n | \"h1\"\n | \"h2\"\n | \"h3\"\n | \"h4\"\n | \"p\"\n | \"blockquote\"\n | \"code\"\n | \"lead\" // large muted intro paragraph\n | \"large\" // large text, semibold\n | \"small\" // small, medium-weight\n | \"muted\"; // small, muted-foreground\n\nexport type TypographyProps = {\n /** Plain text content. */\n text?: string;\n /** A child card rendered as content. */\n childCard?: PiCardRef;\n /** Inline paragraph: mix of literal strings and nested TypographyProps. */\n paragraph?: (string | TypographyProps)[];\n\n /** Semantic level — controls the HTML element and default prose styling. */\n level?: TypographyLevel;\n\n /** Additional CSS classes applied directly to the element. */\n className?: string;\n /** Inline styles applied directly to the element. */\n style?: React.CSSProperties;\n};\n",
27
+ "type": "registry:component",
28
+ "target": "src/cards/typography/typography.types.ts"
29
+ }
30
+ ]
31
+ }