@blimu/react 0.6.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.
- package/README.md +552 -0
- package/dist/_virtual/index.cjs +2 -0
- package/dist/_virtual/index.cjs.map +1 -0
- package/dist/_virtual/index.js +6 -0
- package/dist/_virtual/index.js.map +1 -0
- package/dist/_virtual/index2.cjs +2 -0
- package/dist/_virtual/index2.cjs.map +1 -0
- package/dist/_virtual/index2.js +5 -0
- package/dist/_virtual/index2.js.map +1 -0
- package/dist/_virtual/use-sync-external-store-shim.development.cjs +2 -0
- package/dist/_virtual/use-sync-external-store-shim.development.cjs.map +1 -0
- package/dist/_virtual/use-sync-external-store-shim.development.js +5 -0
- package/dist/_virtual/use-sync-external-store-shim.development.js.map +1 -0
- package/dist/_virtual/use-sync-external-store-shim.production.cjs +2 -0
- package/dist/_virtual/use-sync-external-store-shim.production.cjs.map +1 -0
- package/dist/_virtual/use-sync-external-store-shim.production.js +5 -0
- package/dist/_virtual/use-sync-external-store-shim.production.js.map +1 -0
- package/dist/client/auth.service.cjs +2 -0
- package/dist/client/auth.service.cjs.map +1 -0
- package/dist/client/auth.service.d.ts +50 -0
- package/dist/client/auth.service.d.ts.map +1 -0
- package/dist/client/auth.service.js +153 -0
- package/dist/client/auth.service.js.map +1 -0
- package/dist/client/auth.service.test-service.d.ts +39 -0
- package/dist/client/auth.service.test-service.d.ts.map +1 -0
- package/dist/client/external-store.cjs +2 -0
- package/dist/client/external-store.cjs.map +1 -0
- package/dist/client/external-store.d.ts +20 -0
- package/dist/client/external-store.d.ts.map +1 -0
- package/dist/client/external-store.js +13 -0
- package/dist/client/external-store.js.map +1 -0
- package/dist/client/runtime-client.cjs +2 -0
- package/dist/client/runtime-client.cjs.map +1 -0
- package/dist/client/runtime-client.d.ts +49 -0
- package/dist/client/runtime-client.d.ts.map +1 -0
- package/dist/client/runtime-client.js +103 -0
- package/dist/client/runtime-client.js.map +1 -0
- package/dist/components/index.d.ts +11 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/members-list.cjs +2 -0
- package/dist/components/members-list.cjs.map +1 -0
- package/dist/components/members-list.d.ts +70 -0
- package/dist/components/members-list.d.ts.map +1 -0
- package/dist/components/members-list.js +111 -0
- package/dist/components/members-list.js.map +1 -0
- package/dist/components/redirect-to-sign-in.cjs +2 -0
- package/dist/components/redirect-to-sign-in.cjs.map +1 -0
- package/dist/components/redirect-to-sign-in.d.ts +39 -0
- package/dist/components/redirect-to-sign-in.d.ts.map +1 -0
- package/dist/components/redirect-to-sign-in.js +27 -0
- package/dist/components/redirect-to-sign-in.js.map +1 -0
- package/dist/components/sign-in-button/styles.d.ts +7 -0
- package/dist/components/sign-in-button/styles.d.ts.map +1 -0
- package/dist/components/sign-in-button.cjs +2 -0
- package/dist/components/sign-in-button.cjs.map +1 -0
- package/dist/components/sign-in-button.d.ts +47 -0
- package/dist/components/sign-in-button.d.ts.map +1 -0
- package/dist/components/sign-in-button.js +33 -0
- package/dist/components/sign-in-button.js.map +1 -0
- package/dist/components/ui/avatar.cjs +2 -0
- package/dist/components/ui/avatar.cjs.map +1 -0
- package/dist/components/ui/avatar.d.ts +7 -0
- package/dist/components/ui/avatar.d.ts.map +1 -0
- package/dist/components/ui/avatar.js +43 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.d.ts +10 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.cjs +2 -0
- package/dist/components/ui/dropdown-menu.cjs.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +28 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.js +130 -0
- package/dist/components/ui/dropdown-menu.js.map +1 -0
- package/dist/components/ui/popover.d.ts +8 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/separator.d.ts +5 -0
- package/dist/components/ui/separator.d.ts.map +1 -0
- package/dist/components/user-avatar/styles.d.ts +7 -0
- package/dist/components/user-avatar/styles.d.ts.map +1 -0
- package/dist/components/user-avatar.cjs +2 -0
- package/dist/components/user-avatar.cjs.map +1 -0
- package/dist/components/user-avatar.d.ts +41 -0
- package/dist/components/user-avatar.d.ts.map +1 -0
- package/dist/components/user-avatar.js +23 -0
- package/dist/components/user-avatar.js.map +1 -0
- package/dist/components/user-button/styles.cjs +2 -0
- package/dist/components/user-button/styles.cjs.map +1 -0
- package/dist/components/user-button/styles.d.ts +17 -0
- package/dist/components/user-button/styles.d.ts.map +1 -0
- package/dist/components/user-button/styles.js +39 -0
- package/dist/components/user-button/styles.js.map +1 -0
- package/dist/components/user-button/user-button.cjs +2 -0
- package/dist/components/user-button/user-button.cjs.map +1 -0
- package/dist/components/user-button/user-button.d.ts +15 -0
- package/dist/components/user-button/user-button.d.ts.map +1 -0
- package/dist/components/user-button/user-button.js +93 -0
- package/dist/components/user-button/user-button.js.map +1 -0
- package/dist/components.cjs +2 -0
- package/dist/components.cjs.map +1 -0
- package/dist/components.js +13 -0
- package/dist/components.js.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/use-auth.cjs +2 -0
- package/dist/hooks/use-auth.cjs.map +1 -0
- package/dist/hooks/use-auth.d.ts +92 -0
- package/dist/hooks/use-auth.d.ts.map +1 -0
- package/dist/hooks/use-auth.js +41 -0
- package/dist/hooks/use-auth.js.map +1 -0
- package/dist/hooks/use-client.cjs +2 -0
- package/dist/hooks/use-client.cjs.map +1 -0
- package/dist/hooks/use-client.d.ts +27 -0
- package/dist/hooks/use-client.d.ts.map +1 -0
- package/dist/hooks/use-client.js +9 -0
- package/dist/hooks/use-client.js.map +1 -0
- package/dist/hooks/use-members.cjs +2 -0
- package/dist/hooks/use-members.cjs.map +1 -0
- package/dist/hooks/use-members.d.ts +50 -0
- package/dist/hooks/use-members.d.ts.map +1 -0
- package/dist/hooks/use-members.js +49 -0
- package/dist/hooks/use-members.js.map +1 -0
- package/dist/hooks/use-store.cjs +2 -0
- package/dist/hooks/use-store.cjs.map +1 -0
- package/dist/hooks/use-store.d.ts +24 -0
- package/dist/hooks/use-store.d.ts.map +1 -0
- package/dist/hooks/use-store.js +18 -0
- package/dist/hooks/use-store.js.map +1 -0
- package/dist/hooks.cjs +2 -0
- package/dist/hooks.cjs.map +1 -0
- package/dist/hooks.js +14 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/utils.cjs +2 -0
- package/dist/lib/utils.cjs.map +1 -0
- package/dist/lib/utils.d.ts +7 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/variants.cjs +2 -0
- package/dist/lib/variants.cjs.map +1 -0
- package/dist/lib/variants.d.ts +37 -0
- package/dist/lib/variants.d.ts.map +1 -0
- package/dist/lib/variants.js +46 -0
- package/dist/lib/variants.js.map +1 -0
- package/dist/node_modules/@floating-ui/core/dist/floating-ui.core.cjs +2 -0
- package/dist/node_modules/@floating-ui/core/dist/floating-ui.core.cjs.map +1 -0
- package/dist/node_modules/@floating-ui/core/dist/floating-ui.core.js +528 -0
- package/dist/node_modules/@floating-ui/core/dist/floating-ui.core.js.map +1 -0
- package/dist/node_modules/@floating-ui/dom/dist/floating-ui.dom.cjs +2 -0
- package/dist/node_modules/@floating-ui/dom/dist/floating-ui.dom.cjs.map +1 -0
- package/dist/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +403 -0
- package/dist/node_modules/@floating-ui/dom/dist/floating-ui.dom.js.map +1 -0
- package/dist/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.cjs +2 -0
- package/dist/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.cjs.map +1 -0
- package/dist/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js +209 -0
- package/dist/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js.map +1 -0
- package/dist/node_modules/@floating-ui/utils/dist/floating-ui.utils.cjs +2 -0
- package/dist/node_modules/@floating-ui/utils/dist/floating-ui.utils.cjs.map +1 -0
- package/dist/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.cjs +2 -0
- package/dist/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.cjs.map +1 -0
- package/dist/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js +137 -0
- package/dist/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js.map +1 -0
- package/dist/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +131 -0
- package/dist/node_modules/@floating-ui/utils/dist/floating-ui.utils.js.map +1 -0
- package/dist/node_modules/@radix-ui/primitive/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/primitive/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/primitive/dist/index.js +10 -0
- package/dist/node_modules/@radix-ui/primitive/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-arrow/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-arrow/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-arrow/dist/index.js +25 -0
- package/dist/node_modules/@radix-ui/react-arrow/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-avatar/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-avatar/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-avatar/dist/index.js +76 -0
- package/dist/node_modules/@radix-ui/react-avatar/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context/dist/index.js +56 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-context/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive/dist/index.js +33 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-primitive/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-slot/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-slot/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-slot/dist/index.js +59 -0
- package/dist/node_modules/@radix-ui/react-avatar/node_modules/@radix-ui/react-slot/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-collection/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-collection/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-collection/dist/index.js +51 -0
- package/dist/node_modules/@radix-ui/react-collection/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-compose-refs/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-compose-refs/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-compose-refs/dist/index.js +30 -0
- package/dist/node_modules/@radix-ui/react-compose-refs/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-context/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-context/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-context/dist/index.js +54 -0
- package/dist/node_modules/@radix-ui/react-context/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-direction/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-direction/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-direction/dist/index.js +11 -0
- package/dist/node_modules/@radix-ui/react-direction/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-dismissable-layer/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-dismissable-layer/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-dismissable-layer/dist/index.js +128 -0
- package/dist/node_modules/@radix-ui/react-dismissable-layer/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-dropdown-menu/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-dropdown-menu/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-dropdown-menu/dist/index.js +215 -0
- package/dist/node_modules/@radix-ui/react-dropdown-menu/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-focus-guards/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-focus-guards/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-focus-guards/dist/index.js +18 -0
- package/dist/node_modules/@radix-ui/react-focus-guards/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-focus-scope/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-focus-scope/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-focus-scope/dist/index.js +137 -0
- package/dist/node_modules/@radix-ui/react-focus-scope/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-id/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-id/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-id/dist/index.js +14 -0
- package/dist/node_modules/@radix-ui/react-id/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-menu/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-menu/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-menu/dist/index.js +609 -0
- package/dist/node_modules/@radix-ui/react-menu/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-popper/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-popper/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-popper/dist/index.js +220 -0
- package/dist/node_modules/@radix-ui/react-popper/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-portal/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-portal/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-portal/dist/index.js +16 -0
- package/dist/node_modules/@radix-ui/react-portal/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-presence/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-presence/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-presence/dist/index.js +71 -0
- package/dist/node_modules/@radix-ui/react-presence/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-primitive/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-primitive/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-primitive/dist/index.js +37 -0
- package/dist/node_modules/@radix-ui/react-primitive/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-roving-focus/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-roving-focus/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-roving-focus/dist/index.js +184 -0
- package/dist/node_modules/@radix-ui/react-roving-focus/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-slot/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-slot/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-slot/dist/index.js +50 -0
- package/dist/node_modules/@radix-ui/react-slot/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-callback-ref/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-use-callback-ref/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-callback-ref/dist/index.js +11 -0
- package/dist/node_modules/@radix-ui/react-use-callback-ref/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-controllable-state/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-use-controllable-state/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-controllable-state/dist/index.js +53 -0
- package/dist/node_modules/@radix-ui/react-use-controllable-state/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-escape-keydown/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-use-escape-keydown/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-escape-keydown/dist/index.js +15 -0
- package/dist/node_modules/@radix-ui/react-use-escape-keydown/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-is-hydrated/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-use-is-hydrated/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-is-hydrated/dist/index.js +16 -0
- package/dist/node_modules/@radix-ui/react-use-is-hydrated/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-layout-effect/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-use-layout-effect/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-layout-effect/dist/index.js +7 -0
- package/dist/node_modules/@radix-ui/react-use-layout-effect/dist/index.js.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-size/dist/index.cjs +2 -0
- package/dist/node_modules/@radix-ui/react-use-size/dist/index.cjs.map +1 -0
- package/dist/node_modules/@radix-ui/react-use-size/dist/index.js +28 -0
- package/dist/node_modules/@radix-ui/react-use-size/dist/index.js.map +1 -0
- package/dist/node_modules/aria-hidden/dist/es2015/index.cjs +2 -0
- package/dist/node_modules/aria-hidden/dist/es2015/index.cjs.map +1 -0
- package/dist/node_modules/aria-hidden/dist/es2015/index.js +53 -0
- package/dist/node_modules/aria-hidden/dist/es2015/index.js.map +1 -0
- package/dist/node_modules/class-variance-authority/dist/index.cjs +2 -0
- package/dist/node_modules/class-variance-authority/dist/index.cjs.map +1 -0
- package/dist/node_modules/class-variance-authority/dist/index.js +36 -0
- package/dist/node_modules/class-variance-authority/dist/index.js.map +1 -0
- package/dist/node_modules/clsx/dist/clsx.cjs +2 -0
- package/dist/node_modules/clsx/dist/clsx.cjs.map +1 -0
- package/dist/node_modules/clsx/dist/clsx.js +18 -0
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/get-nonce/dist/es2015/index.cjs +2 -0
- package/dist/node_modules/get-nonce/dist/es2015/index.cjs.map +1 -0
- package/dist/node_modules/get-nonce/dist/es2015/index.js +8 -0
- package/dist/node_modules/get-nonce/dist/es2015/index.js.map +1 -0
- package/dist/node_modules/js-cookie/dist/js.cookie.cjs +2 -0
- package/dist/node_modules/js-cookie/dist/js.cookie.cjs.map +1 -0
- package/dist/node_modules/js-cookie/dist/js.cookie.js +74 -0
- package/dist/node_modules/js-cookie/dist/js.cookie.js.map +1 -0
- package/dist/node_modules/jwt-decode/build/esm/index.cjs +2 -0
- package/dist/node_modules/jwt-decode/build/esm/index.cjs.map +1 -0
- package/dist/node_modules/jwt-decode/build/esm/index.js +53 -0
- package/dist/node_modules/jwt-decode/build/esm/index.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/Icon.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/Icon.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/Icon.js +36 -0
- package/dist/node_modules/lucide-react/dist/esm/Icon.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/createLucideIcon.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/createLucideIcon.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/createLucideIcon.js +22 -0
- package/dist/node_modules/lucide-react/dist/esm/createLucideIcon.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/defaultAttributes.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/defaultAttributes.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/defaultAttributes.js +15 -0
- package/dist/node_modules/lucide-react/dist/esm/defaultAttributes.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/check.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/check.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/check.js +7 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/check.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/chevron-right.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/chevron-right.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/chevron-right.js +7 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/chevron-right.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle.js +7 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/circle.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/log-out.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/log-out.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/log-out.js +11 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/log-out.js.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/shared/src/utils.cjs +2 -0
- package/dist/node_modules/lucide-react/dist/esm/shared/src/utils.cjs.map +1 -0
- package/dist/node_modules/lucide-react/dist/esm/shared/src/utils.js +19 -0
- package/dist/node_modules/lucide-react/dist/esm/shared/src/utils.js.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/Combination.cjs +2 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/Combination.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/Combination.js +12 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/Combination.js.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/SideEffect.cjs +5 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/SideEffect.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/SideEffect.js +116 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/SideEffect.js.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/UI.cjs +2 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/UI.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/UI.js +32 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/UI.js.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/aggresiveCapture.cjs +2 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/aggresiveCapture.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/aggresiveCapture.js +17 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/aggresiveCapture.js.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/handleScroll.cjs +2 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/handleScroll.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/handleScroll.js +69 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/handleScroll.js.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/medium.cjs +2 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/medium.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/medium.js +6 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/medium.js.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/sidecar.cjs +2 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/sidecar.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/sidecar.js +8 -0
- package/dist/node_modules/react-remove-scroll/dist/es2015/sidecar.js.map +1 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/component.cjs +39 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/component.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/component.js +72 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/component.js.map +1 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/constants.cjs +2 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/constants.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/constants.js +8 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/constants.js.map +1 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/utils.cjs +2 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/utils.cjs.map +1 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/utils.js +26 -0
- package/dist/node_modules/react-remove-scroll-bar/dist/es2015/utils.js.map +1 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/component.cjs +2 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/component.cjs.map +1 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/component.js +12 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/component.js.map +1 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/hook.cjs +2 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/hook.cjs.map +1 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/hook.js +16 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/hook.js.map +1 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/singleton.cjs +2 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/singleton.cjs.map +1 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/singleton.js +31 -0
- package/dist/node_modules/react-style-singleton/dist/es2015/singleton.js.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.cjs +2 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.cjs.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +2766 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/dist/node_modules/tailwindcss/dist/plugin.cjs +2 -0
- package/dist/node_modules/tailwindcss/dist/plugin.cjs.map +1 -0
- package/dist/node_modules/tailwindcss/dist/plugin.js +14 -0
- package/dist/node_modules/tailwindcss/dist/plugin.js.map +1 -0
- package/dist/node_modules/tslib/tslib.es6.cjs +2 -0
- package/dist/node_modules/tslib/tslib.es6.cjs.map +1 -0
- package/dist/node_modules/tslib/tslib.es6.js +28 -0
- package/dist/node_modules/tslib/tslib.es6.js.map +1 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/assignRef.cjs +2 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/assignRef.cjs.map +1 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/assignRef.js +7 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/assignRef.js.map +1 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/useMergeRef.cjs +2 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/useMergeRef.cjs.map +1 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/useMergeRef.js +27 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/useMergeRef.js.map +1 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/useRef.cjs +2 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/useRef.cjs.map +1 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/useRef.js +26 -0
- package/dist/node_modules/use-callback-ref/dist/es2015/useRef.js.map +1 -0
- package/dist/node_modules/use-sidecar/dist/es2015/exports.cjs +2 -0
- package/dist/node_modules/use-sidecar/dist/es2015/exports.cjs.map +1 -0
- package/dist/node_modules/use-sidecar/dist/es2015/exports.js +19 -0
- package/dist/node_modules/use-sidecar/dist/es2015/exports.js.map +1 -0
- package/dist/node_modules/use-sidecar/dist/es2015/medium.cjs +2 -0
- package/dist/node_modules/use-sidecar/dist/es2015/medium.cjs.map +1 -0
- package/dist/node_modules/use-sidecar/dist/es2015/medium.js +68 -0
- package/dist/node_modules/use-sidecar/dist/es2015/medium.js.map +1 -0
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.cjs +2 -0
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.cjs.map +1 -0
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js +59 -0
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +1 -0
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.cjs +2 -0
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.cjs.map +1 -0
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js +47 -0
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +1 -0
- package/dist/node_modules/use-sync-external-store/shim/index.cjs +2 -0
- package/dist/node_modules/use-sync-external-store/shim/index.cjs.map +1 -0
- package/dist/node_modules/use-sync-external-store/shim/index.js +11 -0
- package/dist/node_modules/use-sync-external-store/shim/index.js.map +1 -0
- package/dist/providers/auth/auth.context.cjs +2 -0
- package/dist/providers/auth/auth.context.cjs.map +1 -0
- package/dist/providers/auth/auth.context.d.ts +3 -0
- package/dist/providers/auth/auth.context.d.ts.map +1 -0
- package/dist/providers/auth/auth.context.js +6 -0
- package/dist/providers/auth/auth.context.js.map +1 -0
- package/dist/providers/auth/auth.hook.cjs +2 -0
- package/dist/providers/auth/auth.hook.cjs.map +1 -0
- package/dist/providers/auth/auth.hook.d.ts +7 -0
- package/dist/providers/auth/auth.hook.d.ts.map +1 -0
- package/dist/providers/auth/auth.hook.js +12 -0
- package/dist/providers/auth/auth.hook.js.map +1 -0
- package/dist/providers/auth/auth.provider.cjs +2 -0
- package/dist/providers/auth/auth.provider.cjs.map +1 -0
- package/dist/providers/auth/auth.provider.d.ts +7 -0
- package/dist/providers/auth/auth.provider.d.ts.map +1 -0
- package/dist/providers/auth/auth.provider.js +29 -0
- package/dist/providers/auth/auth.provider.js.map +1 -0
- package/dist/providers/blimu/blimu.context.cjs +2 -0
- package/dist/providers/blimu/blimu.context.cjs.map +1 -0
- package/dist/providers/blimu/blimu.context.d.ts +27 -0
- package/dist/providers/blimu/blimu.context.d.ts.map +1 -0
- package/dist/providers/blimu/blimu.context.js +6 -0
- package/dist/providers/blimu/blimu.context.js.map +1 -0
- package/dist/providers/blimu/blimu.hook.cjs +2 -0
- package/dist/providers/blimu/blimu.hook.cjs.map +1 -0
- package/dist/providers/blimu/blimu.hook.d.ts +19 -0
- package/dist/providers/blimu/blimu.hook.d.ts.map +1 -0
- package/dist/providers/blimu/blimu.hook.js +12 -0
- package/dist/providers/blimu/blimu.hook.js.map +1 -0
- package/dist/providers/blimu/blimu.provider.cjs +2 -0
- package/dist/providers/blimu/blimu.provider.cjs.map +1 -0
- package/dist/providers/blimu/blimu.provider.d.ts +47 -0
- package/dist/providers/blimu/blimu.provider.d.ts.map +1 -0
- package/dist/providers/blimu/blimu.provider.js +67 -0
- package/dist/providers/blimu/blimu.provider.js.map +1 -0
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/theme/index.d.ts +4 -0
- package/dist/providers/theme/index.d.ts.map +1 -0
- package/dist/providers/theme/theme.context.cjs +2 -0
- package/dist/providers/theme/theme.context.cjs.map +1 -0
- package/dist/providers/theme/theme.context.d.ts +8 -0
- package/dist/providers/theme/theme.context.d.ts.map +1 -0
- package/dist/providers/theme/theme.context.js +6 -0
- package/dist/providers/theme/theme.context.js.map +1 -0
- package/dist/providers/theme/theme.hook.cjs +2 -0
- package/dist/providers/theme/theme.hook.cjs.map +1 -0
- package/dist/providers/theme/theme.hook.d.ts +18 -0
- package/dist/providers/theme/theme.hook.d.ts.map +1 -0
- package/dist/providers/theme/theme.hook.js +12 -0
- package/dist/providers/theme/theme.hook.js.map +1 -0
- package/dist/providers/theme/theme.provider.cjs +2 -0
- package/dist/providers/theme/theme.provider.cjs.map +1 -0
- package/dist/providers/theme/theme.provider.d.ts +28 -0
- package/dist/providers/theme/theme.provider.d.ts.map +1 -0
- package/dist/providers/theme/theme.provider.js +68 -0
- package/dist/providers/theme/theme.provider.js.map +1 -0
- package/dist/providers.cjs +2 -0
- package/dist/providers.cjs.map +1 -0
- package/dist/providers.js +13 -0
- package/dist/providers.js.map +1 -0
- package/dist/styles/styles.css +1351 -0
- package/dist/styles/tw-styles.css +120 -0
- package/dist/tailwind.plugin.cjs +2 -0
- package/dist/tailwind.plugin.cjs.map +1 -0
- package/dist/tailwind.plugin.d.ts +19 -0
- package/dist/tailwind.plugin.d.ts.map +1 -0
- package/dist/tailwind.plugin.js +200 -0
- package/dist/tailwind.plugin.js.map +1 -0
- package/dist/types/index.cjs +2 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.ts +128 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/publishable-key.cjs +2 -0
- package/dist/utils/publishable-key.cjs.map +1 -0
- package/dist/utils/publishable-key.d.ts +38 -0
- package/dist/utils/publishable-key.d.ts.map +1 -0
- package/dist/utils/publishable-key.js +38 -0
- package/dist/utils/publishable-key.js.map +1 -0
- package/package.json +128 -0
package/README.md
ADDED
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
# @blimu/react
|
|
2
|
+
|
|
3
|
+
React components and hooks for [Blimu](https://blimu.dev) authentication and authorization.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔐 **Drop-in Authentication Components** - Pre-built UI components like `UserButton`
|
|
8
|
+
- 🎨 **Fully Customizable** - Theme system with CSS variables and className overrides
|
|
9
|
+
- 🌓 **Dark Mode Support** - Built-in light and dark theme variants
|
|
10
|
+
- 🎯 **TypeScript First** - Complete type safety with IntelliSense support
|
|
11
|
+
- ⚡ **Tailwind CSS v4** - Modern CSS-first configuration
|
|
12
|
+
- 🪝 **React Hooks** - `useAuth`, `useUser`, and more
|
|
13
|
+
- 🧩 **Headless UI** - Built on Radix UI primitives
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @blimu/react
|
|
19
|
+
# or
|
|
20
|
+
yarn add @blimu/react
|
|
21
|
+
# or
|
|
22
|
+
pnpm add @blimu/react
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Peer Dependencies
|
|
26
|
+
|
|
27
|
+
This library requires:
|
|
28
|
+
- `react` ^18.0.0 || ^19.0.0
|
|
29
|
+
- `react-dom` ^18.0.0 || ^19.0.0
|
|
30
|
+
- `tailwindcss` ^4.0.0 (optional, but recommended)
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
### 1. Wrap your app with BlimuProvider
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { BlimuProvider } from '@blimu/react';
|
|
38
|
+
import '@blimu/react/styles';
|
|
39
|
+
|
|
40
|
+
function App() {
|
|
41
|
+
return (
|
|
42
|
+
<BlimuProvider publishableKey="pk_...">
|
|
43
|
+
<YourApp />
|
|
44
|
+
</BlimuProvider>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 2. Use authentication components
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { UserButton } from '@blimu/react';
|
|
53
|
+
|
|
54
|
+
function Header() {
|
|
55
|
+
return (
|
|
56
|
+
<header>
|
|
57
|
+
<h1>My App</h1>
|
|
58
|
+
<UserButton />
|
|
59
|
+
</header>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 3. Access authentication state
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { useAuth, useUser } from '@blimu/react';
|
|
68
|
+
|
|
69
|
+
function Dashboard() {
|
|
70
|
+
const { isAuthenticated, login, logout } = useAuth();
|
|
71
|
+
const { user } = useUser();
|
|
72
|
+
|
|
73
|
+
if (!isAuthenticated) {
|
|
74
|
+
return <button onClick={() => login()}>Sign In</button>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div>
|
|
79
|
+
<h1>Welcome, {user?.firstName}!</h1>
|
|
80
|
+
<button onClick={() => logout()}>Sign Out</button>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Styling & Customization
|
|
87
|
+
|
|
88
|
+
### Default Setup (with Tailwind CSS v4)
|
|
89
|
+
|
|
90
|
+
If you're using Tailwind CSS v4, import the stylesheet in your app:
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import '@blimu/react/styles';
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
This gives you the default Blimu theme with dark mode support.
|
|
97
|
+
|
|
98
|
+
### Theme Customization
|
|
99
|
+
|
|
100
|
+
#### Option 1: Theme Prop (Easiest)
|
|
101
|
+
|
|
102
|
+
Customize colors and border radius via the `theme` prop:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<BlimuProvider
|
|
106
|
+
publishableKey="pk_..."
|
|
107
|
+
theme={{
|
|
108
|
+
colors: {
|
|
109
|
+
primary: 'oklch(0.5 0.2 250)', // Custom blue
|
|
110
|
+
background: '#ffffff', // Hex colors work too
|
|
111
|
+
foreground: 'rgb(0, 0, 0)', // Or RGB
|
|
112
|
+
},
|
|
113
|
+
radius: 'lg', // 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | custom CSS value
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
<YourApp />
|
|
117
|
+
</BlimuProvider>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Option 2: CSS Variables (Maximum Control)
|
|
121
|
+
|
|
122
|
+
Override CSS variables in your global styles:
|
|
123
|
+
|
|
124
|
+
```css
|
|
125
|
+
/* your-app.css */
|
|
126
|
+
:root {
|
|
127
|
+
--blimu-primary: oklch(0.45 0.25 264);
|
|
128
|
+
--blimu-primary-foreground: oklch(1 0 0);
|
|
129
|
+
--blimu-radius: 0.5rem;
|
|
130
|
+
/* See full list of variables below */
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.dark {
|
|
134
|
+
--blimu-primary: oklch(0.7 0.2 264);
|
|
135
|
+
--blimu-background: oklch(0.15 0 0);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Available CSS Variables:**
|
|
140
|
+
|
|
141
|
+
```css
|
|
142
|
+
/* Colors */
|
|
143
|
+
--blimu-background
|
|
144
|
+
--blimu-foreground
|
|
145
|
+
--blimu-card
|
|
146
|
+
--blimu-card-foreground
|
|
147
|
+
--blimu-popover
|
|
148
|
+
--blimu-popover-foreground
|
|
149
|
+
--blimu-primary
|
|
150
|
+
--blimu-primary-foreground
|
|
151
|
+
--blimu-secondary
|
|
152
|
+
--blimu-secondary-foreground
|
|
153
|
+
--blimu-muted
|
|
154
|
+
--blimu-muted-foreground
|
|
155
|
+
--blimu-accent
|
|
156
|
+
--blimu-accent-foreground
|
|
157
|
+
--blimu-destructive
|
|
158
|
+
--blimu-destructive-foreground
|
|
159
|
+
--blimu-border
|
|
160
|
+
--blimu-input
|
|
161
|
+
--blimu-ring
|
|
162
|
+
|
|
163
|
+
/* Border Radius */
|
|
164
|
+
--blimu-radius
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### Option 3: className Overrides (Component Level)
|
|
168
|
+
|
|
169
|
+
Every component accepts `className` and `classes` props:
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
<UserButton
|
|
173
|
+
className="custom-user-button"
|
|
174
|
+
classes={{
|
|
175
|
+
trigger: 'hover:scale-105 transition-transform',
|
|
176
|
+
avatar: 'ring-2 ring-blue-500',
|
|
177
|
+
popover: 'shadow-2xl',
|
|
178
|
+
userName: 'font-bold',
|
|
179
|
+
}}
|
|
180
|
+
onManageAccount={() => router.push('/settings')}
|
|
181
|
+
/>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Dark Mode
|
|
185
|
+
|
|
186
|
+
Blimu components automatically support dark mode when a `.dark` class is present on any parent element:
|
|
187
|
+
|
|
188
|
+
```tsx
|
|
189
|
+
// Using next-themes
|
|
190
|
+
import { ThemeProvider } from 'next-themes';
|
|
191
|
+
|
|
192
|
+
<ThemeProvider attribute="class">
|
|
193
|
+
<BlimuProvider publishableKey="pk_...">
|
|
194
|
+
<YourApp />
|
|
195
|
+
</BlimuProvider>
|
|
196
|
+
</ThemeProvider>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Or manually:
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
<div className="dark">
|
|
203
|
+
<BlimuProvider publishableKey="pk_...">
|
|
204
|
+
<YourApp />
|
|
205
|
+
</BlimuProvider>
|
|
206
|
+
</div>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Components
|
|
210
|
+
|
|
211
|
+
### UserButton
|
|
212
|
+
|
|
213
|
+
A button that displays the current user's avatar and provides account management options.
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import { UserButton } from '@blimu/react';
|
|
217
|
+
|
|
218
|
+
<UserButton
|
|
219
|
+
className="custom-class"
|
|
220
|
+
classes={{
|
|
221
|
+
trigger: 'hover:opacity-90',
|
|
222
|
+
avatar: 'ring-2 ring-primary',
|
|
223
|
+
popover: 'shadow-xl',
|
|
224
|
+
userName: 'font-semibold',
|
|
225
|
+
manageAccountButton: 'hover:bg-accent',
|
|
226
|
+
signOutButton: 'hover:bg-destructive/10',
|
|
227
|
+
}}
|
|
228
|
+
onManageAccount={() => {
|
|
229
|
+
// Navigate to account settings
|
|
230
|
+
}}
|
|
231
|
+
/>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**Props:**
|
|
235
|
+
- `className?: string` - Custom class for the root element
|
|
236
|
+
- `classes?: object` - Object of classes for sub-elements
|
|
237
|
+
- `onManageAccount?: () => void` - Callback when "Manage account" is clicked
|
|
238
|
+
|
|
239
|
+
### RedirectToSignIn
|
|
240
|
+
|
|
241
|
+
Redirects unauthenticated users to the sign-in page.
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
import { RedirectToSignIn } from '@blimu/react';
|
|
245
|
+
|
|
246
|
+
function ProtectedPage() {
|
|
247
|
+
return (
|
|
248
|
+
<>
|
|
249
|
+
<RedirectToSignIn returnUrl="/dashboard" />
|
|
250
|
+
<Dashboard />
|
|
251
|
+
</>
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Hooks
|
|
257
|
+
|
|
258
|
+
### useAuth
|
|
259
|
+
|
|
260
|
+
Access authentication state and methods.
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
import { useAuth } from '@blimu/react';
|
|
264
|
+
|
|
265
|
+
function Component() {
|
|
266
|
+
const {
|
|
267
|
+
state, // Full auth state object
|
|
268
|
+
isAuthenticated, // Boolean
|
|
269
|
+
isLoading, // Boolean
|
|
270
|
+
login, // (returnUrl?) => void
|
|
271
|
+
logout, // () => Promise<void>
|
|
272
|
+
getToken, // (options) => Promise<string | null>
|
|
273
|
+
} = useAuth();
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### useUser
|
|
278
|
+
|
|
279
|
+
Get the current user object.
|
|
280
|
+
|
|
281
|
+
```tsx
|
|
282
|
+
import { useUser } from '@blimu/react';
|
|
283
|
+
|
|
284
|
+
function Profile() {
|
|
285
|
+
const { user } = useUser();
|
|
286
|
+
|
|
287
|
+
return (
|
|
288
|
+
<div>
|
|
289
|
+
<h1>{user?.firstName} {user?.lastName}</h1>
|
|
290
|
+
<p>{user?.email}</p>
|
|
291
|
+
</div>
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**User object:**
|
|
297
|
+
```ts
|
|
298
|
+
interface User {
|
|
299
|
+
id: string;
|
|
300
|
+
email: string;
|
|
301
|
+
firstName?: string | null;
|
|
302
|
+
lastName?: string | null;
|
|
303
|
+
emailVerified: boolean;
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### useBlimu
|
|
308
|
+
|
|
309
|
+
Access the Blimu client and configuration.
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
import { useBlimu } from '@blimu/react';
|
|
313
|
+
|
|
314
|
+
function Component() {
|
|
315
|
+
const { client, config } = useBlimu();
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## TypeScript
|
|
320
|
+
|
|
321
|
+
Full TypeScript support with exported types:
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
import type {
|
|
325
|
+
User,
|
|
326
|
+
AuthState,
|
|
327
|
+
BlimuConfig,
|
|
328
|
+
BlimuTheme,
|
|
329
|
+
BlimuThemeColors,
|
|
330
|
+
UserButtonProps,
|
|
331
|
+
} from '@blimu/react';
|
|
332
|
+
|
|
333
|
+
// Type-safe theme configuration
|
|
334
|
+
const theme: BlimuTheme = {
|
|
335
|
+
colors: {
|
|
336
|
+
primary: 'oklch(0.5 0.2 250)',
|
|
337
|
+
},
|
|
338
|
+
radius: 'lg',
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// Component props are fully typed
|
|
342
|
+
const userButtonProps: UserButtonProps = {
|
|
343
|
+
className: 'my-button',
|
|
344
|
+
onManageAccount: () => console.log('Account'),
|
|
345
|
+
};
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Framework Guides
|
|
349
|
+
|
|
350
|
+
### Next.js (App Router)
|
|
351
|
+
|
|
352
|
+
```tsx
|
|
353
|
+
// app/layout.tsx
|
|
354
|
+
import { BlimuProvider } from '@blimu/react';
|
|
355
|
+
import '@blimu/react/styles';
|
|
356
|
+
|
|
357
|
+
export default function RootLayout({ children }) {
|
|
358
|
+
return (
|
|
359
|
+
<html>
|
|
360
|
+
<body>
|
|
361
|
+
<BlimuProvider publishableKey={process.env.NEXT_PUBLIC_BLIMU_PUBLISHABLE_KEY!}>
|
|
362
|
+
{children}
|
|
363
|
+
</BlimuProvider>
|
|
364
|
+
</body>
|
|
365
|
+
</html>
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Next.js (Pages Router)
|
|
371
|
+
|
|
372
|
+
```tsx
|
|
373
|
+
// pages/_app.tsx
|
|
374
|
+
import { BlimuProvider } from '@blimu/react';
|
|
375
|
+
import '@blimu/react/styles';
|
|
376
|
+
import type { AppProps } from 'next/app';
|
|
377
|
+
|
|
378
|
+
export default function App({ Component, pageProps }: AppProps) {
|
|
379
|
+
return (
|
|
380
|
+
<BlimuProvider publishableKey={process.env.NEXT_PUBLIC_BLIMU_PUBLISHABLE_KEY!}>
|
|
381
|
+
<Component {...pageProps} />
|
|
382
|
+
</BlimuProvider>
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Vite + React
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
// main.tsx
|
|
391
|
+
import { BlimuProvider } from '@blimu/react';
|
|
392
|
+
import '@blimu/react/styles';
|
|
393
|
+
import ReactDOM from 'react-dom/client';
|
|
394
|
+
import App from './App';
|
|
395
|
+
|
|
396
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
397
|
+
<BlimuProvider publishableKey={import.meta.env.VITE_BLIMU_PUBLISHABLE_KEY}>
|
|
398
|
+
<App />
|
|
399
|
+
</BlimuProvider>
|
|
400
|
+
);
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Remix
|
|
404
|
+
|
|
405
|
+
```tsx
|
|
406
|
+
// app/root.tsx
|
|
407
|
+
import { BlimuProvider } from '@blimu/react';
|
|
408
|
+
import styles from '@blimu/react/styles';
|
|
409
|
+
|
|
410
|
+
export const links = () => [
|
|
411
|
+
{ rel: 'stylesheet', href: styles },
|
|
412
|
+
];
|
|
413
|
+
|
|
414
|
+
export default function Root() {
|
|
415
|
+
return (
|
|
416
|
+
<html>
|
|
417
|
+
<head>
|
|
418
|
+
<Links />
|
|
419
|
+
</head>
|
|
420
|
+
<body>
|
|
421
|
+
<BlimuProvider publishableKey={process.env.BLIMU_PUBLISHABLE_KEY!}>
|
|
422
|
+
<Outlet />
|
|
423
|
+
</BlimuProvider>
|
|
424
|
+
</body>
|
|
425
|
+
</html>
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
## Advanced Usage
|
|
431
|
+
|
|
432
|
+
### Protected Routes
|
|
433
|
+
|
|
434
|
+
```tsx
|
|
435
|
+
import { useAuth, RedirectToSignIn } from '@blimu/react';
|
|
436
|
+
|
|
437
|
+
function ProtectedRoute({ children }) {
|
|
438
|
+
const { isAuthenticated, isLoading } = useAuth();
|
|
439
|
+
|
|
440
|
+
if (isLoading) {
|
|
441
|
+
return <div>Loading...</div>;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (!isAuthenticated) {
|
|
445
|
+
return <RedirectToSignIn />;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return <>{children}</>;
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Getting Tokens
|
|
453
|
+
|
|
454
|
+
```tsx
|
|
455
|
+
import { useAuth } from '@blimu/react';
|
|
456
|
+
|
|
457
|
+
function ApiCall() {
|
|
458
|
+
const { getToken } = useAuth();
|
|
459
|
+
|
|
460
|
+
const fetchData = async () => {
|
|
461
|
+
const token = await getToken({ template: 'web' });
|
|
462
|
+
|
|
463
|
+
const response = await fetch('/api/data', {
|
|
464
|
+
headers: {
|
|
465
|
+
Authorization: `Bearer ${token}`,
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Custom Components
|
|
473
|
+
|
|
474
|
+
Build your own components using the hooks:
|
|
475
|
+
|
|
476
|
+
```tsx
|
|
477
|
+
import { useUser, useAuth } from '@blimu/react';
|
|
478
|
+
|
|
479
|
+
function CustomUserMenu() {
|
|
480
|
+
const { user } = useUser();
|
|
481
|
+
const { logout } = useAuth();
|
|
482
|
+
|
|
483
|
+
if (!user) return null;
|
|
484
|
+
|
|
485
|
+
return (
|
|
486
|
+
<div className="menu">
|
|
487
|
+
<img src={user.avatarUrl} alt={user.firstName} />
|
|
488
|
+
<span>{user.email}</span>
|
|
489
|
+
<button onClick={logout}>Sign Out</button>
|
|
490
|
+
</div>
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
## Examples
|
|
496
|
+
|
|
497
|
+
See the [examples directory](../../examples) for complete working examples:
|
|
498
|
+
|
|
499
|
+
- Next.js App Router
|
|
500
|
+
- Next.js Pages Router
|
|
501
|
+
- Vite + React
|
|
502
|
+
- Remix
|
|
503
|
+
- Custom styling examples
|
|
504
|
+
|
|
505
|
+
## Troubleshooting
|
|
506
|
+
|
|
507
|
+
### Tailwind classes not working
|
|
508
|
+
|
|
509
|
+
Make sure you've imported the styles:
|
|
510
|
+
|
|
511
|
+
```tsx
|
|
512
|
+
import '@blimu/react/styles';
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
If you're using Tailwind CSS v4 in your app, the Blimu components will inherit your Tailwind configuration.
|
|
516
|
+
|
|
517
|
+
### Dark mode not working
|
|
518
|
+
|
|
519
|
+
Ensure a `.dark` class is added to a parent element:
|
|
520
|
+
|
|
521
|
+
```tsx
|
|
522
|
+
<div className="dark">
|
|
523
|
+
<BlimuProvider>...</BlimuProvider>
|
|
524
|
+
</div>
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### TypeScript errors
|
|
528
|
+
|
|
529
|
+
Make sure `@blimu/react` is installed and your `tsconfig.json` has:
|
|
530
|
+
|
|
531
|
+
```json
|
|
532
|
+
{
|
|
533
|
+
"compilerOptions": {
|
|
534
|
+
"moduleResolution": "bundler",
|
|
535
|
+
"jsx": "react-jsx"
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
## API Reference
|
|
541
|
+
|
|
542
|
+
Full API documentation available at [docs.blimu.dev](https://docs.blimu.dev)
|
|
543
|
+
|
|
544
|
+
## License
|
|
545
|
+
|
|
546
|
+
MIT
|
|
547
|
+
|
|
548
|
+
## Support
|
|
549
|
+
|
|
550
|
+
- Documentation: [docs.blimu.dev](https://docs.blimu.dev)
|
|
551
|
+
- Issues: [GitHub Issues](https://github.com/blimu/blimu/issues)
|
|
552
|
+
- Discord: [Join our community](https://discord.gg/blimu)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index2.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index2.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-sync-external-store-shim.development.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-sync-external-store-shim.development.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-sync-external-store-shim.production.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-sync-external-store-shim.production.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("@blimu/client"),o=require("../node_modules/js-cookie/dist/js.cookie.cjs"),A=require("../node_modules/jwt-decode/build/esm/index.cjs"),a="__bli_session",d="__lh_jwt",u="__lh_jwt",S=10,_=1e3,m=t=>Math.floor(t*_),O=t=>Math.floor(t/_),C=()=>O(Date.now()),T=t=>m(t),b=(t,e)=>{const s=T(t),r=m(e),n=Date.now();return Math.max(s-r-n,0)},c=(t,e)=>{const s=C();return t-e<s};class P{constructor(e,s,r,n,l){this.isLive=e,this.client=s,this.store=r,this.pendingRefresher=null,this.refreshPromise=null,this.refreshingSignals=new Set,this.refreshingSignalAbortController=null,this.localClient=new E.Blimu({baseURL:n,credentials:"include",headers:{"x-blimu-publishable-key":l}}),this.handleRequestError=this.handleRequestError.bind(this)}setCookie(e,s,r={}){const n={secure:this.isLive,sameSite:"lax",path:"/"};r.maxAge!==void 0&&(n.expires=r.maxAge/(1440*60)),o.set(e,s,n)}getSessionPayload(){const e=o.get(a);return e?A.jwtDecode(e):null}async getSessionToken(){const e=this.getSessionPayload();if(e)return this.refreshPromise?(await this.refreshPromise,o.get(a)):(c(e.exp,0)&&await this.refreshSession(),o.get(a))}async handleRequestError(e){return e instanceof E.BlimuError&&[401,500].includes(e.status)?(o.remove(a),o.remove(u),{error:e.message,user:null}):e instanceof DOMException?{error:e.message,user:null}:e instanceof Error?{error:e.message,user:null}:{error:"unknown error",user:null}}async initialize({signal:e}={}){const s=new URL(window.location.href),r=s.searchParams.get(d)??void 0;if(r&&(s.searchParams.delete(d),window.history.replaceState({},"",s.toString())),r&&this.setCookie(u,r,{maxAge:720*60*60}),o.get(u)&&!o.get(a)){const i=await this.refreshSession({signal:e}).catch(this.handleRequestError);if("error"in i)return i}const l=this.getSessionPayload();if(!l)return{error:null,user:null};if(c(l.exp,S)){const i=await this.refreshSession().catch(this.handleRequestError);if("error"in i)return i}const h=await this.client.auth.getSession().catch(this.handleRequestError);return"error"in h?h:{error:null,user:h.user}}scheduleRefresh(){const e=new AbortController;let s=!0,r=null;const n=()=>{s=!0,this.pendingRefresher&&(this.pendingRefresher(),this.pendingRefresher=null)},l=()=>{s=!1};window.addEventListener("online",n),window.addEventListener("offline",l);const h=()=>{r!==null&&(window.clearTimeout(r),r=null);const i=this.getSessionPayload();if(!i||c(i.exp,0))return;const g=b(i.exp,S);if(g<0)return;const w=async()=>{if(r=null,!s){this.pendingRefresher=w;return}const f=await this.refreshSession({signal:e.signal});if("error"in f){if(f.error==="aborted")return;this.store.setState({status:"error",user:null,error:f.error});return}else h()};r=window.setTimeout(w,g)};return h(),()=>{r&&window.clearTimeout(r),e.abort(),window.removeEventListener("online",n),window.removeEventListener("offline",l)}}async refreshSession({signal:e}={}){if(e&&(this.refreshingSignals.add(e),e.addEventListener("abort",()=>{this.refreshingSignals.delete(e),this.refreshingSignals.size===0&&this.refreshingSignalAbortController?.abort()})),this.refreshPromise)return this.refreshPromise;this.refreshingSignalAbortController=new AbortController,this.refreshingSignalAbortController.signal.addEventListener("abort",()=>{this.refreshPromise=null,this.refreshingSignalAbortController=null,this.refreshingSignals.clear()});const s=o.get(u);this.refreshPromise=this.localClient.auth.refresh({__lh_jwt:s},{signal:this.refreshingSignalAbortController.signal}).then(r=>(r.sessionToken&&this.setCookie(a,r.sessionToken,{maxAge:720*60*60}),r)).catch(this.handleRequestError);try{return await this.refreshPromise}finally{this.refreshPromise=null,this.refreshingSignalAbortController=null,this.refreshingSignals.clear()}}}exports.AuthSessionService=P;exports.LOCALHOST_JWT_COOKIE_NAME=u;exports.LOCALHOST_JWT_URL_PARAM_NAME=d;exports.SESSION_COOKIE_NAME=a;exports.SESSION_EXPIRATION_BUFFER=S;exports.isExpiredIn=c;
|
|
2
|
+
//# sourceMappingURL=auth.service.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.service.cjs","sources":["../../src/client/auth.service.ts"],"sourcesContent":["import { Blimu, BlimuError } from '@blimu/client';\nimport type { RefreshResponse } from '@blimu/client/schema';\nimport Cookies from 'js-cookie';\nimport { jwtDecode } from 'jwt-decode';\n\nimport type { AuthState, User } from '../types';\nimport { ExternalStore } from './external-store';\n\nexport const SESSION_COOKIE_NAME = '__bli_session';\nexport const LOCALHOST_JWT_URL_PARAM_NAME = '__lh_jwt';\nexport const LOCALHOST_JWT_COOKIE_NAME = '__lh_jwt';\nexport const SESSION_EXPIRATION_BUFFER = 10;\n\n/**\n * Time conversion utilities\n * JWT tokens use seconds (Unix timestamp), JavaScript Date uses milliseconds\n */\nconst SECONDS_TO_MS = 1000;\n\n/**\n * Convert seconds to milliseconds\n */\nconst secondsToMilliseconds = (seconds: number): number => Math.floor(seconds * SECONDS_TO_MS);\n\n/**\n * Convert milliseconds to seconds\n */\nconst millisecondsToSeconds = (ms: number): number => Math.floor(ms / SECONDS_TO_MS);\n\n/**\n * Get current time in seconds (Unix timestamp)\n */\nconst nowInSeconds = (): number => millisecondsToSeconds(Date.now());\n\n/**\n * Convert JWT expiration time (seconds) to milliseconds\n */\nconst jwtExpToMilliseconds = (exp: number): number => secondsToMilliseconds(exp);\n\n/**\n * Calculate timeout delay in milliseconds for refreshing before expiration\n * @param expirationSeconds - JWT exp claim in seconds\n * @param bufferSeconds - Buffer time in seconds before expiration\n * @returns Timeout delay in milliseconds\n */\nconst calculateTimeoutDelay = (expirationSeconds: number, bufferSeconds: number): number => {\n const expirationMS = jwtExpToMilliseconds(expirationSeconds);\n const bufferMS = secondsToMilliseconds(bufferSeconds);\n const nowMS = Date.now();\n return Math.max(expirationMS - bufferMS - nowMS, 0);\n};\n\n/**\n * Check if a JWT expiration time (in seconds) is expired or will expire within the buffer\n * @param expiration - JWT exp claim in seconds (Unix timestamp)\n * @param buffer - Buffer time in seconds before expiration to consider it expired\n * @returns true if expired or will expire within buffer\n */\nexport const isExpiredIn = (expiration: number, buffer: number): boolean => {\n const now = nowInSeconds();\n return expiration - buffer < now;\n};\n\nexport class AuthSessionService {\n private pendingRefresher: (() => void) | null = null;\n private refreshPromise: Promise<RefreshResponse | { error: string; user: null }> | null = null;\n private refreshingSignals: Set<AbortSignal> = new Set();\n private refreshingSignalAbortController: AbortController | null = null;\n // A local client that doesn't call getSessionToken() which calls refreshSession().\n private localClient: Blimu;\n\n constructor(\n private readonly isLive: boolean,\n private readonly client: Blimu,\n private readonly store: ExternalStore<AuthState>,\n baseURL: string,\n publishableKey: string,\n ) {\n this.localClient = new Blimu({\n baseURL,\n credentials: 'include',\n headers: { 'x-blimu-publishable-key': publishableKey },\n });\n this.handleRequestError = this.handleRequestError.bind(this);\n }\n\n /**\n * Set cookie with appropriate security settings based on environment\n */\n private setCookie(name: string, value: string, options: { maxAge?: number } = {}): void {\n const cookieOptions: Cookies.CookieAttributes = {\n secure: this.isLive, // true for live environments, false for localhost\n sameSite: 'lax',\n path: '/',\n };\n\n if (options.maxAge !== undefined) {\n cookieOptions.expires = options.maxAge / (24 * 60 * 60); // Convert seconds to days\n }\n\n Cookies.set(name, value, cookieOptions);\n }\n\n getSessionPayload(): {\n sub: string;\n environmentId: string;\n type: string;\n iat: number;\n exp: number;\n } | null {\n const token = Cookies.get(SESSION_COOKIE_NAME);\n\n if (!token) {\n return null;\n }\n\n const decoded = jwtDecode<{\n sub: string;\n environmentId: string;\n type: string;\n iat: number;\n exp: number;\n }>(token);\n\n return decoded;\n }\n\n async getSessionToken(): Promise<string | undefined> {\n const sessionPayload = this.getSessionPayload();\n\n if (!sessionPayload) {\n return undefined;\n }\n\n // If a refresh is already in progress, wait for it to complete\n // This prevents infinite recursion when refreshSession() calls client.auth.refresh()\n // which triggers accessToken() which calls getSessionToken()\n if (this.refreshPromise) {\n await this.refreshPromise;\n // After refresh completes, return the updated token from cookie\n return Cookies.get(SESSION_COOKIE_NAME);\n }\n\n if (isExpiredIn(sessionPayload.exp, 0)) {\n await this.refreshSession();\n }\n\n return Cookies.get(SESSION_COOKIE_NAME);\n }\n\n async handleRequestError(error: unknown): Promise<{ error: string; user: null }> {\n if (error instanceof BlimuError && [401, 500].includes(error.status)) {\n Cookies.remove(SESSION_COOKIE_NAME);\n Cookies.remove(LOCALHOST_JWT_COOKIE_NAME);\n\n return {\n error: error.message,\n user: null,\n };\n }\n\n if (error instanceof DOMException)\n return {\n error: error.message,\n user: null,\n };\n\n if (error instanceof Error) {\n return {\n error: error.message,\n user: null,\n };\n }\n\n return {\n error: 'unknown error',\n user: null,\n };\n }\n\n async initialize({ signal }: { signal?: AbortSignal } = {}): Promise<{\n error: string | null;\n user: User | null;\n }> {\n const url = new URL(window.location.href);\n const localhostJWT = url.searchParams.get(LOCALHOST_JWT_URL_PARAM_NAME) ?? undefined;\n\n // Clean up URL parameters immediately to prevent re-processing on re-renders\n if (localhostJWT) {\n url.searchParams.delete(LOCALHOST_JWT_URL_PARAM_NAME);\n window.history.replaceState({}, '', url.toString());\n }\n\n // Handle localhost JWT from URL parameter\n if (localhostJWT) {\n // Set localhost JWT cookie on customer app domain\n this.setCookie(LOCALHOST_JWT_COOKIE_NAME, localhostJWT, {\n maxAge: 30 * 24 * 60 * 60, // 30 days\n });\n }\n\n const localhostJWTCookie = Cookies.get(LOCALHOST_JWT_COOKIE_NAME);\n\n if (localhostJWTCookie && !Cookies.get(SESSION_COOKIE_NAME)) {\n const result = await this.refreshSession({ signal }).catch(this.handleRequestError);\n if ('error' in result) return result;\n }\n\n const sessionPayload = this.getSessionPayload();\n\n if (!sessionPayload) {\n return {\n error: null,\n user: null,\n };\n }\n\n if (isExpiredIn(sessionPayload.exp, SESSION_EXPIRATION_BUFFER)) {\n const result = await this.refreshSession().catch(this.handleRequestError);\n if ('error' in result) return result;\n }\n\n const result = await this.client.auth.getSession().catch(this.handleRequestError);\n if ('error' in result) return result;\n\n return {\n error: null,\n user: result.user,\n };\n }\n\n scheduleRefresh() {\n const abortController = new AbortController();\n let isOnline = true;\n let timeoutId: number | null = null;\n\n const onlineHandler = () => {\n isOnline = true;\n if (this.pendingRefresher) {\n this.pendingRefresher();\n this.pendingRefresher = null;\n }\n };\n const offlineHandler = () => {\n isOnline = false;\n };\n\n window.addEventListener('online', onlineHandler);\n window.addEventListener('offline', offlineHandler);\n\n const refresh = () => {\n // Clear any existing timeout before scheduling a new one\n // This prevents infinite loops when refresh() is called recursively\n if (timeoutId !== null) {\n window.clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n const sessionPayload = this.getSessionPayload();\n\n if (!sessionPayload || isExpiredIn(sessionPayload.exp, 0)) return;\n\n // Calculate timeout delay: refresh SESSION_EXPIRATION_BUFFER seconds before expiration\n const timeoutDelayMS = calculateTimeoutDelay(sessionPayload.exp, SESSION_EXPIRATION_BUFFER);\n\n // Prevent scheduling if timeout is negative (token already expired)\n // Allow 0ms delays to handle edge cases where we're exactly at the refresh point\n // This prevents immediate re-scheduling that could cause infinite loops\n if (timeoutDelayMS < 0) {\n return;\n }\n\n // Having this function outside timeout, allows us to call refresh immediately when back online\n const refresher = async () => {\n // Clear timeoutId since we're executing now\n timeoutId = null;\n\n if (!isOnline) {\n // Keep closure of refresh function alive\n this.pendingRefresher = refresher;\n return;\n }\n\n const result = await this.refreshSession({ signal: abortController.signal });\n\n if ('error' in result) {\n // If the refresh was aborted (e.g., due to React strict mode unmounting),\n // don't treat it as an error - just return and let the component remount handle it\n if (result.error === 'aborted') {\n return;\n }\n // For real errors, update the store\n this.store.setState({\n status: 'error',\n user: null,\n error: result.error,\n });\n return;\n } else {\n // After successful refresh, schedule the next refresh with the new token\n refresh();\n }\n };\n\n timeoutId = window.setTimeout(refresher, timeoutDelayMS);\n };\n\n refresh();\n\n return () => {\n if (timeoutId) {\n window.clearTimeout(timeoutId);\n }\n abortController.abort();\n window.removeEventListener('online', onlineHandler);\n window.removeEventListener('offline', offlineHandler);\n };\n }\n\n private async refreshSession({ signal }: { signal?: AbortSignal } = {}) {\n if (signal) {\n // Add signal to tracking set (was using .has() instead of .add() - bug fix)\n this.refreshingSignals.add(signal);\n\n signal.addEventListener('abort', () => {\n this.refreshingSignals.delete(signal);\n\n if (this.refreshingSignals.size === 0) {\n this.refreshingSignalAbortController?.abort();\n }\n });\n }\n\n if (this.refreshPromise) {\n return this.refreshPromise;\n }\n\n this.refreshingSignalAbortController = new AbortController();\n\n this.refreshingSignalAbortController.signal.addEventListener('abort', () => {\n this.refreshPromise = null;\n this.refreshingSignalAbortController = null;\n this.refreshingSignals.clear();\n });\n\n // Get localhost_jwt from cookie to send as query parameter\n const localhostJWT = Cookies.get(LOCALHOST_JWT_COOKIE_NAME);\n\n // Use local client to avoid infinite recursion. Regular client calls getSessionToken() which calls refreshSession().\n // There are hacks to avoid infinite recursion, but they are not reliable.\n // The localhost_jwt is sent as a query parameter\n // Note: Type assertion needed because the generated SDK type doesn't include 'query' in RequestInit,\n // but the underlying CoreClient.request() method does support it\n this.refreshPromise = this.localClient.auth\n .refresh(\n { __lh_jwt: localhostJWT },\n {\n signal: this.refreshingSignalAbortController.signal,\n },\n )\n .then((response) => {\n // Update cookie with new session token from response body\n // Server also sets it via Set-Cookie header on auth domain, but we set it manually on customer domain\n if (response.sessionToken) {\n this.setCookie(SESSION_COOKIE_NAME, response.sessionToken, {\n maxAge: 30 * 24 * 60 * 60, // 30 days\n });\n }\n return response;\n })\n .catch(this.handleRequestError);\n\n try {\n return await this.refreshPromise;\n } finally {\n this.refreshPromise = null;\n this.refreshingSignalAbortController = null;\n this.refreshingSignals.clear();\n }\n }\n}\n"],"names":["SESSION_COOKIE_NAME","LOCALHOST_JWT_URL_PARAM_NAME","LOCALHOST_JWT_COOKIE_NAME","SESSION_EXPIRATION_BUFFER","SECONDS_TO_MS","secondsToMilliseconds","seconds","millisecondsToSeconds","ms","nowInSeconds","jwtExpToMilliseconds","exp","calculateTimeoutDelay","expirationSeconds","bufferSeconds","expirationMS","bufferMS","nowMS","isExpiredIn","expiration","buffer","now","AuthSessionService","isLive","client","store","baseURL","publishableKey","Blimu","name","value","options","cookieOptions","Cookies","token","jwtDecode","sessionPayload","error","BlimuError","signal","url","localhostJWT","result","abortController","isOnline","timeoutId","onlineHandler","offlineHandler","refresh","timeoutDelayMS","refresher","response"],"mappings":"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"}
|