@volter/twin-clerk 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 (321) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +102 -0
  3. package/client/clerk-js-dist/167_clerk.headless_b86dff_5.127.2.js +1 -0
  4. package/client/clerk-js-dist/2172_clerk.browser_0cc2cc_5.127.2.js +1 -0
  5. package/client/clerk-js-dist/2172_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  6. package/client/clerk-js-dist/368_clerk.headless_b86dff_5.127.2.js +3 -0
  7. package/client/clerk-js-dist/377_clerk.headless_b86dff_5.127.2.js +1 -0
  8. package/client/clerk-js-dist/4170_clerk.browser_0cc2cc_5.127.2.js +1 -0
  9. package/client/clerk-js-dist/4170_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  10. package/client/clerk-js-dist/437_clerk.headless_b86dff_5.127.2.js +1 -0
  11. package/client/clerk-js-dist/5192_clerk.browser_0cc2cc_5.127.2.js +1 -0
  12. package/client/clerk-js-dist/5192_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  13. package/client/clerk-js-dist/553_clerk.headless_b86dff_5.127.2.js +1 -0
  14. package/client/clerk-js-dist/5645_clerk.browser_0cc2cc_5.127.2.js +1 -0
  15. package/client/clerk-js-dist/5645_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  16. package/client/clerk-js-dist/623_clerk.headless_b86dff_5.127.2.js +42 -0
  17. package/client/clerk-js-dist/7067_clerk.browser_0cc2cc_5.127.2.js +1 -0
  18. package/client/clerk-js-dist/7067_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  19. package/client/clerk-js-dist/7502_clerk.browser_0cc2cc_5.127.2.js +1 -0
  20. package/client/clerk-js-dist/7502_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  21. package/client/clerk-js-dist/785_clerk.headless.browser_540199_5.127.2.js +1 -0
  22. package/client/clerk-js-dist/785_clerk.headless_b86dff_5.127.2.js +1 -0
  23. package/client/clerk-js-dist/8043_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  24. package/client/clerk-js-dist/825_clerk.headless.browser_540199_5.127.2.js +1 -0
  25. package/client/clerk-js-dist/825_clerk.headless_b86dff_5.127.2.js +1 -0
  26. package/client/clerk-js-dist/890_clerk.headless_b86dff_5.127.2.js +2 -0
  27. package/client/clerk-js-dist/901_clerk.headless.browser_540199_5.127.2.js +1 -0
  28. package/client/clerk-js-dist/apiKeys_clerk.browser_0cc2cc_5.127.2.js +1 -0
  29. package/client/clerk-js-dist/apiKeys_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  30. package/client/clerk-js-dist/base-account-sdk_clerk.browser_0cc2cc_5.127.2.js +42 -0
  31. package/client/clerk-js-dist/base-account-sdk_clerk.headless.browser_540199_5.127.2.js +42 -0
  32. package/client/clerk-js-dist/base-account-sdk_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  33. package/client/clerk-js-dist/blankcaptcha_clerk.browser_0cc2cc_5.127.2.js +1 -0
  34. package/client/clerk-js-dist/blankcaptcha_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  35. package/client/clerk-js-dist/checkout_clerk.browser_0cc2cc_5.127.2.js +9 -0
  36. package/client/clerk-js-dist/checkout_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  37. package/client/clerk-js-dist/clerk.browser.js +19 -0
  38. package/client/clerk-js-dist/clerk.headless.browser.js +19 -0
  39. package/client/clerk-js-dist/clerk.headless.js +19 -0
  40. package/client/clerk-js-dist/clerk.js +809 -0
  41. package/client/clerk-js-dist/clerk.legacy.browser.js +1 -0
  42. package/client/clerk-js-dist/clerk.no-rhc.js +766 -0
  43. package/client/clerk-js-dist/coinbase-wallet-sdk_clerk.browser_0cc2cc_5.127.2.js +3 -0
  44. package/client/clerk-js-dist/coinbase-wallet-sdk_clerk.headless.browser_540199_5.127.2.js +3 -0
  45. package/client/clerk-js-dist/coinbase-wallet-sdk_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  46. package/client/clerk-js-dist/cookieSuffix_clerk.browser_0cc2cc_5.127.2.js +1 -0
  47. package/client/clerk-js-dist/cookieSuffix_clerk.headless.browser_540199_5.127.2.js +1 -0
  48. package/client/clerk-js-dist/cookieSuffix_clerk.headless_b86dff_5.127.2.js +1 -0
  49. package/client/clerk-js-dist/cookieSuffix_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  50. package/client/clerk-js-dist/copy-api-key-modal_clerk.browser_0cc2cc_5.127.2.js +1 -0
  51. package/client/clerk-js-dist/copy-api-key-modal_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  52. package/client/clerk-js-dist/createorganization_clerk.browser_0cc2cc_5.127.2.js +1 -0
  53. package/client/clerk-js-dist/createorganization_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  54. package/client/clerk-js-dist/enableOrganizationsPrompt_clerk.browser_0cc2cc_5.127.2.js +247 -0
  55. package/client/clerk-js-dist/enableOrganizationsPrompt_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  56. package/client/clerk-js-dist/framework_clerk.browser_0cc2cc_5.127.2.js +1 -0
  57. package/client/clerk-js-dist/framework_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  58. package/client/clerk-js-dist/impersonationfab_clerk.browser_0cc2cc_5.127.2.js +1 -0
  59. package/client/clerk-js-dist/impersonationfab_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  60. package/client/clerk-js-dist/keylessPrompt_clerk.browser_0cc2cc_5.127.2.js +228 -0
  61. package/client/clerk-js-dist/keylessPrompt_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  62. package/client/clerk-js-dist/oauthConsent_clerk.browser_0cc2cc_5.127.2.js +1 -0
  63. package/client/clerk-js-dist/oauthConsent_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  64. package/client/clerk-js-dist/onetap_clerk.browser_0cc2cc_5.127.2.js +1 -0
  65. package/client/clerk-js-dist/onetap_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  66. package/client/clerk-js-dist/op-api-keys-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  67. package/client/clerk-js-dist/op-api-keys-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  68. package/client/clerk-js-dist/op-billing-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  69. package/client/clerk-js-dist/op-billing-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  70. package/client/clerk-js-dist/op-plans-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  71. package/client/clerk-js-dist/op-plans-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  72. package/client/clerk-js-dist/organizationlist_clerk.browser_0cc2cc_5.127.2.js +1 -0
  73. package/client/clerk-js-dist/organizationlist_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  74. package/client/clerk-js-dist/organizationprofile_clerk.browser_0cc2cc_5.127.2.js +1 -0
  75. package/client/clerk-js-dist/organizationprofile_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  76. package/client/clerk-js-dist/organizationswitcher_clerk.browser_0cc2cc_5.127.2.js +1 -0
  77. package/client/clerk-js-dist/organizationswitcher_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  78. package/client/clerk-js-dist/payment-attempt-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  79. package/client/clerk-js-dist/payment-attempt-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  80. package/client/clerk-js-dist/planDetails_clerk.browser_0cc2cc_5.127.2.js +1 -0
  81. package/client/clerk-js-dist/planDetails_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  82. package/client/clerk-js-dist/prefetchorganizationlist_clerk.browser_0cc2cc_5.127.2.js +1 -0
  83. package/client/clerk-js-dist/prefetchorganizationlist_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  84. package/client/clerk-js-dist/pricingTable_clerk.browser_0cc2cc_5.127.2.js +1 -0
  85. package/client/clerk-js-dist/pricingTable_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  86. package/client/clerk-js-dist/query-core-vendors_clerk.browser_0cc2cc_5.127.2.js +1 -0
  87. package/client/clerk-js-dist/query-core-vendors_clerk.headless.browser_540199_5.127.2.js +1 -0
  88. package/client/clerk-js-dist/query-core-vendors_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  89. package/client/clerk-js-dist/revoke-api-key-modal_clerk.browser_0cc2cc_5.127.2.js +1 -0
  90. package/client/clerk-js-dist/revoke-api-key-modal_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  91. package/client/clerk-js-dist/sessionTasks_clerk.browser_0cc2cc_5.127.2.js +1 -0
  92. package/client/clerk-js-dist/sessionTasks_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  93. package/client/clerk-js-dist/signin_clerk.browser_0cc2cc_5.127.2.js +1 -0
  94. package/client/clerk-js-dist/signin_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  95. package/client/clerk-js-dist/signup_clerk.browser_0cc2cc_5.127.2.js +1 -0
  96. package/client/clerk-js-dist/signup_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  97. package/client/clerk-js-dist/statement-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  98. package/client/clerk-js-dist/statement-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  99. package/client/clerk-js-dist/stripe-vendors_clerk.browser_0cc2cc_5.127.2.js +1 -0
  100. package/client/clerk-js-dist/stripe-vendors_clerk.headless.browser_540199_5.127.2.js +1 -0
  101. package/client/clerk-js-dist/stripe-vendors_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  102. package/client/clerk-js-dist/subscriptionDetails_clerk.browser_0cc2cc_5.127.2.js +1 -0
  103. package/client/clerk-js-dist/subscriptionDetails_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  104. package/client/clerk-js-dist/taskChooseOrganization_clerk.browser_0cc2cc_5.127.2.js +1 -0
  105. package/client/clerk-js-dist/taskChooseOrganization_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  106. package/client/clerk-js-dist/taskResetPassword_clerk.browser_0cc2cc_5.127.2.js +1 -0
  107. package/client/clerk-js-dist/taskResetPassword_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  108. package/client/clerk-js-dist/taskSetupMFA_clerk.browser_0cc2cc_5.127.2.js +4 -0
  109. package/client/clerk-js-dist/taskSetupMFA_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  110. package/client/clerk-js-dist/ui-common_clerk.browser_0cc2cc_5.127.2.js +124 -0
  111. package/client/clerk-js-dist/ui-common_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  112. package/client/clerk-js-dist/up-api-keys-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  113. package/client/clerk-js-dist/up-api-keys-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  114. package/client/clerk-js-dist/up-billing-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  115. package/client/clerk-js-dist/up-billing-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  116. package/client/clerk-js-dist/up-plans-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  117. package/client/clerk-js-dist/up-plans-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  118. package/client/clerk-js-dist/useravatar_clerk.browser_0cc2cc_5.127.2.js +1 -0
  119. package/client/clerk-js-dist/useravatar_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  120. package/client/clerk-js-dist/userbutton_clerk.browser_0cc2cc_5.127.2.js +1 -0
  121. package/client/clerk-js-dist/userbutton_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  122. package/client/clerk-js-dist/userprofile_clerk.browser_0cc2cc_5.127.2.js +4 -0
  123. package/client/clerk-js-dist/userprofile_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  124. package/client/clerk-js-dist/userverification_clerk.browser_0cc2cc_5.127.2.js +1 -0
  125. package/client/clerk-js-dist/userverification_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  126. package/client/clerk-js-dist/vendors_clerk.browser_0cc2cc_5.127.2.js +20 -0
  127. package/client/clerk-js-dist/vendors_clerk.headless.browser_540199_5.127.2.js +1 -0
  128. package/client/clerk-js-dist/vendors_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  129. package/client/clerk-js-dist/waitlist_clerk.browser_0cc2cc_5.127.2.js +1 -0
  130. package/client/clerk-js-dist/waitlist_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  131. package/client/clerk-js-dist/web3-solana-wallet-buttons_clerk.browser_0cc2cc_5.127.2.js +143 -0
  132. package/client/clerk-js-dist/web3-solana-wallet-buttons_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  133. package/client/clerk-js-dist/zxcvbn-common_clerk.browser_0cc2cc_5.127.2.js +1 -0
  134. package/client/clerk-js-dist/zxcvbn-common_clerk.headless.browser_540199_5.127.2.js +1 -0
  135. package/client/clerk-js-dist/zxcvbn-common_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  136. package/client/clerk-js-dist/zxcvbn-ts-core_clerk.browser_0cc2cc_5.127.2.js +2 -0
  137. package/client/clerk-js-dist/zxcvbn-ts-core_clerk.headless.browser_540199_5.127.2.js +2 -0
  138. package/client/clerk-js-dist/zxcvbn-ts-core_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  139. package/client/clerk-mirror.css +72 -0
  140. package/client/clerk-mirror.tsx +204 -0
  141. package/client/clerk.browser.js +19 -0
  142. package/dist/client/clerk-js-dist/167_clerk.headless_b86dff_5.127.2.js +1 -0
  143. package/dist/client/clerk-js-dist/2172_clerk.browser_0cc2cc_5.127.2.js +1 -0
  144. package/dist/client/clerk-js-dist/2172_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  145. package/dist/client/clerk-js-dist/368_clerk.headless_b86dff_5.127.2.js +3 -0
  146. package/dist/client/clerk-js-dist/377_clerk.headless_b86dff_5.127.2.js +1 -0
  147. package/dist/client/clerk-js-dist/4170_clerk.browser_0cc2cc_5.127.2.js +1 -0
  148. package/dist/client/clerk-js-dist/4170_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  149. package/dist/client/clerk-js-dist/437_clerk.headless_b86dff_5.127.2.js +1 -0
  150. package/dist/client/clerk-js-dist/5192_clerk.browser_0cc2cc_5.127.2.js +1 -0
  151. package/dist/client/clerk-js-dist/5192_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  152. package/dist/client/clerk-js-dist/553_clerk.headless_b86dff_5.127.2.js +1 -0
  153. package/dist/client/clerk-js-dist/5645_clerk.browser_0cc2cc_5.127.2.js +1 -0
  154. package/dist/client/clerk-js-dist/5645_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  155. package/dist/client/clerk-js-dist/623_clerk.headless_b86dff_5.127.2.js +42 -0
  156. package/dist/client/clerk-js-dist/7067_clerk.browser_0cc2cc_5.127.2.js +1 -0
  157. package/dist/client/clerk-js-dist/7067_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  158. package/dist/client/clerk-js-dist/7502_clerk.browser_0cc2cc_5.127.2.js +1 -0
  159. package/dist/client/clerk-js-dist/7502_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  160. package/dist/client/clerk-js-dist/785_clerk.headless.browser_540199_5.127.2.js +1 -0
  161. package/dist/client/clerk-js-dist/785_clerk.headless_b86dff_5.127.2.js +1 -0
  162. package/dist/client/clerk-js-dist/8043_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  163. package/dist/client/clerk-js-dist/825_clerk.headless.browser_540199_5.127.2.js +1 -0
  164. package/dist/client/clerk-js-dist/825_clerk.headless_b86dff_5.127.2.js +1 -0
  165. package/dist/client/clerk-js-dist/890_clerk.headless_b86dff_5.127.2.js +2 -0
  166. package/dist/client/clerk-js-dist/901_clerk.headless.browser_540199_5.127.2.js +1 -0
  167. package/dist/client/clerk-js-dist/apiKeys_clerk.browser_0cc2cc_5.127.2.js +1 -0
  168. package/dist/client/clerk-js-dist/apiKeys_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  169. package/dist/client/clerk-js-dist/base-account-sdk_clerk.browser_0cc2cc_5.127.2.js +42 -0
  170. package/dist/client/clerk-js-dist/base-account-sdk_clerk.headless.browser_540199_5.127.2.js +42 -0
  171. package/dist/client/clerk-js-dist/base-account-sdk_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  172. package/dist/client/clerk-js-dist/blankcaptcha_clerk.browser_0cc2cc_5.127.2.js +1 -0
  173. package/dist/client/clerk-js-dist/blankcaptcha_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  174. package/dist/client/clerk-js-dist/checkout_clerk.browser_0cc2cc_5.127.2.js +9 -0
  175. package/dist/client/clerk-js-dist/checkout_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  176. package/dist/client/clerk-js-dist/clerk.browser.js +19 -0
  177. package/dist/client/clerk-js-dist/clerk.headless.browser.js +19 -0
  178. package/dist/client/clerk-js-dist/clerk.headless.js +19 -0
  179. package/dist/client/clerk-js-dist/clerk.js +809 -0
  180. package/dist/client/clerk-js-dist/clerk.legacy.browser.js +1 -0
  181. package/dist/client/clerk-js-dist/clerk.no-rhc.js +766 -0
  182. package/dist/client/clerk-js-dist/coinbase-wallet-sdk_clerk.browser_0cc2cc_5.127.2.js +3 -0
  183. package/dist/client/clerk-js-dist/coinbase-wallet-sdk_clerk.headless.browser_540199_5.127.2.js +3 -0
  184. package/dist/client/clerk-js-dist/coinbase-wallet-sdk_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  185. package/dist/client/clerk-js-dist/cookieSuffix_clerk.browser_0cc2cc_5.127.2.js +1 -0
  186. package/dist/client/clerk-js-dist/cookieSuffix_clerk.headless.browser_540199_5.127.2.js +1 -0
  187. package/dist/client/clerk-js-dist/cookieSuffix_clerk.headless_b86dff_5.127.2.js +1 -0
  188. package/dist/client/clerk-js-dist/cookieSuffix_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  189. package/dist/client/clerk-js-dist/copy-api-key-modal_clerk.browser_0cc2cc_5.127.2.js +1 -0
  190. package/dist/client/clerk-js-dist/copy-api-key-modal_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  191. package/dist/client/clerk-js-dist/createorganization_clerk.browser_0cc2cc_5.127.2.js +1 -0
  192. package/dist/client/clerk-js-dist/createorganization_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  193. package/dist/client/clerk-js-dist/enableOrganizationsPrompt_clerk.browser_0cc2cc_5.127.2.js +247 -0
  194. package/dist/client/clerk-js-dist/enableOrganizationsPrompt_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  195. package/dist/client/clerk-js-dist/framework_clerk.browser_0cc2cc_5.127.2.js +1 -0
  196. package/dist/client/clerk-js-dist/framework_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  197. package/dist/client/clerk-js-dist/impersonationfab_clerk.browser_0cc2cc_5.127.2.js +1 -0
  198. package/dist/client/clerk-js-dist/impersonationfab_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  199. package/dist/client/clerk-js-dist/keylessPrompt_clerk.browser_0cc2cc_5.127.2.js +228 -0
  200. package/dist/client/clerk-js-dist/keylessPrompt_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  201. package/dist/client/clerk-js-dist/oauthConsent_clerk.browser_0cc2cc_5.127.2.js +1 -0
  202. package/dist/client/clerk-js-dist/oauthConsent_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  203. package/dist/client/clerk-js-dist/onetap_clerk.browser_0cc2cc_5.127.2.js +1 -0
  204. package/dist/client/clerk-js-dist/onetap_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  205. package/dist/client/clerk-js-dist/op-api-keys-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  206. package/dist/client/clerk-js-dist/op-api-keys-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  207. package/dist/client/clerk-js-dist/op-billing-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  208. package/dist/client/clerk-js-dist/op-billing-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  209. package/dist/client/clerk-js-dist/op-plans-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  210. package/dist/client/clerk-js-dist/op-plans-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  211. package/dist/client/clerk-js-dist/organizationlist_clerk.browser_0cc2cc_5.127.2.js +1 -0
  212. package/dist/client/clerk-js-dist/organizationlist_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  213. package/dist/client/clerk-js-dist/organizationprofile_clerk.browser_0cc2cc_5.127.2.js +1 -0
  214. package/dist/client/clerk-js-dist/organizationprofile_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  215. package/dist/client/clerk-js-dist/organizationswitcher_clerk.browser_0cc2cc_5.127.2.js +1 -0
  216. package/dist/client/clerk-js-dist/organizationswitcher_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  217. package/dist/client/clerk-js-dist/payment-attempt-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  218. package/dist/client/clerk-js-dist/payment-attempt-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  219. package/dist/client/clerk-js-dist/planDetails_clerk.browser_0cc2cc_5.127.2.js +1 -0
  220. package/dist/client/clerk-js-dist/planDetails_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  221. package/dist/client/clerk-js-dist/prefetchorganizationlist_clerk.browser_0cc2cc_5.127.2.js +1 -0
  222. package/dist/client/clerk-js-dist/prefetchorganizationlist_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  223. package/dist/client/clerk-js-dist/pricingTable_clerk.browser_0cc2cc_5.127.2.js +1 -0
  224. package/dist/client/clerk-js-dist/pricingTable_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  225. package/dist/client/clerk-js-dist/query-core-vendors_clerk.browser_0cc2cc_5.127.2.js +1 -0
  226. package/dist/client/clerk-js-dist/query-core-vendors_clerk.headless.browser_540199_5.127.2.js +1 -0
  227. package/dist/client/clerk-js-dist/query-core-vendors_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  228. package/dist/client/clerk-js-dist/revoke-api-key-modal_clerk.browser_0cc2cc_5.127.2.js +1 -0
  229. package/dist/client/clerk-js-dist/revoke-api-key-modal_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  230. package/dist/client/clerk-js-dist/sessionTasks_clerk.browser_0cc2cc_5.127.2.js +1 -0
  231. package/dist/client/clerk-js-dist/sessionTasks_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  232. package/dist/client/clerk-js-dist/signin_clerk.browser_0cc2cc_5.127.2.js +1 -0
  233. package/dist/client/clerk-js-dist/signin_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  234. package/dist/client/clerk-js-dist/signup_clerk.browser_0cc2cc_5.127.2.js +1 -0
  235. package/dist/client/clerk-js-dist/signup_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  236. package/dist/client/clerk-js-dist/statement-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  237. package/dist/client/clerk-js-dist/statement-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  238. package/dist/client/clerk-js-dist/stripe-vendors_clerk.browser_0cc2cc_5.127.2.js +1 -0
  239. package/dist/client/clerk-js-dist/stripe-vendors_clerk.headless.browser_540199_5.127.2.js +1 -0
  240. package/dist/client/clerk-js-dist/stripe-vendors_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  241. package/dist/client/clerk-js-dist/subscriptionDetails_clerk.browser_0cc2cc_5.127.2.js +1 -0
  242. package/dist/client/clerk-js-dist/subscriptionDetails_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  243. package/dist/client/clerk-js-dist/taskChooseOrganization_clerk.browser_0cc2cc_5.127.2.js +1 -0
  244. package/dist/client/clerk-js-dist/taskChooseOrganization_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  245. package/dist/client/clerk-js-dist/taskResetPassword_clerk.browser_0cc2cc_5.127.2.js +1 -0
  246. package/dist/client/clerk-js-dist/taskResetPassword_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  247. package/dist/client/clerk-js-dist/taskSetupMFA_clerk.browser_0cc2cc_5.127.2.js +4 -0
  248. package/dist/client/clerk-js-dist/taskSetupMFA_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  249. package/dist/client/clerk-js-dist/ui-common_clerk.browser_0cc2cc_5.127.2.js +124 -0
  250. package/dist/client/clerk-js-dist/ui-common_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  251. package/dist/client/clerk-js-dist/up-api-keys-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  252. package/dist/client/clerk-js-dist/up-api-keys-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  253. package/dist/client/clerk-js-dist/up-billing-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  254. package/dist/client/clerk-js-dist/up-billing-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  255. package/dist/client/clerk-js-dist/up-plans-page_clerk.browser_0cc2cc_5.127.2.js +1 -0
  256. package/dist/client/clerk-js-dist/up-plans-page_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  257. package/dist/client/clerk-js-dist/useravatar_clerk.browser_0cc2cc_5.127.2.js +1 -0
  258. package/dist/client/clerk-js-dist/useravatar_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  259. package/dist/client/clerk-js-dist/userbutton_clerk.browser_0cc2cc_5.127.2.js +1 -0
  260. package/dist/client/clerk-js-dist/userbutton_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  261. package/dist/client/clerk-js-dist/userprofile_clerk.browser_0cc2cc_5.127.2.js +4 -0
  262. package/dist/client/clerk-js-dist/userprofile_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  263. package/dist/client/clerk-js-dist/userverification_clerk.browser_0cc2cc_5.127.2.js +1 -0
  264. package/dist/client/clerk-js-dist/userverification_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  265. package/dist/client/clerk-js-dist/vendors_clerk.browser_0cc2cc_5.127.2.js +20 -0
  266. package/dist/client/clerk-js-dist/vendors_clerk.headless.browser_540199_5.127.2.js +1 -0
  267. package/dist/client/clerk-js-dist/vendors_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  268. package/dist/client/clerk-js-dist/waitlist_clerk.browser_0cc2cc_5.127.2.js +1 -0
  269. package/dist/client/clerk-js-dist/waitlist_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  270. package/dist/client/clerk-js-dist/web3-solana-wallet-buttons_clerk.browser_0cc2cc_5.127.2.js +143 -0
  271. package/dist/client/clerk-js-dist/web3-solana-wallet-buttons_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  272. package/dist/client/clerk-js-dist/zxcvbn-common_clerk.browser_0cc2cc_5.127.2.js +1 -0
  273. package/dist/client/clerk-js-dist/zxcvbn-common_clerk.headless.browser_540199_5.127.2.js +1 -0
  274. package/dist/client/clerk-js-dist/zxcvbn-common_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  275. package/dist/client/clerk-js-dist/zxcvbn-ts-core_clerk.browser_0cc2cc_5.127.2.js +2 -0
  276. package/dist/client/clerk-js-dist/zxcvbn-ts-core_clerk.headless.browser_540199_5.127.2.js +2 -0
  277. package/dist/client/clerk-js-dist/zxcvbn-ts-core_clerk.legacy.browser_6070dd_5.127.2.js +1 -0
  278. package/dist/client/clerk-mirror.bundle.js +321 -0
  279. package/dist/client/clerk-mirror.css +72 -0
  280. package/dist/client/clerk-mirror.d.ts +33 -0
  281. package/dist/client/clerk-mirror.js +143 -0
  282. package/dist/client/clerk-mirror.tsx +204 -0
  283. package/dist/client/clerk.browser.js +19 -0
  284. package/dist/src/clerk-capabilities.d.ts +4 -0
  285. package/dist/src/clerk-capabilities.js +1132 -0
  286. package/dist/src/clerk-conformance.d.ts +32 -0
  287. package/dist/src/clerk-conformance.js +158 -0
  288. package/dist/src/clerk-connector.d.ts +170 -0
  289. package/dist/src/clerk-connector.js +223 -0
  290. package/dist/src/clerk-events.d.ts +55 -0
  291. package/dist/src/clerk-events.js +146 -0
  292. package/dist/src/clerk-fapi.d.ts +19 -0
  293. package/dist/src/clerk-fapi.js +665 -0
  294. package/dist/src/clerk-jwt.d.ts +109 -0
  295. package/dist/src/clerk-jwt.js +230 -0
  296. package/dist/src/clerk-mirror-ui.d.ts +34 -0
  297. package/dist/src/clerk-mirror-ui.js +160 -0
  298. package/dist/src/clerk-server.d.ts +35 -0
  299. package/dist/src/clerk-server.js +172 -0
  300. package/dist/src/clerk-twin.d.ts +28 -0
  301. package/dist/src/clerk-twin.js +1658 -0
  302. package/dist/src/cli.d.ts +2 -0
  303. package/dist/src/cli.js +35 -0
  304. package/dist/src/index.d.ts +12 -0
  305. package/dist/src/index.js +56 -0
  306. package/dist/test-fixtures/clerk-openapi-operations.SOURCE.md +16 -0
  307. package/dist/test-fixtures/clerk-openapi-operations.json +1989 -0
  308. package/package.json +76 -0
  309. package/src/clerk-capabilities.ts +1246 -0
  310. package/src/clerk-conformance.ts +172 -0
  311. package/src/clerk-connector.ts +268 -0
  312. package/src/clerk-events.ts +166 -0
  313. package/src/clerk-fapi.ts +673 -0
  314. package/src/clerk-jwt.ts +256 -0
  315. package/src/clerk-mirror-ui.ts +165 -0
  316. package/src/clerk-server.ts +175 -0
  317. package/src/clerk-twin.ts +1580 -0
  318. package/src/cli.ts +33 -0
  319. package/src/index.ts +94 -0
  320. package/test-fixtures/clerk-openapi-operations.SOURCE.md +16 -0
  321. package/test-fixtures/clerk-openapi-operations.json +1989 -0
@@ -0,0 +1,72 @@
1
+ :root {
2
+ --bg: #0b0b0f;
3
+ --panel: #15151c;
4
+ --panel-2: #1c1c26;
5
+ --border: #2a2a36;
6
+ --text: #e7e7ee;
7
+ --muted: #9a9aab;
8
+ --accent: #6c47ff; /* Clerk purple */
9
+ --ok: #2ecc71;
10
+ --warn: #f1c40f;
11
+ --bad: #e74c3c;
12
+ --neutral: #6b6b7b;
13
+ }
14
+ * { box-sizing: border-box; }
15
+ html, body, #root { height: 100%; margin: 0; }
16
+ body {
17
+ background: var(--bg);
18
+ color: var(--text);
19
+ font: 14px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
20
+ }
21
+ .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
22
+ .app { display: flex; flex-direction: column; height: 100%; }
23
+ .topbar {
24
+ display: flex; align-items: baseline; gap: 12px;
25
+ padding: 12px 18px; border-bottom: 1px solid var(--border); background: var(--panel);
26
+ }
27
+ .brand { font-weight: 700; color: var(--accent); font-size: 16px; }
28
+ .subtitle { color: var(--muted); font-size: 12px; }
29
+ .body { display: grid; grid-template-columns: 200px 320px 1fr; flex: 1; min-height: 0; }
30
+ .nav { border-right: 1px solid var(--border); background: var(--panel); padding: 8px; overflow: auto; }
31
+ .nav-item {
32
+ display: block; width: 100%; text-align: left; padding: 8px 10px; margin-bottom: 2px;
33
+ background: transparent; color: var(--text); border: 0; border-radius: 6px; cursor: pointer;
34
+ }
35
+ .nav-item:hover { background: var(--panel-2); }
36
+ .nav-item.active { background: var(--accent); color: #fff; }
37
+ .list { border-right: 1px solid var(--border); overflow: auto; background: var(--bg); }
38
+ .list-head { padding: 10px 14px; color: var(--muted); font-weight: 600; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--bg); }
39
+ .row {
40
+ display: block; width: 100%; text-align: left; padding: 10px 14px; border: 0;
41
+ border-bottom: 1px solid var(--border); background: transparent; color: var(--text); cursor: pointer;
42
+ }
43
+ .row:hover { background: var(--panel-2); }
44
+ .row.selected { background: var(--panel-2); border-left: 3px solid var(--accent); }
45
+ .row-title { font-weight: 600; }
46
+ .row-sub { color: var(--muted); font-size: 12px; }
47
+ .detail { overflow: auto; padding: 16px 18px; }
48
+ .detail-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
49
+ .detail-lines { margin: 0; }
50
+ .detail-line { display: grid; grid-template-columns: 220px 1fr; gap: 12px; padding: 4px 0; border-bottom: 1px solid var(--border); }
51
+ .detail-line dt { color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
52
+ .detail-line dd { margin: 0; word-break: break-word; }
53
+ .empty { padding: 16px; color: var(--muted); }
54
+ .empty.error { color: var(--bad); }
55
+ .pill {
56
+ display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11px;
57
+ text-transform: capitalize; border: 1px solid var(--border);
58
+ }
59
+ .pill.ok { color: var(--ok); border-color: var(--ok); }
60
+ .pill.warn { color: var(--warn); border-color: var(--warn); }
61
+ .pill.bad { color: var(--bad); border-color: var(--bad); }
62
+ .pill.neutral { color: var(--neutral); }
63
+
64
+ /* create-user action + impersonate action (dashboard actions, API↔UI parity) */
65
+ .create-user { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; border-bottom: 1px solid var(--border); }
66
+ .create-user-head { font-weight: 600; font-size: 12px; color: var(--muted); }
67
+ .field { padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel-2); color: inherit; font-size: 13px; }
68
+ .action-btn { padding: 6px 10px; border: 1px solid var(--accent); border-radius: 6px; background: transparent; color: var(--accent); cursor: pointer; font-size: 13px; }
69
+ .action-btn:disabled { opacity: 0.5; cursor: default; }
70
+ .create-user-msg { font-size: 11px; color: var(--muted); }
71
+ .impersonate { margin-bottom: 12px; }
72
+ .impersonate-token { font-size: 11px; color: var(--muted); margin-top: 6px; }
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import { type ClerkRow, type FlatLine } from '../src/clerk-mirror-ui.js';
3
+ export type Section = {
4
+ key: string;
5
+ label: string;
6
+ title: (r: ClerkRow) => string;
7
+ subtitle: (r: ClerkRow) => string;
8
+ };
9
+ export declare const SECTIONS: Section[];
10
+ export declare function StatusPill({ value }: {
11
+ value: any;
12
+ }): React.JSX.Element;
13
+ /** Render the flattened nested-field lines for the detail panel. */
14
+ export declare function NestedLines({ lines }: {
15
+ lines: FlatLine[];
16
+ }): React.JSX.Element;
17
+ /**
18
+ * Create-a-user action (the dashboard's "+ Create user" form). Mirrors the Backend API:
19
+ * POST /v1/users {email_address:[...], first_name, last_name}. On success it calls back so
20
+ * the list refreshes — same endpoint an app uses (API↔UI parity).
21
+ */
22
+ export declare function CreateUserForm({ onCreated }: {
23
+ onCreated: () => void;
24
+ }): React.JSX.Element;
25
+ /**
26
+ * Impersonate (sign-in-as) a user — the dashboard's "Impersonate user" action. Mirrors the
27
+ * Backend API impersonation flow: POST /v1/actor_tokens {user_id, actor:{sub}}, which mints
28
+ * a real signed token that signs in AS the target user. Shows the minted token id.
29
+ */
30
+ export declare function ImpersonateButton({ user }: {
31
+ user: ClerkRow;
32
+ }): React.JSX.Element;
33
+ export declare function App(): React.JSX.Element;
@@ -0,0 +1,143 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ // Clerk UI mirror — React/TSX client (Bun-bundled). A Clerk-dashboard-style admin view
3
+ // in the shared world UI-mirror design language: top bar + left nav + list/detail split.
4
+ // Renders by consuming the twin's own REST API (/v1/<collection>).
5
+ //
6
+ // The pure format helpers live in ../src/clerk-mirror-ui.ts so they can be unit-tested
7
+ // AND shared here (Bun tree-shakes the server-only exports out of this browser bundle).
8
+ import { useEffect, useMemo, useState } from 'react';
9
+ import { createRoot } from 'react-dom/client';
10
+ import { formatUserName, primaryEmail, userStatus, statusTone, flattenClerkValue, orgMemberCount, } from "../src/clerk-mirror-ui.js";
11
+ // WHERE THIS MIRROR LIVES. Served at a vendor root the base is '' (fetches are root-relative, as
12
+ // before); served under a path prefix with a <base> tag every read and write resolves inside that
13
+ // prefix instead of escaping it.
14
+ const WIRE_BASE = typeof document === 'undefined' || document.querySelector('base[href]') === null ? '' : new URL('.', document.baseURI).pathname.replace(/\/$/, '');
15
+ export const SECTIONS = [
16
+ { key: 'users', label: 'Users', title: (r) => formatUserName(r), subtitle: (r) => `${primaryEmail(r) || r.id} · ${userStatus(r)}` },
17
+ { key: 'sessions', label: 'Sessions', title: (r) => r.id, subtitle: (r) => `${r.status ?? ''} · ${r.user_id ?? ''}` },
18
+ { key: 'organizations', label: 'Organizations', title: (r) => r.name || r.slug || r.id, subtitle: (r) => `${orgMemberCount(r)} members · ${r.slug ?? ''}` },
19
+ { key: 'invitations', label: 'Invitations', title: (r) => r.email_address || r.id, subtitle: (r) => `${r.status ?? ''} · ${r.id}` },
20
+ { key: 'allowlist_identifiers', label: 'Allowlist', title: (r) => r.identifier || r.id, subtitle: (r) => `${r.identifier_type ?? ''} · ${r.id}` },
21
+ { key: 'blocklist_identifiers', label: 'Blocklist', title: (r) => r.identifier || r.id, subtitle: (r) => `${r.identifier_type ?? ''} · ${r.id}` },
22
+ { key: 'jwt_templates', label: 'JWT Templates', title: (r) => r.name || r.id, subtitle: (r) => `lifetime ${r.lifetime ?? '?'}s · ${r.signing_algorithm ?? 'RS256'}` },
23
+ ];
24
+ const SECTION_BY_KEY = Object.fromEntries(SECTIONS.map((s) => [s.key, s]));
25
+ export function StatusPill({ value }) {
26
+ const v = String(value ?? '');
27
+ return _jsx("span", { className: `pill ${statusTone(v)}`, children: v.replace(/_/g, ' ') || '—' });
28
+ }
29
+ /** Render the flattened nested-field lines for the detail panel. */
30
+ export function NestedLines({ lines }) {
31
+ return (_jsx("dl", { className: "detail-lines", children: lines.map((ln, i) => (_jsxs("div", { className: "detail-line", children: [_jsx("dt", { className: "mono", children: ln.key }), _jsx("dd", { className: "mono", children: ln.value })] }, `${ln.key}-${i}`))) }));
32
+ }
33
+ function useCollection(section, reloadKey = 0) {
34
+ const [rows, setRows] = useState([]);
35
+ const [loading, setLoading] = useState(true);
36
+ const [error, setError] = useState('');
37
+ useEffect(() => {
38
+ let live = true;
39
+ setLoading(true);
40
+ setError('');
41
+ fetch(`${WIRE_BASE}/v1/${section}`)
42
+ .then((r) => r.json())
43
+ .then((body) => {
44
+ if (!live)
45
+ return;
46
+ const data = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : [];
47
+ setRows(data);
48
+ setLoading(false);
49
+ })
50
+ .catch((e) => { if (live) {
51
+ setError(String(e));
52
+ setLoading(false);
53
+ } });
54
+ return () => { live = false; };
55
+ }, [section, reloadKey]);
56
+ return { rows, loading, error };
57
+ }
58
+ /**
59
+ * Create-a-user action (the dashboard's "+ Create user" form). Mirrors the Backend API:
60
+ * POST /v1/users {email_address:[...], first_name, last_name}. On success it calls back so
61
+ * the list refreshes — same endpoint an app uses (API↔UI parity).
62
+ */
63
+ export function CreateUserForm({ onCreated }) {
64
+ const [email, setEmail] = useState('');
65
+ const [firstName, setFirstName] = useState('');
66
+ const [busy, setBusy] = useState(false);
67
+ const [msg, setMsg] = useState('');
68
+ async function submit(e) {
69
+ e.preventDefault();
70
+ setBusy(true);
71
+ setMsg('');
72
+ try {
73
+ const res = await fetch(`${WIRE_BASE}/v1/users`, {
74
+ method: 'POST',
75
+ headers: { 'content-type': 'application/json' },
76
+ body: JSON.stringify({ email_address: email ? [email] : [], first_name: firstName || undefined }),
77
+ });
78
+ const body = await res.json();
79
+ if (res.ok) {
80
+ setMsg(`Created ${body.id}`);
81
+ setEmail('');
82
+ setFirstName('');
83
+ onCreated();
84
+ }
85
+ else
86
+ setMsg(body?.errors?.[0]?.message ?? 'Create failed');
87
+ }
88
+ catch (err) {
89
+ setMsg(String(err));
90
+ }
91
+ finally {
92
+ setBusy(false);
93
+ }
94
+ }
95
+ return (_jsxs("form", { className: "create-user", onSubmit: submit, children: [_jsx("div", { className: "create-user-head", children: "Create user" }), _jsx("input", { className: "field", placeholder: "email address", value: email, onChange: (e) => setEmail(e.target.value) }), _jsx("input", { className: "field", placeholder: "first name", value: firstName, onChange: (e) => setFirstName(e.target.value) }), _jsx("button", { className: "action-btn", type: "submit", disabled: busy, children: busy ? 'Creating…' : 'Create user' }), msg && _jsx("div", { className: "create-user-msg mono", children: msg })] }));
96
+ }
97
+ /**
98
+ * Impersonate (sign-in-as) a user — the dashboard's "Impersonate user" action. Mirrors the
99
+ * Backend API impersonation flow: POST /v1/actor_tokens {user_id, actor:{sub}}, which mints
100
+ * a real signed token that signs in AS the target user. Shows the minted token id.
101
+ */
102
+ export function ImpersonateButton({ user }) {
103
+ const [token, setToken] = useState('');
104
+ const [busy, setBusy] = useState(false);
105
+ async function impersonate() {
106
+ setBusy(true);
107
+ try {
108
+ const res = await fetch(`${WIRE_BASE}/v1/actor_tokens`, {
109
+ method: 'POST',
110
+ headers: { 'content-type': 'application/json' },
111
+ body: JSON.stringify({ user_id: user.id, actor: { sub: 'dashboard_admin' } }),
112
+ });
113
+ const body = await res.json();
114
+ setToken(res.ok ? (body.id ?? 'created') : (body?.errors?.[0]?.message ?? 'failed'));
115
+ }
116
+ catch (err) {
117
+ setToken(String(err));
118
+ }
119
+ finally {
120
+ setBusy(false);
121
+ }
122
+ }
123
+ return (_jsxs("div", { className: "impersonate", children: [_jsx("button", { className: "action-btn impersonate-btn", onClick: impersonate, disabled: busy, children: busy ? 'Signing in as…' : 'Impersonate user' }), token && _jsxs("div", { className: "impersonate-token mono", children: ["actor token: ", token] })] }));
124
+ }
125
+ export function App() {
126
+ const [section, setSection] = useState(SECTIONS[0].key);
127
+ const [selectedId, setSelectedId] = useState(null);
128
+ const [reloadKey, setReloadKey] = useState(0);
129
+ const { rows, loading, error } = useCollection(section, reloadKey);
130
+ const current = SECTION_BY_KEY[section];
131
+ const selected = useMemo(() => rows.find((r) => r.id === selectedId) ?? rows[0] ?? null, [rows, selectedId]);
132
+ const lines = useMemo(() => (selected ? flattenClerkValue(selected) : []), [selected]);
133
+ return (_jsxs("div", { className: "app", children: [_jsxs("header", { className: "topbar", children: [_jsx("span", { className: "brand", children: "Clerk twin" }), _jsx("span", { className: "subtitle", children: "local Backend API mirror \u2014 users \u00B7 sessions \u00B7 orgs \u00B7 JWT/JWKS" })] }), _jsxs("div", { className: "body", children: [_jsx("nav", { className: "nav", children: SECTIONS.map((s) => (_jsx("button", { className: `nav-item ${s.key === section ? 'active' : ''}`, onClick: () => { setSection(s.key); setSelectedId(null); }, children: s.label }, s.key))) }), _jsxs("section", { className: "list", children: [_jsxs("div", { className: "list-head", children: [current.label, !loading ? ` (${rows.length})` : ''] }), section === 'users' && _jsx(CreateUserForm, { onCreated: () => setReloadKey((k) => k + 1) }), loading && _jsx("div", { className: "empty", children: "Loading\u2026" }), error && _jsx("div", { className: "empty error", children: error }), !loading && !error && rows.length === 0 && _jsxs("div", { className: "empty", children: ["No ", current.label.toLowerCase(), " yet."] }), rows.map((r) => (_jsxs("button", { className: `row ${selected?.id === r.id ? 'selected' : ''}`, onClick: () => setSelectedId(r.id), children: [_jsx("div", { className: "row-title", children: current.title(r) }), _jsx("div", { className: "row-sub mono", children: current.subtitle(r) })] }, r.id)))] }), _jsx("aside", { className: "detail", children: selected ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "detail-head", children: [_jsx("span", { className: "mono", children: selected.id }), selected.status && _jsx(StatusPill, { value: selected.status })] }), section === 'users' && _jsx(ImpersonateButton, { user: selected }), _jsx(NestedLines, { lines: lines })] })) : (_jsx("div", { className: "empty", children: "Select a record." })) })] })] }));
134
+ }
135
+ // Browser-only mount. Guarded so the presentational components above (SECTIONS, StatusPill,
136
+ // NestedLines, CreateUserForm, ImpersonateButton, …) can be imported and renderToStaticMarkup'd
137
+ // in a DOM-less test/SSR environment (TWIN-14 verify()s) without this top-level `document`
138
+ // access throwing. The browser bundle still mounts exactly as before.
139
+ if (typeof document !== 'undefined') {
140
+ const rootEl = document.getElementById('root');
141
+ if (rootEl)
142
+ createRoot(rootEl).render(_jsx(App, {}));
143
+ }
@@ -0,0 +1,204 @@
1
+ // Clerk UI mirror — React/TSX client (Bun-bundled). A Clerk-dashboard-style admin view
2
+ // in the shared world UI-mirror design language: top bar + left nav + list/detail split.
3
+ // Renders by consuming the twin's own REST API (/v1/<collection>).
4
+ //
5
+ // The pure format helpers live in ../src/clerk-mirror-ui.ts so they can be unit-tested
6
+ // AND shared here (Bun tree-shakes the server-only exports out of this browser bundle).
7
+ import React, { useEffect, useMemo, useState } from 'react';
8
+ import { createRoot } from 'react-dom/client';
9
+ import {
10
+ formatUserName, primaryEmail, userStatus, formatClerkDate, statusTone,
11
+ flattenClerkValue, orgMemberCount, type ClerkRow, type FlatLine,
12
+ } from '../src/clerk-mirror-ui.ts';
13
+
14
+ // WHERE THIS MIRROR LIVES. Served at a vendor root the base is '' (fetches are root-relative, as
15
+ // before); served under a path prefix with a <base> tag every read and write resolves inside that
16
+ // prefix instead of escaping it.
17
+ const WIRE_BASE = typeof document === 'undefined' || document.querySelector('base[href]') === null ? '' : new URL('.', document.baseURI).pathname.replace(/\/$/, '');
18
+
19
+ export type Section = { key: string; label: string; title: (r: ClerkRow) => string; subtitle: (r: ClerkRow) => string };
20
+
21
+ export const SECTIONS: Section[] = [
22
+ { key: 'users', label: 'Users', title: (r) => formatUserName(r), subtitle: (r) => `${primaryEmail(r) || r.id} · ${userStatus(r)}` },
23
+ { key: 'sessions', label: 'Sessions', title: (r) => r.id, subtitle: (r) => `${r.status ?? ''} · ${r.user_id ?? ''}` },
24
+ { key: 'organizations', label: 'Organizations', title: (r) => r.name || r.slug || r.id, subtitle: (r) => `${orgMemberCount(r)} members · ${r.slug ?? ''}` },
25
+ { key: 'invitations', label: 'Invitations', title: (r) => r.email_address || r.id, subtitle: (r) => `${r.status ?? ''} · ${r.id}` },
26
+ { key: 'allowlist_identifiers', label: 'Allowlist', title: (r) => r.identifier || r.id, subtitle: (r) => `${r.identifier_type ?? ''} · ${r.id}` },
27
+ { key: 'blocklist_identifiers', label: 'Blocklist', title: (r) => r.identifier || r.id, subtitle: (r) => `${r.identifier_type ?? ''} · ${r.id}` },
28
+ { key: 'jwt_templates', label: 'JWT Templates', title: (r) => r.name || r.id, subtitle: (r) => `lifetime ${r.lifetime ?? '?'}s · ${r.signing_algorithm ?? 'RS256'}` },
29
+ ];
30
+
31
+ const SECTION_BY_KEY: Record<string, Section> = Object.fromEntries(SECTIONS.map((s) => [s.key, s]));
32
+
33
+ export function StatusPill({ value }: { value: any }) {
34
+ const v = String(value ?? '');
35
+ return <span className={`pill ${statusTone(v)}`}>{v.replace(/_/g, ' ') || '—'}</span>;
36
+ }
37
+
38
+ /** Render the flattened nested-field lines for the detail panel. */
39
+ export function NestedLines({ lines }: { lines: FlatLine[] }) {
40
+ return (
41
+ <dl className="detail-lines">
42
+ {lines.map((ln, i) => (
43
+ <div className="detail-line" key={`${ln.key}-${i}`}>
44
+ <dt className="mono">{ln.key}</dt>
45
+ <dd className="mono">{ln.value}</dd>
46
+ </div>
47
+ ))}
48
+ </dl>
49
+ );
50
+ }
51
+
52
+ function useCollection(section: string, reloadKey = 0): { rows: ClerkRow[]; loading: boolean; error: string } {
53
+ const [rows, setRows] = useState<ClerkRow[]>([]);
54
+ const [loading, setLoading] = useState(true);
55
+ const [error, setError] = useState('');
56
+ useEffect(() => {
57
+ let live = true;
58
+ setLoading(true);
59
+ setError('');
60
+ fetch(`${WIRE_BASE}/v1/${section}`)
61
+ .then((r) => r.json())
62
+ .then((body) => {
63
+ if (!live) return;
64
+ const data = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : [];
65
+ setRows(data);
66
+ setLoading(false);
67
+ })
68
+ .catch((e) => { if (live) { setError(String(e)); setLoading(false); } });
69
+ return () => { live = false; };
70
+ }, [section, reloadKey]);
71
+ return { rows, loading, error };
72
+ }
73
+
74
+ /**
75
+ * Create-a-user action (the dashboard's "+ Create user" form). Mirrors the Backend API:
76
+ * POST /v1/users {email_address:[...], first_name, last_name}. On success it calls back so
77
+ * the list refreshes — same endpoint an app uses (API↔UI parity).
78
+ */
79
+ export function CreateUserForm({ onCreated }: { onCreated: () => void }) {
80
+ const [email, setEmail] = useState('');
81
+ const [firstName, setFirstName] = useState('');
82
+ const [busy, setBusy] = useState(false);
83
+ const [msg, setMsg] = useState('');
84
+ async function submit(e: React.FormEvent) {
85
+ e.preventDefault();
86
+ setBusy(true);
87
+ setMsg('');
88
+ try {
89
+ const res = await fetch(`${WIRE_BASE}/v1/users`, {
90
+ method: 'POST',
91
+ headers: { 'content-type': 'application/json' },
92
+ body: JSON.stringify({ email_address: email ? [email] : [], first_name: firstName || undefined }),
93
+ });
94
+ const body = await res.json();
95
+ if (res.ok) { setMsg(`Created ${body.id}`); setEmail(''); setFirstName(''); onCreated(); }
96
+ else setMsg(body?.errors?.[0]?.message ?? 'Create failed');
97
+ } catch (err) { setMsg(String(err)); }
98
+ finally { setBusy(false); }
99
+ }
100
+ return (
101
+ <form className="create-user" onSubmit={submit}>
102
+ <div className="create-user-head">Create user</div>
103
+ <input className="field" placeholder="email address" value={email} onChange={(e) => setEmail(e.target.value)} />
104
+ <input className="field" placeholder="first name" value={firstName} onChange={(e) => setFirstName(e.target.value)} />
105
+ <button className="action-btn" type="submit" disabled={busy}>{busy ? 'Creating…' : 'Create user'}</button>
106
+ {msg && <div className="create-user-msg mono">{msg}</div>}
107
+ </form>
108
+ );
109
+ }
110
+
111
+ /**
112
+ * Impersonate (sign-in-as) a user — the dashboard's "Impersonate user" action. Mirrors the
113
+ * Backend API impersonation flow: POST /v1/actor_tokens {user_id, actor:{sub}}, which mints
114
+ * a real signed token that signs in AS the target user. Shows the minted token id.
115
+ */
116
+ export function ImpersonateButton({ user }: { user: ClerkRow }) {
117
+ const [token, setToken] = useState<string>('');
118
+ const [busy, setBusy] = useState(false);
119
+ async function impersonate() {
120
+ setBusy(true);
121
+ try {
122
+ const res = await fetch(`${WIRE_BASE}/v1/actor_tokens`, {
123
+ method: 'POST',
124
+ headers: { 'content-type': 'application/json' },
125
+ body: JSON.stringify({ user_id: user.id, actor: { sub: 'dashboard_admin' } }),
126
+ });
127
+ const body = await res.json();
128
+ setToken(res.ok ? (body.id ?? 'created') : (body?.errors?.[0]?.message ?? 'failed'));
129
+ } catch (err) { setToken(String(err)); }
130
+ finally { setBusy(false); }
131
+ }
132
+ return (
133
+ <div className="impersonate">
134
+ <button className="action-btn impersonate-btn" onClick={impersonate} disabled={busy}>
135
+ {busy ? 'Signing in as…' : 'Impersonate user'}
136
+ </button>
137
+ {token && <div className="impersonate-token mono">actor token: {token}</div>}
138
+ </div>
139
+ );
140
+ }
141
+
142
+ export function App() {
143
+ const [section, setSection] = useState<string>(SECTIONS[0]!.key);
144
+ const [selectedId, setSelectedId] = useState<string | null>(null);
145
+ const [reloadKey, setReloadKey] = useState(0);
146
+ const { rows, loading, error } = useCollection(section, reloadKey);
147
+ const current = SECTION_BY_KEY[section]!;
148
+ const selected = useMemo(() => rows.find((r) => r.id === selectedId) ?? rows[0] ?? null, [rows, selectedId]);
149
+ const lines = useMemo(() => (selected ? flattenClerkValue(selected) : []), [selected]);
150
+
151
+ return (
152
+ <div className="app">
153
+ <header className="topbar">
154
+ <span className="brand">Clerk twin</span>
155
+ <span className="subtitle">local Backend API mirror — users · sessions · orgs · JWT/JWKS</span>
156
+ </header>
157
+ <div className="body">
158
+ <nav className="nav">
159
+ {SECTIONS.map((s) => (
160
+ <button key={s.key} className={`nav-item ${s.key === section ? 'active' : ''}`} onClick={() => { setSection(s.key); setSelectedId(null); }}>
161
+ {s.label}
162
+ </button>
163
+ ))}
164
+ </nav>
165
+ <section className="list">
166
+ <div className="list-head">{current.label}{!loading ? ` (${rows.length})` : ''}</div>
167
+ {section === 'users' && <CreateUserForm onCreated={() => setReloadKey((k) => k + 1)} />}
168
+ {loading && <div className="empty">Loading…</div>}
169
+ {error && <div className="empty error">{error}</div>}
170
+ {!loading && !error && rows.length === 0 && <div className="empty">No {current.label.toLowerCase()} yet.</div>}
171
+ {rows.map((r) => (
172
+ <button key={r.id} className={`row ${selected?.id === r.id ? 'selected' : ''}`} onClick={() => setSelectedId(r.id)}>
173
+ <div className="row-title">{current.title(r)}</div>
174
+ <div className="row-sub mono">{current.subtitle(r)}</div>
175
+ </button>
176
+ ))}
177
+ </section>
178
+ <aside className="detail">
179
+ {selected ? (
180
+ <>
181
+ <div className="detail-head">
182
+ <span className="mono">{selected.id}</span>
183
+ {selected.status && <StatusPill value={selected.status} />}
184
+ </div>
185
+ {section === 'users' && <ImpersonateButton user={selected} />}
186
+ <NestedLines lines={lines} />
187
+ </>
188
+ ) : (
189
+ <div className="empty">Select a record.</div>
190
+ )}
191
+ </aside>
192
+ </div>
193
+ </div>
194
+ );
195
+ }
196
+
197
+ // Browser-only mount. Guarded so the presentational components above (SECTIONS, StatusPill,
198
+ // NestedLines, CreateUserForm, ImpersonateButton, …) can be imported and renderToStaticMarkup'd
199
+ // in a DOM-less test/SSR environment (TWIN-14 verify()s) without this top-level `document`
200
+ // access throwing. The browser bundle still mounts exactly as before.
201
+ if (typeof document !== 'undefined') {
202
+ const rootEl = document.getElementById('root');
203
+ if (rootEl) createRoot(rootEl).render(<App />);
204
+ }