├── examples ├── solidjs │ ├── .gitignore │ ├── .env.example │ ├── src │ │ ├── assets │ │ │ └── favicon.ico │ │ ├── index.tsx │ │ ├── store.ts │ │ ├── index.css │ │ ├── logo.svg │ │ ├── App.tsx │ │ ├── muiswitch.tsx │ │ └── App.module.css │ ├── CHANGELOG.md │ ├── vite.config.ts │ ├── tsconfig.json │ ├── index.html │ ├── package.json │ └── README.md ├── svelte │ ├── .npmrc │ ├── src │ │ ├── routes │ │ │ ├── +page.ts │ │ │ ├── MenuIcon.svelte │ │ │ ├── +layout.svelte │ │ │ └── ToggleButton.svelte │ │ ├── db.ts │ │ ├── app.d.ts │ │ ├── app.html │ │ └── tailwind.css │ ├── static │ │ └── favicon.png │ ├── vite.config.ts │ ├── .env.example │ ├── .gitignore │ ├── tailwind.config.cjs │ ├── .eslintignore │ ├── .prettierignore │ ├── .prettierrc │ ├── .eslintrc.cjs │ ├── tsconfig.json │ ├── svelte.config.js │ ├── README.md │ └── package.json └── react │ ├── src │ ├── vite-env.d.ts │ ├── main.tsx │ ├── MenuIcon.tsx │ ├── App.module.css │ ├── tailwind.css │ ├── ToggleButton.tsx │ └── assets │ │ └── react.svg │ ├── .env.example │ ├── tailwind.config.cjs │ ├── tsconfig.node.json │ ├── vite.config.ts │ ├── .gitignore │ ├── index.html │ ├── tsconfig.json │ ├── package.json │ └── public │ └── vite.svg ├── packages ├── solid │ ├── .gitignore │ ├── src │ │ ├── index.tsx │ │ ├── components │ │ │ ├── Auth │ │ │ │ ├── index.ts │ │ │ │ ├── interfaces │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── UpdatePassword.tsx │ │ │ │ │ ├── MagicLink.tsx │ │ │ │ │ ├── ForgottenPassword.tsx │ │ │ │ │ └── SocialAuth.tsx │ │ │ │ ├── UserContext.tsx │ │ │ │ └── ui │ │ │ │ │ └── index.tsx │ │ │ └── UI │ │ │ │ ├── index.ts │ │ │ │ ├── Divider.tsx │ │ │ │ ├── Label.tsx │ │ │ │ ├── Anchor.tsx │ │ │ │ ├── Message.tsx │ │ │ │ ├── Container.tsx │ │ │ │ ├── Input.tsx │ │ │ │ ├── Loader.tsx │ │ │ │ └── Button.tsx │ │ ├── assets │ │ │ └── favicon.ico │ │ ├── types.ts │ │ └── logo.svg │ ├── vite.config.js │ ├── tsconfig.json │ ├── .eslintrc.js │ ├── package.json │ ├── README.md │ └── CHANGELOG.md ├── svelte │ ├── .npmrc │ ├── src │ │ ├── lib │ │ │ ├── index.ts │ │ │ ├── Auth │ │ │ │ ├── index.ts │ │ │ │ ├── interfaces │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── SocialAuth.svelte │ │ │ │ │ ├── MagicLink.svelte │ │ │ │ │ ├── ForgottenPassword.svelte │ │ │ │ │ ├── UpdatePassword.svelte │ │ │ │ │ └── VerifyOtp.svelte │ │ │ │ ├── ui │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── VerifyOtp.svelte │ │ │ │ │ ├── ForgottenPassword.svelte │ │ │ │ │ ├── UpdatePassword.svelte │ │ │ │ │ ├── MagicLink.svelte │ │ │ │ │ ├── SocialAuth.svelte │ │ │ │ │ ├── SignIn.svelte │ │ │ │ │ └── SignUp.svelte │ │ │ │ └── Auth.svelte │ │ │ ├── UI │ │ │ │ ├── Divider.svelte │ │ │ │ ├── Label.svelte │ │ │ │ ├── Anchor.svelte │ │ │ │ ├── Loader.svelte │ │ │ │ ├── Message.svelte │ │ │ │ ├── Container.svelte │ │ │ │ ├── Input.svelte │ │ │ │ └── Button.svelte │ │ │ └── types.ts │ │ ├── app.d.ts │ │ └── app.html │ ├── static │ │ └── favicon.png │ ├── .gitignore │ ├── vite.config.ts │ ├── .eslintignore │ ├── .prettierignore │ ├── playwright.config.ts │ ├── .prettierrc │ ├── svelte.config.js │ ├── .eslintrc.cjs │ ├── tsconfig.json │ ├── package.json │ ├── README.md │ └── CHANGELOG.md ├── shared │ ├── src │ │ ├── localization │ │ │ ├── index.ts │ │ │ └── en.json │ │ ├── theming │ │ │ ├── index.ts │ │ │ ├── utils.ts │ │ │ ├── Types.ts │ │ │ └── Themes.ts │ │ ├── index.ts │ │ ├── constants.ts │ │ └── utils.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ ├── package.json │ └── CHANGELOG.md ├── react │ ├── src │ │ ├── index.tsx │ │ ├── components │ │ │ ├── Auth │ │ │ │ ├── index.tsx │ │ │ │ ├── interfaces │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── UpdatePassword.tsx │ │ │ │ │ ├── ForgottenPassword.tsx │ │ │ │ │ ├── MagicLink.tsx │ │ │ │ │ └── SocialAuth.tsx │ │ │ │ ├── UserContext.tsx │ │ │ │ └── ui │ │ │ │ │ └── index.tsx │ │ │ └── UI │ │ │ │ ├── index.tsx │ │ │ │ ├── Divider.tsx │ │ │ │ ├── Label.tsx │ │ │ │ ├── Anchor.tsx │ │ │ │ ├── Message.tsx │ │ │ │ ├── Container.tsx │ │ │ │ ├── Input.tsx │ │ │ │ ├── Loader.tsx │ │ │ │ └── Button.tsx │ │ └── types.ts │ ├── vite.config.d.ts │ ├── .gitignore │ ├── index.html │ ├── tsconfig.json │ ├── README.md │ ├── vite.config.ts │ └── package.json └── tsconfig │ ├── README.md │ ├── package.json │ ├── solidjs.json │ ├── react-library.json │ ├── svelte.json │ ├── base.json │ └── nextjs.json ├── pnpm-workspace.yaml ├── .prettierrc ├── .changeset ├── config.json └── README.md ├── .npmignore ├── .gitignore ├── turbo.json ├── LICENSE ├── .github └── workflows │ └── release.yml ├── development.md ├── package.json ├── localization ├── japanese │ └── ja.json ├── german │ ├── de_formal.json │ └── de_informal.json ├── spanish │ └── es.json └── french │ └── fr.json └── README.md /examples/solidjs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /examples/svelte/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /packages/solid/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /packages/svelte/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /examples/svelte/src/routes/+page.ts: -------------------------------------------------------------------------------- 1 | export const ssr = true; 2 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Auth/index'; 2 | -------------------------------------------------------------------------------- /packages/solid/src/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './components/Auth/index' 2 | -------------------------------------------------------------------------------- /examples/react/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "examples/*" 3 | - "packages/*" 4 | -------------------------------------------------------------------------------- /packages/shared/src/localization/index.ts: -------------------------------------------------------------------------------- 1 | export { default as en } from './en.json' 2 | -------------------------------------------------------------------------------- /packages/react/src/index.tsx: -------------------------------------------------------------------------------- 1 | // // GENERAL 2 | export * from './components/Auth/index.js' 3 | -------------------------------------------------------------------------------- /examples/react/.env.example: -------------------------------------------------------------------------------- 1 | VITE_SUPABASE_URL=http://localhost:54321 2 | VITE_SUPABASE_ANON_KEY= -------------------------------------------------------------------------------- /examples/solidjs/.env.example: -------------------------------------------------------------------------------- 1 | VITE_SUPABASE_URL=http://localhost:54321 2 | VITE_SUPABASE_ANON_KEY= -------------------------------------------------------------------------------- /packages/solid/src/components/Auth/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Auth } from './Auth' 2 | export * from './ui' 3 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Auth } from './Auth.svelte'; 2 | export * from './ui'; 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "printWidth": 80, 5 | "endOfLine": "auto" 6 | } 7 | -------------------------------------------------------------------------------- /packages/react/vite.config.d.ts: -------------------------------------------------------------------------------- 1 | declare const _default: import("vite").UserConfigExport; 2 | export default _default; 3 | -------------------------------------------------------------------------------- /packages/react/src/components/Auth/index.tsx: -------------------------------------------------------------------------------- 1 | export { default as Auth } from './Auth.js' 2 | export * from './ui/index.js' 3 | -------------------------------------------------------------------------------- /examples/svelte/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supabase-community/auth-ui/HEAD/examples/svelte/static/favicon.png -------------------------------------------------------------------------------- /packages/svelte/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supabase-community/auth-ui/HEAD/packages/svelte/static/favicon.png -------------------------------------------------------------------------------- /packages/solid/src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supabase-community/auth-ui/HEAD/packages/solid/src/assets/favicon.ico -------------------------------------------------------------------------------- /packages/svelte/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | -------------------------------------------------------------------------------- /examples/solidjs/src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supabase-community/auth-ui/HEAD/examples/solidjs/src/assets/favicon.ico -------------------------------------------------------------------------------- /packages/tsconfig/README.md: -------------------------------------------------------------------------------- 1 | # `tsconfig` 2 | 3 | These are base shared `tsconfig.json`s from which all other `tsconfig.json`'s inherit from. 4 | -------------------------------------------------------------------------------- /packages/shared/src/theming/index.ts: -------------------------------------------------------------------------------- 1 | export * from './defaultThemes' 2 | export * from './Themes' 3 | export * from './Types' 4 | export * from './utils' 5 | -------------------------------------------------------------------------------- /examples/solidjs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @example/solidjs 2 | 3 | ## 0.0.1 4 | 5 | ### Patch Changes 6 | 7 | - Updated dependencies [11a09a6] 8 | - @supabase/auth-ui-solid@0.1.1 9 | -------------------------------------------------------------------------------- /packages/shared/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './theming' 2 | export * from './constants' 3 | export * from './types' 4 | export * from './utils' 5 | export { en } from './localization' 6 | -------------------------------------------------------------------------------- /examples/svelte/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import { defineConfig } from 'vite'; 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()] 6 | }); 7 | -------------------------------------------------------------------------------- /examples/svelte/.env.example: -------------------------------------------------------------------------------- 1 | # Update these with your Supabase details from your project settings > API 2 | PUBLIC_SUPABASE_URL=https://your-project.supabase.co 3 | PUBLIC_SUPABASE_ANON_KEY=your-anon-key 4 | -------------------------------------------------------------------------------- /examples/svelte/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | vite.config.js.timestamp-* 10 | vite.config.ts.timestamp-* 11 | -------------------------------------------------------------------------------- /packages/shared/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tsconfig/base.json", 3 | "compilerOptions": { 4 | "resolveJsonModule": true, 5 | }, 6 | "include": ["src"], 7 | "exclude": ["node_modules"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/svelte/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | import type { UserConfig } from 'vite'; 3 | 4 | const config: UserConfig = { 5 | plugins: [sveltekit()] 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /examples/solidjs/src/index.tsx: -------------------------------------------------------------------------------- 1 | 2 | /* @refresh reload */ 3 | import { render } from 'solid-js/web'; 4 | 5 | import './index.css'; 6 | import App from './App'; 7 | 8 | render(() => , document.getElementById('root') as HTMLElement); -------------------------------------------------------------------------------- /packages/solid/src/components/UI/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Anchor' 2 | export * from './Button' 3 | export * from './Container' 4 | export * from './Divider' 5 | export * from './Input' 6 | export * from './Label' 7 | export * from './Message' -------------------------------------------------------------------------------- /packages/react/src/components/UI/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Anchor' 2 | export * from './Button' 3 | export * from './Container' 4 | export * from './Divider' 5 | export * from './Input' 6 | export * from './Label' 7 | export * from './Message' 8 | -------------------------------------------------------------------------------- /examples/svelte/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./src/**/*.{html,js,svelte,ts}'], 4 | darkMode: 'media', 5 | theme: { 6 | extend: {} 7 | }, 8 | plugins: [] 9 | }; 10 | -------------------------------------------------------------------------------- /packages/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tsconfig", 3 | "version": "0.0.0", 4 | "private": true, 5 | "main": "index.js", 6 | "files": [ 7 | "base.json", 8 | "nextjs.json", 9 | "react-library.json" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /examples/svelte/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /examples/svelte/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /packages/svelte/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /packages/svelte/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /examples/react/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./src/**/*.{html,js,jsx,tsx,ts}'], 4 | darkMode: 'media', 5 | theme: { 6 | extend: {}, 7 | }, 8 | plugins: [], 9 | } 10 | -------------------------------------------------------------------------------- /examples/react/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/solid/src/components/Auth/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MagicLink' 2 | export * from './SocialAuth' 3 | export * from './EmailAuth' 4 | export * from './ForgottenPassword' 5 | export * from './UpdatePassword' 6 | export * from './VerifyOtp' 7 | -------------------------------------------------------------------------------- /examples/svelte/src/db.ts: -------------------------------------------------------------------------------- 1 | import { createClient } from '@supabase/supabase-js'; 2 | import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public'; 3 | 4 | export const supabaseClient = createClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY); 5 | -------------------------------------------------------------------------------- /examples/react/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | server: { 8 | port: 3001, 9 | }, 10 | }) 11 | -------------------------------------------------------------------------------- /packages/react/src/components/Auth/interfaces/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './MagicLink.js' 2 | export * from './SocialAuth.js' 3 | export * from './EmailAuth.js' 4 | export * from './ForgottenPassword.js' 5 | export * from './UpdatePassword.js' 6 | export * from './VerifyOtp.js' 7 | -------------------------------------------------------------------------------- /packages/tsconfig/solidjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "extends": "./base.json", 4 | "display":"Solid Library", 5 | "compilerOptions":{ 6 | "lib":["ES6","DOM"], 7 | "module":"ESNext", 8 | "jsx":"preserve" 9 | } 10 | } -------------------------------------------------------------------------------- /packages/svelte/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import type { PlaywrightTestConfig } from '@playwright/test'; 2 | 3 | const config: PlaywrightTestConfig = { 4 | webServer: { 5 | command: 'npm run build && npm run preview', 6 | port: 4173 7 | } 8 | }; 9 | 10 | export default config; 11 | -------------------------------------------------------------------------------- /examples/solidjs/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import solidPlugin from 'vite-plugin-solid' 3 | 4 | export default defineConfig({ 5 | plugins: [solidPlugin()], 6 | server: { 7 | port: 3002, 8 | }, 9 | build: { 10 | target: 'esnext', 11 | }, 12 | }) 13 | -------------------------------------------------------------------------------- /examples/svelte/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte"], 7 | "pluginSearchDirs": ["."], 8 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/solid/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import solidPlugin from 'vite-plugin-solid'; 3 | 4 | export default defineConfig({ 5 | plugins: [solidPlugin()], 6 | server: { 7 | port: 3000, 8 | }, 9 | build: { 10 | target: 'esnext', 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /packages/svelte/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte"], 7 | "pluginSearchDirs": ["."], 8 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 9 | } 10 | -------------------------------------------------------------------------------- /examples/react/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App' 4 | import './app.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 7 | 8 | 9 | 10 | ) 11 | -------------------------------------------------------------------------------- /examples/svelte/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | declare global { 4 | namespace App { 5 | // interface Error {} 6 | // interface Locals {} 7 | // interface PageData {} 8 | // interface Platform {} 9 | } 10 | } 11 | 12 | export {}; 13 | -------------------------------------------------------------------------------- /packages/tsconfig/react-library.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "React Library", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "lib": ["ES6", "DOM"], 7 | "module": "ESNext", 8 | "target": "ES6", 9 | "jsx": "react-jsx" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["@example/*"] 11 | } -------------------------------------------------------------------------------- /packages/svelte/src/app.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // See https://kit.svelte.dev/docs/types#app 4 | // for information about these interfaces 5 | // and what to do when importing types 6 | declare namespace App { 7 | // interface Locals {} 8 | // interface PageData {} 9 | // interface Error {} 10 | // interface Platform {} 11 | } 12 | -------------------------------------------------------------------------------- /examples/react/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/react/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/svelte/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/svelte/src/routes/MenuIcon.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 16 | -------------------------------------------------------------------------------- /packages/tsconfig/svelte.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Svelte", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "moduleResolution": "node", 7 | "module": "es2020", 8 | "lib": ["es2020", "DOM"], 9 | "target": "es2020", 10 | "importsNotUsedAsValues": "error", 11 | "isolatedModules": true, 12 | "resolveJsonModule": true, 13 | "sourceMap": true 14 | } 15 | } -------------------------------------------------------------------------------- /examples/react/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Auth UI React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/solid/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tsconfig/solidjs.json", 3 | "compilerOptions": { 4 | "strict": true, 5 | "moduleResolution": "node", 6 | "allowSyntheticDefaultImports": true, 7 | "jsxImportSource": "solid-js", 8 | "resolveJsonModule": true, 9 | "types": ["vite/client"], 10 | "outDir": "dist" 11 | }, 12 | "include": ["src"], 13 | "exclude": ["node_modules", "dist", "build"] 14 | } 15 | -------------------------------------------------------------------------------- /packages/svelte/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto'; 2 | import preprocess from 'svelte-preprocess'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://github.com/sveltejs/svelte-preprocess 7 | // for more information about preprocessors 8 | preprocess: preprocess(), 9 | 10 | kit: { 11 | adapter: adapter() 12 | } 13 | }; 14 | 15 | export default config; 16 | -------------------------------------------------------------------------------- /packages/react/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tsconfig/react-library.json", 3 | "compilerOptions": { 4 | "strict": true, 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true, 7 | "jsxImportSource": "react", 8 | "resolveJsonModule": true, 9 | "types": ["vite/client"], 10 | "outDir": "dist" 11 | }, 12 | "include": ["src/*"], 13 | "exclude": ["node_modules", "dist", "build"] 14 | } 15 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export { default as EmailAuth } from './EmailAuth.svelte'; 2 | export { default as ForgottenPassword } from './ForgottenPassword.svelte'; 3 | export { default as MagicLink } from './MagicLink.svelte'; 4 | export { default as SocialAuth } from './SocialAuth.svelte'; 5 | export { default as UpdatePassword } from './UpdatePassword.svelte'; 6 | export { default as VerifyOtp } from './VerifyOtp.svelte'; 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.log 2 | npm-debug.log* 3 | 4 | # Coverage directory used by tools like istanbul 5 | coverage 6 | .nyc_output 7 | 8 | # Dependency directories 9 | node_modules 10 | 11 | # npm package lock 12 | package-lock.json 13 | yarn.lock 14 | 15 | # project files 16 | src 17 | test 18 | examples 19 | example 20 | example-next-js 21 | umd_temp 22 | CHANGELOG.md 23 | .travis.yml 24 | .editorconfig 25 | .eslintignore 26 | .eslintrc 27 | .babelrc 28 | .gitignore -------------------------------------------------------------------------------- /examples/solidjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | "moduleResolution": "node", 7 | "allowSyntheticDefaultImports": true, 8 | "esModuleInterop": true, 9 | "resolveJsonModule": true, 10 | "jsx": "preserve", 11 | "jsxImportSource": "solid-js", 12 | "types": ["vite/client"], 13 | "noEmit": true, 14 | "isolatedModules": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/svelte/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | %sveltekit.head% 9 | 10 | 11 |
%sveltekit.body%
12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/ui/index.ts: -------------------------------------------------------------------------------- 1 | export { default as SignUp } from './SignUp.svelte'; 2 | export { default as SignIn } from './SignIn.svelte'; 3 | export { default as MagicLink } from './MagicLink.svelte'; 4 | export { default as SocialAuth } from './SocialAuth.svelte'; 5 | export { default as ForgottenPassword } from './ForgottenPassword.svelte'; 6 | export { default as UpdatePassword } from './UpdatePassword.svelte'; 7 | export { default as VerifyOtp } from './VerifyOtp.svelte'; 8 | -------------------------------------------------------------------------------- /examples/svelte/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /packages/shared/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import type { Options } from 'tsup'; 2 | 3 | export const tsup: Options = { 4 | dts: true, 5 | entryPoints: ['src/index.ts'], 6 | external: ['react', 'next', /^@supabase\//], 7 | format: ['cjs', 'esm'], 8 | // inject: ['src/react-shim.js'], 9 | // ! .cjs/.mjs doesn't work with Angular's webpack4 config by default! 10 | legacyOutput: false, 11 | sourcemap: true, 12 | splitting: false, 13 | bundle: true, 14 | clean: true 15 | }; 16 | -------------------------------------------------------------------------------- /examples/solidjs/src/store.ts: -------------------------------------------------------------------------------- 1 | import { SocialLayout } from '@supabase/auth-ui-shared' 2 | import { createSignal } from 'solid-js' 3 | 4 | export const [customButtonColor, setCustomButtonColor] = 5 | createSignal('rgb(202, 37, 37)') 6 | export const [customBorderRadius, setCustomBorderRadius] = createSignal('5px') 7 | export const [customTheme, setCustomTheme] = createSignal('dark') 8 | export const [customSocialLayout, setCustomSocialLayout] = 9 | createSignal('horizontal') 10 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /examples/react/src/MenuIcon.tsx: -------------------------------------------------------------------------------- 1 | interface Props { 2 | className?: string 3 | } 4 | 5 | export default function MenuIcon({ className = '' }: Props) { 6 | return ( 7 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /examples/solidjs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Auth UI Solid.js 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/svelte/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript') 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /packages/solid/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "plugin:solid/typescript" 10 | ], 11 | "overrides": [ 12 | ], 13 | "parser": "@typescript-eslint/parser", 14 | "parserOptions": { 15 | "ecmaVersion": "latest", 16 | "sourceType": "module" 17 | }, 18 | "plugins": [ 19 | "@typescript-eslint", 20 | "solid" 21 | ], 22 | "rules": { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/svelte/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript') 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /examples/react/src/App.module.css: -------------------------------------------------------------------------------- 1 | .container-redshadow { 2 | min-width: 300px; 3 | box-shadow: -2px 1px 69px 5px rgb(202, 37, 37); 4 | border-radius: 1rem; 5 | } 6 | 7 | .container-greenshadow { 8 | min-width: 300px; 9 | box-shadow: -2px 1px 69px 5px rgb(65, 163, 35); 10 | border-radius: 1rem; 11 | } 12 | 13 | .container-blueshadow { 14 | min-width: 300px; 15 | box-shadow: -2px 1px 69px 5px rgb(8, 107, 177); 16 | border-radius: 1rem; 17 | } 18 | 19 | .container-orangeshadow { 20 | min-width: 300px; 21 | box-shadow: -2px 1px 69px 5px rgb(235, 115, 29); 22 | border-radius: 1rem; 23 | } 24 | -------------------------------------------------------------------------------- /packages/react/src/types.ts: -------------------------------------------------------------------------------- 1 | import { BaseAppearance, BaseAuth } from '@supabase/auth-ui-shared' 2 | import { CSSProperties, ReactNode } from 'react' 3 | 4 | export interface Appearance extends BaseAppearance { 5 | style?: { 6 | anchor?: CSSProperties 7 | button?: CSSProperties 8 | container?: CSSProperties 9 | divider?: CSSProperties 10 | input?: CSSProperties 11 | label?: CSSProperties 12 | loader?: CSSProperties 13 | message?: CSSProperties 14 | } 15 | } 16 | 17 | export interface Auth extends BaseAuth { 18 | children?: ReactNode 19 | appearance?: Appearance 20 | } 21 | -------------------------------------------------------------------------------- /examples/svelte/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /packages/svelte/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /packages/tsconfig/base.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Default", 4 | "compilerOptions": { 5 | "composite": false, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "inlineSources": false, 11 | "isolatedModules": true, 12 | "moduleResolution": "node", 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": false, 15 | "preserveWatchOutput": true, 16 | "skipLibCheck": true, 17 | "strict": true 18 | }, 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # testing 9 | coverage 10 | 11 | # next.js 12 | .next/ 13 | out/ 14 | build 15 | 16 | # misc 17 | .DS_Store 18 | *.pem 19 | .vscode 20 | 21 | # debug 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | .pnpm-debug.log* 26 | 27 | # local env files 28 | .env 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # Distribution directories 35 | dist/ 36 | package/ 37 | storybook-static/ 38 | 39 | # turbo 40 | .turbo 41 | -------------------------------------------------------------------------------- /examples/svelte/src/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer components { 6 | .toggle-button { 7 | @apply h-10 w-10 rounded-full border transition hover:scale-105; 8 | } 9 | } 10 | 11 | body { 12 | background-color: #1c1c1c; 13 | color: #fff; 14 | margin: 0; 15 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 16 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 17 | -webkit-font-smoothing: antialiased; 18 | -moz-osx-font-smoothing: grayscale; 19 | } 20 | 21 | p { 22 | font-size: 16px; 23 | color: rgba(255, 255, 255, 0.75); 24 | } 25 | -------------------------------------------------------------------------------- /packages/react/README.md: -------------------------------------------------------------------------------- 1 | # Supabase Auth UI React 2 | 3 | Supabase Auth UI is a collection of pre built UI components that work seamlessly with @supabase/auth-helpers. 4 | 5 | The main purpose of these components is to allow developers to get working on their apps quickly, but also be able to use their own style/css. 6 | 7 | Auth UI is kept deliberately separate from @supabase/auth-helpers so that developers can migrate away from pre-built UI components as their UI system naturally matures. 8 | 9 | Screenshot 2022-04-30 at 9 30 25 PM 10 | -------------------------------------------------------------------------------- /examples/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /examples/react/src/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer components { 6 | .toggle-button { 7 | @apply h-10 w-10 rounded-full border transition hover:scale-105; 8 | } 9 | } 10 | 11 | body { 12 | background-color: #1c1c1c; 13 | color: #fff; 14 | margin: 0; 15 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 16 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 17 | sans-serif; 18 | -webkit-font-smoothing: antialiased; 19 | -moz-osx-font-smoothing: grayscale; 20 | } 21 | 22 | p { 23 | font-size: 16px; 24 | color: rgba(255, 255, 255, 0.75); 25 | } 26 | -------------------------------------------------------------------------------- /packages/tsconfig/nextjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Next.js", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "target": "es5", 7 | "lib": ["dom", "dom.iterable", "esnext"], 8 | "allowJs": true, 9 | "skipLibCheck": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "noEmit": true, 13 | "incremental": true, 14 | "esModuleInterop": true, 15 | "module": "esnext", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "jsx": "preserve" 19 | }, 20 | "include": ["src", "next-env.d.ts"], 21 | "exclude": ["node_modules"] 22 | } 23 | -------------------------------------------------------------------------------- /examples/solidjs/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #1C1C1C; 3 | margin: 0; 4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 5 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 6 | sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | } 10 | 11 | a { 12 | text-decoration: none; 13 | color: #8bb7ff; 14 | } 15 | 16 | a:visited { 17 | color: #325998 18 | } 19 | 20 | p { 21 | font-size: 16px; 22 | color: rgba(255, 255, 255, 0.75); 23 | } 24 | 25 | code { 26 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 27 | monospace; 28 | } 29 | -------------------------------------------------------------------------------- /examples/svelte/src/routes/ToggleButton.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 24 | -------------------------------------------------------------------------------- /examples/solidjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/solidjs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "", 6 | "scripts": { 7 | "start": "vite", 8 | "dev": "vite", 9 | "build:example": "vite build", 10 | "serve": "vite preview" 11 | }, 12 | "license": "MIT", 13 | "devDependencies": { 14 | "@suid/icons-material": "^0.4.1", 15 | "@suid/material": "^0.6.3", 16 | "typescript": "^4.9.5", 17 | "vite": "^4.5.2", 18 | "vite-plugin-solid": "^2.5.0" 19 | }, 20 | "dependencies": { 21 | "@supabase/auth-ui-shared": "workspace:*", 22 | "@supabase/auth-ui-solid": "workspace:*", 23 | "@supabase/supabase-js": "^2.21.0", 24 | "solid-js": "^1.6.10" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/svelte/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto'; 2 | import { vitePreprocess } from '@sveltejs/kit/vite'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors 7 | // for more information about preprocessors 8 | preprocess: vitePreprocess(), 9 | 10 | kit: { 11 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. 12 | // If your environment is not supported or you settled on a specific environment, switch out the adapter. 13 | // See https://kit.svelte.dev/docs/adapters for more information about adapters. 14 | adapter: adapter() 15 | } 16 | }; 17 | 18 | export default config; 19 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/ui/VerifyOtp.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 24 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": ["dist/**", ".svelte-kit/**"] 7 | }, 8 | "build:example": { 9 | "dependsOn": ["^build", "^build:example"], 10 | "outputs": ["dist/**", ".svelte-kit/**"] 11 | }, 12 | "storybook": { 13 | "dependsOn": ["^storybook"], 14 | "outputs": ["dist/**", ".svelte-kit/**"] 15 | }, 16 | "clean:all": { 17 | "dependsOn": ["^clean:all"], 18 | "cache": false 19 | }, 20 | "lint": { 21 | "outputs": [] 22 | }, 23 | "dev": { 24 | "cache": false 25 | } 26 | }, 27 | "globalDependencies": [ 28 | "tsconfig.json", 29 | ".env.*" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/ui/ForgottenPassword.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 24 | -------------------------------------------------------------------------------- /packages/solid/src/types.ts: -------------------------------------------------------------------------------- 1 | import { BaseAppearance, BaseAuth } from '@supabase/auth-ui-shared' 2 | import { JSXElement } from 'solid-js' 3 | import { JSX } from 'solid-js/jsx-runtime' 4 | 5 | export type FormEvent = Event & { 6 | submitter: HTMLElement 7 | } & { 8 | currentTarget: HTMLFormElement 9 | target: Element 10 | } 11 | 12 | export interface Appearance extends BaseAppearance { 13 | style?: { 14 | anchor?: JSX.CSSProperties 15 | button?: JSX.CSSProperties 16 | container?: JSX.CSSProperties 17 | divider?: JSX.CSSProperties 18 | input?: JSX.CSSProperties 19 | label?: JSX.CSSProperties 20 | loader?: JSX.CSSProperties 21 | message?: JSX.CSSProperties 22 | } 23 | } 24 | 25 | export interface Auth extends BaseAuth { 26 | children?: JSXElement 27 | appearance?: Appearance 28 | } 29 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/UI/Divider.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 |
25 | 26 |
27 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/ui/UpdatePassword.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 26 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/UI/Label.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 | 28 | -------------------------------------------------------------------------------- /examples/react/src/ToggleButton.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react' 2 | 3 | interface Props { 4 | className?: string 5 | children?: ReactNode 6 | color?: string 7 | defaultValue: string 8 | setSelected?: (v: string) => void 9 | selected?: string 10 | } 11 | 12 | export default function ToggleButton({ 13 | children, 14 | color = 'transparent', 15 | defaultValue = '', 16 | className = '', 17 | setSelected = (v) => {}, 18 | selected, 19 | }: Props) { 20 | return ( 21 | 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /packages/solid/src/components/UI/Divider.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | import { JSX, Component } from 'solid-js' 5 | 6 | const dividerDefaultStyles = css({ 7 | background: '$dividerBackground', 8 | display: 'block', 9 | margin: '16px 0', 10 | height: '1px', 11 | width: '100%', 12 | }) 13 | 14 | interface DividerProps extends JSX.HTMLAttributes { 15 | appearance?: Appearance 16 | } 17 | 18 | const Divider: Component = (props) => { 19 | const classNames = generateClassNames( 20 | 'divider', 21 | dividerDefaultStyles(), 22 | props.appearance 23 | ) 24 | 25 | return ( 26 |
31 | ) 32 | } 33 | 34 | export { Divider } 35 | -------------------------------------------------------------------------------- /packages/react/src/components/UI/Divider.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | 5 | const dividerDefaultStyles = css({ 6 | background: '$dividerBackground', 7 | display: 'block', 8 | margin: '16px 0', 9 | height: '1px', 10 | width: '100%', 11 | }) 12 | 13 | interface DividerProps extends React.HTMLAttributes { 14 | appearance?: Appearance 15 | } 16 | 17 | const Divider: React.FC = ({ 18 | children, 19 | appearance, 20 | ...props 21 | }) => { 22 | const classNames = generateClassNames( 23 | 'divider', 24 | dividerDefaultStyles(), 25 | appearance 26 | ) 27 | 28 | return ( 29 |
34 | ) 35 | } 36 | 37 | export { Divider } 38 | -------------------------------------------------------------------------------- /packages/shared/src/constants.ts: -------------------------------------------------------------------------------- 1 | import { ViewsMap } from './types' 2 | 3 | export const VIEWS: ViewsMap = { 4 | SIGN_IN: 'sign_in', 5 | SIGN_UP: 'sign_up', 6 | FORGOTTEN_PASSWORD: 'forgotten_password', 7 | MAGIC_LINK: 'magic_link', 8 | UPDATE_PASSWORD: 'update_password', 9 | VERIFY_OTP: 'verify_otp', 10 | } 11 | 12 | export const PREPENDED_CLASS_NAMES = 'supabase-auth-ui' 13 | 14 | /** 15 | * CSS class names 16 | * used for generating prepended classes 17 | */ 18 | export const CLASS_NAMES = { 19 | // interfaces 20 | ROOT: 'root', 21 | SIGN_IN: VIEWS.SIGN_IN, 22 | SIGN_UP: VIEWS.SIGN_UP, 23 | FORGOTTEN_PASSWORD: VIEWS.FORGOTTEN_PASSWORD, 24 | MAGIC_LINK: VIEWS.MAGIC_LINK, 25 | UPDATE_PASSWORD: VIEWS.UPDATE_PASSWORD, 26 | // ui 27 | anchor: 'ui-anchor', 28 | button: 'ui-button', 29 | container: 'ui-container', 30 | divider: 'ui-divider', 31 | input: 'ui-input', 32 | label: 'ui-label', 33 | loader: 'ui-loader', 34 | message: 'ui-message', 35 | } 36 | -------------------------------------------------------------------------------- /packages/react/src/components/UI/Label.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | 5 | const labelDefaultStyles = css({ 6 | fontFamily: '$labelFontFamily', 7 | fontSize: '$baseLabelSize', 8 | marginBottom: '$labelBottomMargin', 9 | color: '$inputLabelText', 10 | display: 'block', 11 | }) 12 | 13 | interface LabelProps extends React.LabelHTMLAttributes { 14 | children: React.ReactNode 15 | appearance?: Appearance 16 | } 17 | 18 | const Label: React.FC = ({ children, appearance, ...props }) => { 19 | const classNames = generateClassNames( 20 | 'label', 21 | labelDefaultStyles(), 22 | appearance 23 | ) 24 | 25 | return ( 26 | 33 | ) 34 | } 35 | 36 | export { Label } 37 | -------------------------------------------------------------------------------- /packages/solid/src/components/UI/Label.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { Component, JSXElement, JSX } from 'solid-js' 3 | import { generateClassNames } from '@supabase/auth-ui-shared' 4 | import { Appearance } from '../../types' 5 | 6 | const labelDefaultStyles = css({ 7 | fontFamily: '$labelFontFamily', 8 | fontSize: '$baseLabelSize', 9 | marginBottom: '$labelBottomMargin', 10 | color: '$inputLabelText', 11 | display: 'block', 12 | }) 13 | 14 | interface LabelProps extends JSX.LabelHTMLAttributes { 15 | children: JSXElement 16 | appearance?: Appearance 17 | } 18 | 19 | const Label: Component = (props) => { 20 | const classNames = generateClassNames( 21 | 'label', 22 | labelDefaultStyles(), 23 | props.appearance 24 | ) 25 | 26 | return ( 27 | 34 | ) 35 | } 36 | 37 | export { Label } 38 | -------------------------------------------------------------------------------- /packages/react/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import dts from 'vite-plugin-dts' 4 | import path from 'path' 5 | import { peerDependencies, dependencies } from './package.json' 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | plugins: [ 10 | react({ 11 | jsxRuntime: 'classic', 12 | }), 13 | dts({ 14 | include: ['src/'], 15 | // insertTypesEntry: true, 16 | }), 17 | ], 18 | build: { 19 | lib: { 20 | entry: path.resolve(__dirname, 'src'), 21 | formats: ['es', 'cjs'], 22 | fileName: (format) => `index.${format}.js`, 23 | }, 24 | rollupOptions: { 25 | external: [ 26 | ...Object.keys(peerDependencies), 27 | ...Object.keys(dependencies), 28 | ], 29 | output: { 30 | globals: { 31 | react: 'React', 32 | 'react-dom': 'ReactDOM', 33 | // 'styled-components': 'styled', 34 | }, 35 | }, 36 | }, 37 | }, 38 | }) 39 | -------------------------------------------------------------------------------- /packages/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@supabase/auth-ui-shared", 3 | "version": "0.1.8", 4 | "main": "dist/index.js", 5 | "module": "dist/index.mjs", 6 | "types": "dist/index.d.ts", 7 | "publishConfig": { 8 | "access": "public" 9 | }, 10 | "files": [ 11 | "dist" 12 | ], 13 | "scripts": { 14 | "build": "tsup" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/supabase/auth-ui.git" 19 | }, 20 | "keywords": [ 21 | "Supabase", 22 | "Auth", 23 | "React", 24 | "Svelte", 25 | "Solid" 26 | ], 27 | "author": "Supabase", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/supabase/auth-ui/issues" 31 | }, 32 | "homepage": "https://github.com/supabase/auth-ui#readme", 33 | "devDependencies": { 34 | "@stitches/core": "^1.2.8", 35 | "@supabase/supabase-js": "^2.39.3", 36 | "tsconfig": "workspace:*", 37 | "tsup": "^6.6.3" 38 | }, 39 | "peerDependencies": { 40 | "@supabase/supabase-js": "^2.39.3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/types.ts: -------------------------------------------------------------------------------- 1 | import type { BaseAppearance } from '@supabase/auth-ui-shared'; 2 | 3 | export interface Appearance extends BaseAppearance { 4 | style?: { 5 | anchor?: string; 6 | button?: string; 7 | container?: string; 8 | divider?: string; 9 | input?: string; 10 | label?: string; 11 | loader?: string; 12 | message?: string; 13 | }; 14 | } 15 | 16 | export interface AuthSettings { 17 | external?: { 18 | apple?: boolean; 19 | azure?: boolean; 20 | bitbucket?: boolean; 21 | discord?: boolean; 22 | github?: boolean; 23 | gitlab?: boolean; 24 | keycloak?: boolean; 25 | google?: boolean; 26 | linkedin?: boolean; 27 | facebook?: boolean; 28 | notion?: boolean; 29 | spotify?: boolean; 30 | slack?: boolean; 31 | workos?: boolean; 32 | twitch?: boolean; 33 | twitter?: boolean; 34 | email?: boolean; 35 | phone?: boolean; 36 | saml?: boolean; 37 | zoom?: boolean; 38 | }; 39 | disable_signup?: boolean; 40 | mailer_autoconfirm?: boolean; 41 | phone_autoconfirm?: boolean; 42 | sms_provider?: string; 43 | } 44 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/UI/Anchor.svelte: -------------------------------------------------------------------------------- 1 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /packages/shared/src/utils.ts: -------------------------------------------------------------------------------- 1 | function value(src: any, next: any) { 2 | let k 3 | if (src && next && typeof src === 'object' && typeof next === 'object') { 4 | if (Array.isArray(next)) { 5 | for (k = 0; k < next.length; k++) { 6 | src[k] = value(src[k], next[k]) 7 | } 8 | } else { 9 | for (k in next) { 10 | src[k] = value(src[k], next[k]) 11 | } 12 | } 13 | return src 14 | } 15 | return next 16 | } 17 | 18 | export function merge(target: any, ...args: any) { 19 | let len: number = args.length 20 | for (let i = 0; i < len; i++) { 21 | target = value(target, args[i]) 22 | } 23 | return target 24 | } 25 | 26 | // Source https://stackoverflow.com/a/61634647/811799 27 | export function template(string: string, data: Record) { 28 | return string.replace( 29 | /{{(\w+)}}/g, 30 | (placeholderWithDelimiters, placeholderWithoutDelimiters) => 31 | data.hasOwnProperty(placeholderWithoutDelimiters) 32 | ? data[placeholderWithoutDelimiters] 33 | : placeholderWithDelimiters 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /examples/svelte/README.md: -------------------------------------------------------------------------------- 1 | # create-svelte 2 | 3 | Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). 4 | 5 | ## Creating a project 6 | 7 | If you're seeing this, you've probably already done this step. Congrats! 8 | 9 | ```bash 10 | # create a new project in the current directory 11 | npm create svelte@latest 12 | 13 | # create a new project in my-app 14 | npm create svelte@latest my-app 15 | ``` 16 | 17 | ## Developing 18 | 19 | Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: 20 | 21 | ```bash 22 | npm run dev 23 | 24 | # or start the server and open the app in a new browser tab 25 | npm run dev -- --open 26 | ``` 27 | 28 | ## Building 29 | 30 | To create a production version of your app: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | You can preview the production build with `npm run preview`. 37 | 38 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. 39 | -------------------------------------------------------------------------------- /examples/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/react", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "concurrently \"npm run dev:css\" \"vite\"", 8 | "dev:css": "tailwindcss -w -i ./src/tailwind.css -o src/app.css", 9 | "build:example": "npm run build:css && tsc && vite build", 10 | "build:css": "tailwindcss -m -i ./src/tailwind.css -o src/app.css", 11 | "preview": "vite preview" 12 | }, 13 | "dependencies": { 14 | "@supabase/auth-ui-react": "workspace:*", 15 | "@supabase/auth-ui-shared": "workspace:*", 16 | "@supabase/supabase-js": "^2.21.0", 17 | "react": "^18.2.0", 18 | "react-dom": "^18.2.0" 19 | }, 20 | "devDependencies": { 21 | "@emotion/react": "^11.10.6", 22 | "@emotion/styled": "^11.10.6", 23 | "@types/react": "^18.0.27", 24 | "@types/react-dom": "^18.0.10", 25 | "@vitejs/plugin-react": "^3.1.0", 26 | "autoprefixer": "^10.4.13", 27 | "concurrently": "^7.6.0", 28 | "postcss": "^8.4.31", 29 | "tailwindcss": "^3.2.7", 30 | "typescript": "^4.9.3", 31 | "vite": "^4.5.2" 32 | } 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Supabase 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/react/src/components/UI/Anchor.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | 5 | const anchorHTMLAttributes = css({ 6 | fontFamily: '$bodyFontFamily', 7 | fontSize: '$baseBodySize', 8 | marginBottom: '$anchorBottomMargin', 9 | color: '$anchorTextColor', 10 | display: 'block', 11 | textAlign: 'center', 12 | textDecoration: 'underline', 13 | '&:hover': { 14 | color: '$anchorTextHoverColor', 15 | }, 16 | }) 17 | 18 | interface LabelProps extends React.AnchorHTMLAttributes { 19 | children: React.ReactNode 20 | appearance?: Appearance 21 | } 22 | 23 | const Anchor: React.FC = ({ children, appearance, ...props }) => { 24 | const classNames = generateClassNames( 25 | 'anchor', 26 | anchorHTMLAttributes(), 27 | appearance 28 | ) 29 | 30 | return ( 31 | 36 | {children} 37 | 38 | ) 39 | } 40 | 41 | export { Anchor } 42 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | jobs: 10 | release: 11 | name: Release / Node ${{ matrix.node }} 12 | strategy: 13 | matrix: 14 | node: ['18'] 15 | 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - uses: pnpm/action-setup@v2.0.1 22 | with: 23 | version: 8.7.0 24 | 25 | - name: Set up Node 26 | uses: actions/setup-node@v2 27 | with: 28 | node-version: ${{ matrix.node }} 29 | cache: pnpm 30 | 31 | - run: | 32 | pnpm install --frozen-lockfile 33 | pnpm run build 34 | 35 | - name: Create a release 36 | id: changesets 37 | uses: changesets/action@v1 38 | with: 39 | version: pnpm ci:version 40 | commit: 'chore: update versions' 41 | title: 'chore: update versions' 42 | publish: pnpm ci:release 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 46 | -------------------------------------------------------------------------------- /packages/shared/src/theming/utils.ts: -------------------------------------------------------------------------------- 1 | import { BaseAppearance } from '../types' 2 | import { CLASS_NAMES, PREPENDED_CLASS_NAMES } from './../constants' 3 | 4 | export function generateClassNames( 5 | /** 6 | * name of css class name variable 7 | */ 8 | classNameKey: 9 | | 'button' 10 | | 'container' 11 | | 'anchor' 12 | | 'divider' 13 | | 'label' 14 | | 'input' 15 | | 'loader' 16 | | 'message', 17 | /** 18 | * stiches CSS output 19 | */ 20 | defaultStyles: string, 21 | /** 22 | * appearance variables 23 | */ 24 | appearance?: BaseAppearance 25 | ) { 26 | const classNames = [] 27 | const className = CLASS_NAMES[classNameKey] 28 | 29 | classNames.push( 30 | appearance?.prependedClassName 31 | ? appearance?.prependedClassName + '_' + className 32 | : PREPENDED_CLASS_NAMES + '_' + className 33 | ) 34 | 35 | if (appearance?.className?.[classNameKey]) { 36 | classNames.push(appearance?.className?.[classNameKey]) 37 | } 38 | 39 | if (appearance?.extend === undefined || appearance?.extend === true) { 40 | classNames.push(defaultStyles) 41 | } 42 | 43 | return classNames 44 | } 45 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/ui/MagicLink.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 | 37 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/ui/SocialAuth.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 | 37 | -------------------------------------------------------------------------------- /examples/solidjs/README.md: -------------------------------------------------------------------------------- 1 | ## Usage 2 | 3 | Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`. 4 | 5 | This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template. 6 | 7 | ```bash 8 | $ npm install # or pnpm install or yarn install 9 | ``` 10 | 11 | ### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs) 12 | 13 | ## Available Scripts 14 | 15 | In the project directory, you can run: 16 | 17 | ### `npm dev` or `npm start` 18 | 19 | Runs the app in the development mode.
20 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 21 | 22 | The page will reload if you make edits.
23 | 24 | ### `npm run build` 25 | 26 | Builds the app for production to the `dist` folder.
27 | It correctly bundles Solid in production mode and optimizes the build for the best performance. 28 | 29 | The build is minified and the filenames include the hashes.
30 | Your app is ready to be deployed! 31 | 32 | ## Deployment 33 | 34 | You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.) 35 | -------------------------------------------------------------------------------- /packages/solid/src/components/UI/Anchor.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | import { JSX } from 'solid-js/jsx-runtime' 5 | import { Component, JSXElement } from 'solid-js' 6 | 7 | const anchorHTMLAttributes = css({ 8 | fontFamily: '$bodyFontFamily', 9 | fontSize: '$baseBodySize', 10 | marginBottom: '$anchorBottomMargin', 11 | color: '$anchorTextColor', 12 | display: 'block', 13 | textAlign: 'center', 14 | textDecoration: 'underline', 15 | '&:hover': { 16 | color: '$anchorTextHoverColor', 17 | }, 18 | fontWeight: '200', 19 | textDecorationLine: 'none', 20 | }) 21 | 22 | interface LabelProps extends JSX.AnchorHTMLAttributes { 23 | children: JSXElement 24 | appearance?: Appearance 25 | } 26 | 27 | const Anchor: Component = (props) => { 28 | const classNames = generateClassNames( 29 | 'anchor', 30 | anchorHTMLAttributes(), 31 | props.appearance 32 | ) 33 | 34 | return ( 35 | 40 | {props.children} 41 | 42 | ) 43 | } 44 | 45 | export { Anchor } 46 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/ui/SignIn.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 | 40 | -------------------------------------------------------------------------------- /packages/shared/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @supabase/auth-ui-shared 2 | 3 | ## 0.1.8 4 | 5 | ### Patch Changes 6 | 7 | - a8f9395d: Message styling change 8 | 9 | ## 0.1.7 10 | 11 | ### Patch Changes 12 | 13 | - 2b252910: Fix check for blank email address on magic links 14 | 15 | ## 0.1.6 16 | 17 | ### Patch Changes 18 | 19 | - 8ca7a586: Add additional data to component to store in user_metadata 20 | 21 | ## 0.1.5 22 | 23 | ### Patch Changes 24 | 25 | - 3aa2c54d: Add new types for verify otp support 26 | 27 | ## 0.1.4 28 | 29 | ### Patch Changes 30 | 31 | - d5052260: Add providerScopes property for setting social auth scopes 32 | 33 | ## 0.1.3 34 | 35 | ### Patch Changes 36 | 37 | - 11ebb978: Update i18n for confirmation messages 38 | 39 | ## 0.1.2 40 | 41 | ### Patch Changes 42 | 43 | - b8e6e3b4: Update appearance property to include extend for default classes 44 | - b8e6e3b4: Update social layout type to only include keys 45 | 46 | ## 0.1.1 47 | 48 | ### Patch Changes 49 | 50 | - 0d794741: Update shared en localization to include templated variable 51 | 52 | ## 0.1.0 53 | 54 | ### Minor Changes 55 | 56 | - 1349aa6: Updated to share common files using the auth-ui-shared package 57 | Removed storybook from the react package 58 | Add examples to showcase the Auth UI 59 | Moved localizations to their own directory 60 | -------------------------------------------------------------------------------- /packages/solid/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@supabase/auth-ui-solid", 3 | "version": "0.3.8", 4 | "description": "", 5 | "type": "module", 6 | "main": "./dist/index.jsx", 7 | "module": "./dist/index.jsx", 8 | "types": "./dist/index.d.ts", 9 | "files": [ 10 | "dist" 11 | ], 12 | "publishConfig": { 13 | "access": "public" 14 | }, 15 | "homepage": "https://github.com/supabase/auth-ui/tree/main/packages/solid", 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/supabase/auth-ui.git" 19 | }, 20 | "source": "src/index.tsx", 21 | "scripts": { 22 | "build": "rm -rf dist && tsc --build" 23 | }, 24 | "devDependencies": { 25 | "@suid/icons-material": "^0.4.1", 26 | "@suid/material": "^0.6.3", 27 | "@supabase/supabase-js": "^2.39.3", 28 | "@typescript-eslint/eslint-plugin": "^5.51.0", 29 | "@typescript-eslint/parser": "^5.51.0", 30 | "eslint": "^8.33.0", 31 | "eslint-plugin-solid": "^0.9.4", 32 | "tsconfig": "workspace:*", 33 | "typescript": "^4.9.5", 34 | "vite": "^4.5.2", 35 | "vite-plugin-solid": "^2.5.0" 36 | }, 37 | "dependencies": { 38 | "@stitches/core": "^1.2.8", 39 | "@supabase/auth-ui-shared": "workspace:*", 40 | "just-merge": "^3.2.0", 41 | "solid-js": "^1.5.1 || ^1.6.0 || ^1.6.1" 42 | }, 43 | "sideEffects": false 44 | } 45 | -------------------------------------------------------------------------------- /development.md: -------------------------------------------------------------------------------- 1 | This repository is a monorepo and makes use of [Turborepo](https://turborepo.org/) and PNPM workspaces. 2 | 3 | ## Set up 4 | 5 | Before you begin, make sure you have the following set up on your local machine. 6 | 7 | - Install [NodeJS v16.x (LTS)](https://nodejs.org/en/) 8 | - Install [PNPM](https://pnpm.io/installation) 9 | 10 | > All commands below should be run at the root level of the cloned repository. 11 | 12 | ### Install package dependencies 13 | 14 | ```bash 15 | pnpm install 16 | ``` 17 | 18 | ### Development setup 19 | 20 | You can run all the packages in development mode using the following command: 21 | 22 | ```bash 23 | pnpm dev 24 | ``` 25 | 26 | Or you can run development for the individual packages using the following command: 27 | 28 | ```bash 29 | pnpm dev:[dirname] 30 | ``` 31 | 32 | For `React` it would be: 33 | 34 | ```bash 35 | pnpm dev:react 36 | ``` 37 | 38 | ### Build 39 | 40 | You can build all packages using the following command: 41 | 42 | ```bash 43 | pnpm build 44 | ``` 45 | 46 | Or you can run build for the individual packages using the following command: 47 | 48 | ```bash 49 | pnpm build:[dirname] 50 | ``` 51 | 52 | For `React` it would be: 53 | 54 | ```bash 55 | pnpm build:react 56 | ``` 57 | 58 | ### Change logs 59 | 60 | To generate a changelog entry, run the following command: 61 | 62 | ```sh 63 | pnpm changeset 64 | ``` 65 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/UI/Loader.svelte: -------------------------------------------------------------------------------- 1 | 43 | 44 |
45 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/UI/Message.svelte: -------------------------------------------------------------------------------- 1 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/ui/SignUp.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/react/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/UI/Container.svelte: -------------------------------------------------------------------------------- 1 | 54 | 55 |
56 | 57 |
58 | -------------------------------------------------------------------------------- /packages/react/src/components/UI/Message.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | 5 | const messageDefaultStyles = css({ 6 | fontFamily: '$bodyFontFamily', 7 | fontSize: '$baseInputSize', 8 | marginBottom: '$labelBottomMargin', 9 | display: 'block', 10 | textAlign: 'center', 11 | borderRadius: '0.375rem', 12 | padding: '1.5rem 1rem', 13 | lineHeight: '1rem', 14 | color: '$messageText', 15 | backgroundColor: '$messageBackground', 16 | border: '1px solid $messageBorder', 17 | variants: { 18 | color: { 19 | danger: { 20 | color: '$messageTextDanger', 21 | backgroundColor: '$messageBackgroundDanger', 22 | border: '1px solid $messageBorderDanger', 23 | }, 24 | }, 25 | }, 26 | }) 27 | 28 | interface MessageProps extends React.HTMLAttributes { 29 | children: React.ReactNode 30 | color?: 'danger' 31 | appearance?: Appearance 32 | } 33 | 34 | const Message: React.FC = ({ 35 | children, 36 | appearance, 37 | ...props 38 | }) => { 39 | const classNames = generateClassNames( 40 | 'message', 41 | messageDefaultStyles({ color: props.color }), 42 | appearance 43 | ) 44 | 45 | return ( 46 | 51 | {children} 52 | 53 | ) 54 | } 55 | 56 | export { Message } 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@supabase/auth-ui", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "turbo run build", 7 | "build:react": "turbo run build --filter=@supabase/auth-ui-react", 8 | "build:solid": "turbo run build --filter=@supabase/auth-ui-solid", 9 | "build:svelte": "turbo run build --filter=@supabase/auth-ui-svelte", 10 | "build:example": "turbo run build:example", 11 | "build:example:react": "turbo run build:example --filter=@example/react", 12 | "build:example:solid": "turbo run build:example --filter=@example/solidjs", 13 | "build:example:svelte": "turbo run build:example --filter=@example/svelte", 14 | "dev": "turbo run dev --parallel", 15 | "dev:react": "turbo run dev --filter=@example/react", 16 | "dev:solid": "turbo run dev --filter=@example/solidjs", 17 | "dev:svelte": "turbo run dev --filter=@example/svelte", 18 | "lint": "turbo run lint", 19 | "format": "prettier --write \"**/*.{ts,tsx,md}\"", 20 | "clean:all": "turbo run clean:all", 21 | "ci:version": "changeset version", 22 | "ci:release": "changeset publish" 23 | }, 24 | "devDependencies": { 25 | "@changesets/cli": "^2.22.0", 26 | "prettier": "^2.5.1", 27 | "turbo": "^1.10.13", 28 | "typedoc": "^0.25.0", 29 | "typescript": "4.4.x || 4.5.x || 4.6.x" 30 | }, 31 | "engines": { 32 | "npm": ">=9.0.0", 33 | "node": ">=18.0.0" 34 | }, 35 | "packageManager": "pnpm@8.7.0", 36 | "peerDependencies": { 37 | "typescript": "4.4.x || 4.5.x || 4.6.x" 38 | } 39 | } -------------------------------------------------------------------------------- /examples/solidjs/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/solid/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/svelte/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@example/svelte", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "concurrently \"npm run dev:css\" \"vite dev\"", 7 | "dev:css": "tailwindcss -w -i ./src/tailwind.css -o static/app.css", 8 | "build:example": "npm run build:css && vite build", 9 | "build:css": "tailwindcss -m -i ./src/tailwind.css -o static/app.css", 10 | "preview": "vite preview", 11 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 12 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 13 | "lint": "prettier --plugin-search-dir . --check . && eslint .", 14 | "format": "prettier --plugin-search-dir . --write ." 15 | }, 16 | "dependencies": { 17 | "@supabase/auth-ui-shared": "workspace:*", 18 | "@supabase/auth-ui-svelte": "workspace:*", 19 | "@supabase/supabase-js": "^2.21.0" 20 | }, 21 | "devDependencies": { 22 | "@sveltejs/adapter-auto": "^2.0.0", 23 | "@sveltejs/kit": "^1.15.2", 24 | "@typescript-eslint/eslint-plugin": "^5.45.0", 25 | "@typescript-eslint/parser": "^5.45.0", 26 | "autoprefixer": "^10.4.13", 27 | "concurrently": "^7.6.0", 28 | "eslint": "^8.28.0", 29 | "eslint-config-prettier": "^8.5.0", 30 | "eslint-plugin-svelte3": "^4.0.0", 31 | "postcss": "^8.4.31", 32 | "prettier": "^2.8.0", 33 | "prettier-plugin-svelte": "^2.8.1", 34 | "svelte": "^3.54.0", 35 | "svelte-check": "^3.0.1", 36 | "tailwindcss": "^3.2.7", 37 | "tslib": "^2.4.1", 38 | "typescript": "^4.9.3", 39 | "vite": "^4.5.2" 40 | }, 41 | "type": "module" 42 | } 43 | -------------------------------------------------------------------------------- /packages/solid/src/components/UI/Message.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { Component, JSXElement, JSX } from 'solid-js' 3 | import { generateClassNames } from '@supabase/auth-ui-shared' 4 | import { Appearance } from '../../types' 5 | 6 | const messageDefaultStyles = css({ 7 | fontFamily: '$bodyFontFamily', 8 | fontSize: '$baseInputSize', 9 | marginBottom: '$labelBottomMargin', 10 | display: 'block', 11 | textAlign: 'center', 12 | borderRadius: '0.375rem', 13 | padding: '1.5rem 1rem', 14 | lineHeight: '1rem', 15 | variants: { 16 | color: { 17 | default: { 18 | color: '$messageText', 19 | backgroundColor: '$messageBackground', 20 | border: '1px solid $messageBorder', 21 | }, 22 | danger: { 23 | color: '$messageTextDanger', 24 | backgroundColor: '$messageBackgroundDanger', 25 | border: '1px solid $messageBorderDanger', 26 | }, 27 | }, 28 | }, 29 | }) 30 | 31 | interface MessageProps extends JSX.HTMLAttributes { 32 | children: JSXElement 33 | color?: 'default' | 'danger' 34 | appearance?: Appearance 35 | } 36 | 37 | const Message: Component = (props) => { 38 | const classNames = generateClassNames( 39 | 'message', 40 | messageDefaultStyles({ color: props.color }), 41 | props.appearance 42 | ) 43 | 44 | return ( 45 | 50 | {props.children} 51 | 52 | ) 53 | } 54 | 55 | export { Message } 56 | -------------------------------------------------------------------------------- /packages/react/src/components/UI/Container.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | 5 | const containerDefaultStyles = css({ 6 | display: 'flex', 7 | gap: '4px', 8 | variants: { 9 | direction: { 10 | horizontal: { 11 | display: 'grid', 12 | gridTemplateColumns: 'repeat(auto-fit, minmax(48px, 1fr))', 13 | }, 14 | vertical: { 15 | flexDirection: 'column', 16 | margin: '8px 0', 17 | }, 18 | }, 19 | gap: { 20 | small: { 21 | gap: '4px', 22 | }, 23 | medium: { 24 | gap: '8px', 25 | }, 26 | large: { 27 | gap: '16px', 28 | }, 29 | }, 30 | }, 31 | }) 32 | 33 | export interface ContainerProps 34 | extends React.HtmlHTMLAttributes { 35 | children: React.ReactNode 36 | direction?: 'horizontal' | 'vertical' 37 | gap?: 'small' | 'medium' | 'large' 38 | appearance?: Appearance 39 | } 40 | 41 | const Container: React.FC = ({ 42 | children, 43 | appearance, 44 | ...props 45 | }) => { 46 | const classNames = generateClassNames( 47 | 'container', 48 | containerDefaultStyles({ 49 | direction: props.direction, 50 | gap: props.gap, 51 | }), 52 | appearance 53 | ) 54 | 55 | return ( 56 |
61 | {children} 62 |
63 | ) 64 | } 65 | 66 | export { Container } 67 | -------------------------------------------------------------------------------- /localization/japanese/ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "sign_up": { 3 | "email_label": "電子メールアドレス", 4 | "password_label": "パスワードを作成", 5 | "email_input_placeholder": "Your email address", 6 | "password_input_placeholder": "Your password", 7 | "button_label": "サインアップ", 8 | "loading_button_label": "Signing up ...", 9 | "social_provider_text": "{{provider}} に登録する", 10 | "link_text": "アカウントをお持ちではありませんか?サインアップ" 11 | }, 12 | "sign_in": { 13 | "email_label": "電子メールアドレス", 14 | "password_label": "あなたのパスワード", 15 | "email_input_placeholder": "Your email address", 16 | "password_input_placeholder": "Your password", 17 | "button_label": "サインイン", 18 | "loading_button_label": "Signing in ...", 19 | "social_provider_text": "{{provider}} に登録する", 20 | "link_text": "Already have an account? Sign in" 21 | }, 22 | "magic_link": { 23 | "email_input_label": "Email address", 24 | "email_input_placeholder": "Your email address", 25 | "button_label": "Send Magic Link", 26 | "loading_button_label": "Sending Magic Link ...", 27 | "link_text": "Send a magic link email" 28 | }, 29 | "forgotten_password": { 30 | "email_label": "Email address", 31 | "password_label": "Your Password", 32 | "email_input_placeholder": "Your email address", 33 | "button_label": "Send reset password instructions", 34 | "loading_button_label": "Sending reset instructions ...", 35 | "link_text": "パスワードをお忘れの方" 36 | }, 37 | "update_password": { 38 | "password_label": "New password", 39 | "password_input_placeholder": "Your new password", 40 | "button_label": "Update password", 41 | "loading_button_label": "Updating password ..." 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/solid/src/components/UI/Container.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { SocialLayout, generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | import { JSXElement, JSX, Component, createMemo } from 'solid-js' 5 | 6 | const containerDefaultStyles = css({ 7 | display: 'flex', 8 | gap: '4px', 9 | variants: { 10 | direction: { 11 | horizontal: { 12 | flexDirection: 'row', 13 | margin: '4px 0', 14 | }, 15 | vertical: { 16 | flexDirection: 'column', 17 | margin: '8px 0', 18 | }, 19 | }, 20 | gap: { 21 | small: { 22 | gap: '4px', 23 | }, 24 | medium: { 25 | gap: '8px', 26 | }, 27 | large: { 28 | gap: '16px', 29 | }, 30 | }, 31 | }, 32 | }) 33 | 34 | export interface ContainerProps extends JSX.HTMLAttributes { 35 | children: JSXElement 36 | direction?: 'horizontal' | 'vertical' | SocialLayout | string 37 | gap?: 'small' | 'medium' | 'large' 38 | appearance?: Appearance 39 | } 40 | 41 | const Container: Component = (props) => { 42 | const classNames = createMemo(() => 43 | generateClassNames( 44 | 'container', 45 | containerDefaultStyles({ 46 | direction: props.direction as 'horizontal' | 'vertical', 47 | gap: props.gap, 48 | }), 49 | props.appearance 50 | ) 51 | ) 52 | 53 | return ( 54 |
59 | {props.children} 60 |
61 | ) 62 | } 63 | 64 | export { Container } 65 | -------------------------------------------------------------------------------- /packages/react/src/components/Auth/UserContext.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState, createContext, useContext } from 'react' 2 | import { SupabaseClient, Session, User } from '@supabase/supabase-js' 3 | 4 | export interface AuthSession { 5 | user: User | null 6 | session: Session | null 7 | } 8 | 9 | const UserContext = createContext({ user: null, session: null }) 10 | 11 | export interface Props { 12 | supabaseClient: SupabaseClient 13 | [propName: string]: any 14 | } 15 | 16 | export const UserContextProvider = (props: Props) => { 17 | const { supabaseClient } = props 18 | const [session, setSession] = useState(null) 19 | const [user, setUser] = useState(session?.user ?? null) 20 | 21 | useEffect(() => { 22 | ;(async () => { 23 | const { data } = await supabaseClient.auth.getSession() 24 | setSession(data.session) 25 | setUser(data.session?.user ?? null) 26 | })() 27 | 28 | const { data: authListener } = supabaseClient.auth.onAuthStateChange( 29 | async (event, session) => { 30 | setSession(session) 31 | setUser(session?.user ?? null) 32 | } 33 | ) 34 | 35 | return () => { 36 | authListener?.subscription.unsubscribe() 37 | } 38 | // eslint-disable-next-line react-hooks/exhaustive-deps 39 | }, []) 40 | 41 | const value = { 42 | session, 43 | user, 44 | } 45 | return 46 | } 47 | 48 | export const useUser = () => { 49 | const context = useContext(UserContext) 50 | if (context === undefined) { 51 | throw new Error(`useUser must be used within a UserContextProvider.`) 52 | } 53 | return context 54 | } 55 | -------------------------------------------------------------------------------- /packages/shared/src/theming/Types.ts: -------------------------------------------------------------------------------- 1 | export type ThemeVariables = { 2 | colors?: { 3 | brand?: string 4 | brandAccent?: string 5 | brandButtonText?: string 6 | defaultButtonBackground?: string 7 | defaultButtonBackgroundHover?: string 8 | defaultButtonBorder?: string 9 | defaultButtonText?: string 10 | dividerBackground?: string 11 | inputBackground?: string 12 | inputBorder?: string 13 | inputBorderFocus?: string 14 | inputBorderHover?: string 15 | inputLabelText?: string 16 | inputPlaceholder?: string 17 | inputText?: string 18 | messageText?: string 19 | messageBackground?: string 20 | messageBorder?: string 21 | messageTextDanger?: string 22 | messageBackgroundDanger?: string 23 | messageBorderDanger?: string 24 | anchorTextColor?: string 25 | anchorTextHoverColor?: string 26 | } 27 | space?: { 28 | spaceSmall?: string 29 | spaceMedium?: string 30 | spaceLarge?: string 31 | labelBottomMargin?: string 32 | anchorBottomMargin?: string 33 | emailInputSpacing?: string 34 | socialAuthSpacing?: string 35 | buttonPadding?: string 36 | inputPadding?: string 37 | } 38 | fontSizes?: { 39 | baseBodySize?: string 40 | baseInputSize?: string 41 | baseLabelSize?: string 42 | baseButtonSize?: string 43 | } 44 | fonts?: { 45 | bodyFontFamily?: string 46 | buttonFontFamily?: string 47 | inputFontFamily?: string 48 | labelFontFamily?: string 49 | } 50 | borderWidths?: { 51 | buttonBorderWidth?: string 52 | inputBorderWidth?: string 53 | } 54 | radii?: { 55 | borderRadiusButton?: string 56 | buttonBorderRadius?: string 57 | inputBorderRadius?: string 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@supabase/auth-ui-react", 3 | "version": "0.4.7", 4 | "main": "./dist/index.cjs.js", 5 | "module": "./dist/index.es.js", 6 | "files": [ 7 | "dist" 8 | ], 9 | "publishConfig": { 10 | "access": "public" 11 | }, 12 | "types": "./dist/index.d.ts", 13 | "type": "module", 14 | "exports": { 15 | "./package.json": "./package.json", 16 | ".": { 17 | "types": "./dist/index.d.ts", 18 | "import": "./dist/index.es.js", 19 | "require": "./dist/index.cjs.js" 20 | } 21 | }, 22 | "homepage": "https://github.com/supabase-community/auth-ui#readme", 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/supabase-community/auth-ui.git" 26 | }, 27 | "sideEffects": false, 28 | "source": "src/index.tsx", 29 | "scripts": { 30 | "build": "tsc && vite build", 31 | "build:tsc": "rm -rf dist && tsc --build" 32 | }, 33 | "dependencies": { 34 | "@stitches/core": "^1.2.8", 35 | "@supabase/auth-ui-shared": "workspace:*", 36 | "prop-types": "^15.7.2", 37 | "react": "^18.2.0", 38 | "react-dom": "^18.2.0" 39 | }, 40 | "peerDependencies": { 41 | "@supabase/supabase-js": "^2.39.3" 42 | }, 43 | "devDependencies": { 44 | "@supabase/supabase-js": "^2.39.3", 45 | "@types/is-ci": "^3.0.0", 46 | "@types/minimist": "^1.2.2", 47 | "@types/node": "^18.14.0", 48 | "@types/normalize-package-data": "^2.4.1", 49 | "@types/react": "^18.0.27", 50 | "@types/react-dom": "^18.0.10", 51 | "@types/semver": "^7.3.13", 52 | "@vitejs/plugin-react": "^3.1.0", 53 | "tsconfig": "workspace:*", 54 | "typescript": "^4.9.3", 55 | "vite": "^4.5.2", 56 | "vite-plugin-dts": "2.0.0-beta.1" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/UI/Input.svelte: -------------------------------------------------------------------------------- 1 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /examples/solidjs/src/App.tsx: -------------------------------------------------------------------------------- 1 | import styles from './App.module.css' 2 | import { createClient } from '@supabase/supabase-js' 3 | import Selectors from './Selectors' 4 | import { 5 | customBorderRadius, 6 | customButtonColor, 7 | customSocialLayout, 8 | customTheme, 9 | } from './store' 10 | import { Auth } from '@supabase/auth-ui-solid' 11 | import { ThemeSupa } from '@supabase/auth-ui-shared' 12 | 13 | const supabase = createClient( 14 | import.meta.env.VITE_SUPABASE_URL, 15 | import.meta.env.VITE_SUPABASE_ANON_KEY 16 | ) 17 | 18 | const classes: { [key: string]: string } = { 19 | 'rgb(202, 37, 37)': styles['container-redshadow'], 20 | 'rgb(65, 163, 35)': styles['container-greenshadow'], 21 | 'rgb(8, 107, 177)': styles['container-blueshadow'], 22 | 'rgb(235, 115, 29)': styles['container-orangeshadow'], 23 | } 24 | 25 | function App() { 26 | return ( 27 |
28 |
29 |
30 | 50 |
51 |
52 | 53 |
54 | ) 55 | } 56 | 57 | export default App 58 | -------------------------------------------------------------------------------- /localization/german/de_formal.json: -------------------------------------------------------------------------------- 1 | { 2 | "sign_up": { 3 | "email_label": "E-Mail Adresse", 4 | "password_label": "Passwort erstellen", 5 | "email_input_placeholder": "Ihre E-Mail Adresse", 6 | "password_input_placeholder": "Ihr Passwort", 7 | "button_label": "Registrieren", 8 | "loading_button_label": "Registrieren ...", 9 | "social_provider_text": "Anmelden mit {{provider}}", 10 | "link_text": "Haben Sie noch kein Konto? Registrieren" 11 | }, 12 | "sign_in": { 13 | "email_label": "E-Mail Adresse", 14 | "password_label": "Passwort erstellen", 15 | "email_input_placeholder": "Ihre E-Mail Adresse", 16 | "password_input_placeholder": "Ihr Passwort", 17 | "button_label": "Anmelden", 18 | "loading_button_label": "Anmelden ...", 19 | "social_provider_text": "Anmelden mit {{provider}}", 20 | "link_text": "Haben Sie bereits ein Konto? Anmelden" 21 | }, 22 | "magic_link": { 23 | "email_input_label": "E-Mail Adresse", 24 | "email_input_placeholder": "Ihre E-Mail Adresse", 25 | "button_label": "Magischen Link senden", 26 | "loading_button_label": "Magischen Link senden ...", 27 | "link_text": "Einen magischen Link per E-Mail versenden" 28 | }, 29 | "forgotten_password": { 30 | "email_label": "E-Mail Adresse", 31 | "password_label": "Ihr Passwort", 32 | "email_input_placeholder": "Ihre E-Mail Adresse", 33 | "button_label": "Anweisungen zum Zurücksetzen des Passworts senden", 34 | "loading_button_label": "Anweisungen zum Zurücksetzen senden ...", 35 | "link_text": "Passwort vergessen?" 36 | }, 37 | "update_password": { 38 | "password_label": "Neues Passwort", 39 | "password_input_placeholder": "Ihr neues Passwort", 40 | "button_label": "Passwort aktualisieren", 41 | "loading_button_label": "Passwort aktualisieren ..." 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /localization/german/de_informal.json: -------------------------------------------------------------------------------- 1 | { 2 | "sign_up": { 3 | "email_label": "E-Mail Adresse", 4 | "password_label": "Passwort erstellen", 5 | "email_input_placeholder": "Deine E-Mail Adresse", 6 | "password_input_placeholder": "Dein Passwort", 7 | "button_label": "Registrieren", 8 | "loading_button_label": "Registrieren ...", 9 | "social_provider_text": "Anmelden mit {{provider}}", 10 | "link_text": "Hast du noch kein Konto? Registrieren" 11 | }, 12 | "sign_in": { 13 | "email_label": "E-Mail Adresse", 14 | "password_label": "Passwort erstellen", 15 | "email_input_placeholder": "Deine E-Mail Adresse", 16 | "password_input_placeholder": "Dein Passwort", 17 | "button_label": "Anmelden", 18 | "loading_button_label": "Anmelden ...", 19 | "social_provider_text": "Anmelden mit {{provider}}", 20 | "link_text": "Hast du bereits ein Konto? Anmelden" 21 | }, 22 | "magic_link": { 23 | "email_input_label": "E-Mail Adresse", 24 | "email_input_placeholder": "Deine E-Mail Adresse", 25 | "button_label": "Magischen Link senden", 26 | "loading_button_label": "Magischen Link senden ...", 27 | "link_text": "Einen magischen Link per E-Mail versenden" 28 | }, 29 | "forgotten_password": { 30 | "email_label": "E-Mail Adresse", 31 | "password_label": "Dein Passwort", 32 | "email_input_placeholder": "Deine E-Mail Adresse", 33 | "button_label": "Anweisungen zum Zurücksetzen des Passworts senden", 34 | "loading_button_label": "Anweisungen zum Zurücksetzen senden ...", 35 | "link_text": "Passwort vergessen?" 36 | }, 37 | "update_password": { 38 | "password_label": "Neues Passwort", 39 | "password_input_placeholder": "Dein neues Passwort", 40 | "button_label": "Passwort aktualisieren", 41 | "loading_button_label": "Passwort aktualisieren ..." 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/svelte/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@supabase/auth-ui-svelte", 3 | "version": "0.2.9", 4 | "type": "module", 5 | "publishConfig": { 6 | "access": "public" 7 | }, 8 | "files": [ 9 | "dist" 10 | ], 11 | "types": "./dist/index.d.ts", 12 | "exports": { 13 | "./package.json": "./package.json", 14 | ".": { 15 | "types": "./dist/index.d.ts", 16 | "svelte": "./dist/index.js" 17 | } 18 | }, 19 | "typesVersions": { 20 | ">4.0": { 21 | ".": [ 22 | "./dist/index.d.ts" 23 | ] 24 | } 25 | }, 26 | "scripts": { 27 | "build": "svelte-kit sync && svelte-package && pnpm fix:esm", 28 | "test": "playwright test", 29 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 30 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 31 | "lint": "prettier --plugin-search-dir . --check . && eslint .", 32 | "format": "prettier --plugin-search-dir . --write .", 33 | "fix:esm": "fix-esm-import-path dist/index.js" 34 | }, 35 | "dependencies": { 36 | "@stitches/core": "^1.2.8", 37 | "@supabase/auth-ui-shared": "workspace:*", 38 | "svelte": "^3.55.1" 39 | }, 40 | "devDependencies": { 41 | "@playwright/test": "^1.25.0", 42 | "@supabase/supabase-js": "^2.39.3", 43 | "@sveltejs/adapter-auto": "^2.0.0", 44 | "@sveltejs/kit": "^1.15.2", 45 | "@sveltejs/package": "^2.0.2", 46 | "@typescript-eslint/eslint-plugin": "^5.51.0", 47 | "@typescript-eslint/parser": "^5.51.0", 48 | "eslint": "^8.33.0", 49 | "eslint-config-prettier": "^8.6.0", 50 | "eslint-plugin-svelte3": "^4.0.0", 51 | "fix-esm-import-path": "^1.3.1", 52 | "prettier": "^2.8.4", 53 | "prettier-plugin-svelte": "^2.9.0", 54 | "svelte-check": "^3.0.3", 55 | "svelte-preprocess": "^5.0.1", 56 | "tslib": "^2.5.0", 57 | "typescript": "^4.9.5", 58 | "vite": "^4.5.2" 59 | }, 60 | "peerDependencies": { 61 | "@supabase/supabase-js": "^2.39.3" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/UI/Button.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 | 22 | 23 | 59 | -------------------------------------------------------------------------------- /packages/solid/src/components/Auth/UserContext.tsx: -------------------------------------------------------------------------------- 1 | import { SupabaseClient, Session, User } from "@supabase/supabase-js"; 2 | import { 3 | createContext, 4 | createEffect, 5 | createSignal, 6 | useContext, 7 | } from "solid-js"; 8 | import { createStore } from "solid-js/store"; 9 | 10 | export interface AuthSession { 11 | user: User | null; 12 | session: Session | null; 13 | } 14 | 15 | const UserContext = createContext({ user: null, session: null}); 16 | 17 | export interface Props { 18 | supabaseClient: SupabaseClient; 19 | [propName: string]: any; 20 | } 21 | 22 | export const UserContextProvider = (props: Props) => { 23 | const { supabaseClient } = props; 24 | const [session, setSession] = createSignal(null); 25 | const [user, setUser] = createSignal(null); 26 | 27 | createEffect(() => { 28 | setUser(session()?.user ?? null); 29 | }); 30 | 31 | async function getSupabaseSession() { 32 | const { data } = await supabaseClient.auth.getSession(); 33 | setSession(data.session); 34 | setUser(data.session?.user ?? null); 35 | } 36 | 37 | createEffect(() => { 38 | getSupabaseSession(); 39 | 40 | const { data: authListener } = supabaseClient.auth.onAuthStateChange( 41 | async (event, session) => { 42 | setSession(session); 43 | setUser(session?.user ?? null); 44 | } 45 | ); 46 | 47 | return () => { 48 | authListener?.subscription.unsubscribe(); 49 | }; 50 | }); 51 | 52 | const [value, setValue] = createStore({ 53 | session: session(), 54 | user: user(), 55 | }); 56 | //@ts-ignore 57 | return ; 58 | }; 59 | 60 | export const useUser = () => { 61 | const context = useContext(UserContext); 62 | if (context === undefined) { 63 | throw new Error(`useUser must be used within a UserContextProvider.`); 64 | } 65 | return context; 66 | }; 67 | -------------------------------------------------------------------------------- /localization/spanish/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "sign_up": { 3 | "email_label": "Dirección de correo electrónico", 4 | "password_label": "Crear contraseña", 5 | "email_input_placeholder": "Tu dirección de correo electrónico", 6 | "password_input_placeholder": "Tu contraseña", 7 | "button_label": "Registrarse", 8 | "loading_button_label": "Registrando...", 9 | "social_provider_text": "Iniciar sesión con {{provider}}", 10 | "link_text": "¿No tienes una cuenta? Regístrate" 11 | }, 12 | "sign_in": { 13 | "email_label": "Dirección de correo electrónico", 14 | "password_label": "Contraseña", 15 | "email_input_placeholder": "Tu dirección de correo electrónico", 16 | "password_input_placeholder": "Tu contraseña", 17 | "button_label": "Iniciar sesión", 18 | "loading_button_label": "Iniciando sesión...", 19 | "social_provider_text": "Iniciar sesión con {{provider}}", 20 | "link_text": "¿Ya tienes una cuenta? Iniciar sesión" 21 | }, 22 | "magic_link": { 23 | "email_input_label": "Dirección de correo electrónico", 24 | "email_input_placeholder": "Tu dirección de correo electrónico", 25 | "button_label": "Enviar enlace mágico", 26 | "loading_button_label": "Enviando enlace mágico...", 27 | "link_text": "Enviar un enlace mágico por correo electrónico" 28 | }, 29 | "forgotten_password": { 30 | "email_label": "Dirección de correo electrónico", 31 | "password_label": "Tu contraseña", 32 | "email_input_placeholder": "Tu dirección de correo electrónico", 33 | "button_label": "Enviar instrucciones para restablecer la contraseña", 34 | "loading_button_label": "Enviando instrucciones...", 35 | "link_text": "¿Olvidaste tu contraseña?" 36 | }, 37 | "update_password": { 38 | "password_label": "Nueva contraseña", 39 | "password_input_placeholder": "Tu nueva contraseña", 40 | "button_label": "Actualizar contraseña", 41 | "loading_button_label": "Actualizando contraseña..." 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/react/src/components/UI/Input.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | 5 | const inputDefaultStyles = css({ 6 | fontFamily: '$inputFontFamily', 7 | background: '$inputBackground', 8 | borderRadius: '$inputBorderRadius', 9 | padding: '$inputPadding', 10 | cursor: 'text', 11 | borderWidth: '$inputBorderWidth', 12 | borderColor: '$inputBorder', 13 | borderStyle: 'solid', 14 | fontSize: '$baseInputSize', 15 | width: '100%', 16 | color: '$inputText', 17 | boxSizing: 'border-box', 18 | '&:hover': { 19 | borderColor: '$inputBorderHover', 20 | outline: 'none', 21 | }, 22 | '&:focus': { 23 | borderColor: '$inputBorderFocus', 24 | outline: 'none', 25 | }, 26 | '&::placeholder': { 27 | color: '$inputPlaceholder', 28 | letterSpacing: 'initial', 29 | }, 30 | transitionProperty: 'background-color, border', 31 | transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)', 32 | transitionDuration: '100ms', 33 | variants: { 34 | type: { 35 | default: { 36 | letterSpacing: '0px', 37 | }, 38 | password: { 39 | letterSpacing: '0px', 40 | }, 41 | }, 42 | }, 43 | }) 44 | 45 | interface InputProps extends React.InputHTMLAttributes { 46 | children?: React.ReactNode 47 | type: 'text' | 'password' | 'email' 48 | appearance?: Appearance 49 | } 50 | 51 | const Input: React.FC = ({ children, appearance, ...props }) => { 52 | const classNames = generateClassNames( 53 | 'input', 54 | inputDefaultStyles({ 55 | type: props.type === 'password' ? 'password' : 'default', 56 | }), 57 | appearance 58 | ) 59 | 60 | return ( 61 | 66 | {children} 67 | 68 | ) 69 | } 70 | 71 | export { Input } 72 | -------------------------------------------------------------------------------- /packages/svelte/README.md: -------------------------------------------------------------------------------- 1 | # Supabase Auth UI Svelte 2 | 3 | Supabase Auth UI is a collection of pre built UI components that work seamlessly with @supabase/auth-helpers. 4 | 5 | The main purpose of these components is to allow developers to get working on their apps quickly, but also be able to use their own style/css. 6 | 7 | Auth UI is kept deliberately separate from @supabase/auth-helpers so that developers can migrate away from pre-built UI components as their UI system naturally matures. 8 | 9 | ## How to use? 10 | 11 | In order to make use of the Auth UI Svelte you'll need to have a few things ready first. Let's talk about those things step by step: 12 | 13 | #### Install Supabase and the Svelte Supabase-auth-ui 14 | 15 | First let us install Supabase into our Svelte project. 16 | 17 | ```bash 18 | npm install @supabase/supabase-js @supabase/auth-ui-svelte 19 | # or 20 | pnpm add @supabase/supabase-js @supabase/auth-ui-svelte 21 | # or 22 | yarn add @supabase/supabase-js @supabase/auth-ui-svelte 23 | ``` 24 | 25 | #### Create you Supabase client 26 | 27 | Let's create our Supabase client 28 | 29 | ```js 30 | import { createClient } from '@supabase/supabase-js' 31 | 32 | const supabase = createClient( 33 | '', 34 | '' 35 | ) 36 | ``` 37 | 38 | #### Passing your Supabase client to the Auth component as a prop 39 | 40 | ```js 41 | 50 | 51 | 52 | ``` 53 | 54 | And voila we're done! This will give you the bare minimum of what you'll need to get started with supabase-auth-ui. In order to add styling to your Auth component checkout our full documentation [here](https://supabase.com/docs/guides/auth/auth-helpers/auth-ui#customization) -------------------------------------------------------------------------------- /packages/solid/src/components/UI/Input.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { Component, JSX, JSXElement } from 'solid-js' 3 | import { generateClassNames } from '@supabase/auth-ui-shared' 4 | import { Appearance } from '../../types' 5 | 6 | const inputDefaultStyles = css({ 7 | fontFamily: '$inputFontFamily', 8 | background: '$inputBackground', 9 | borderRadius: '$inputBorderRadius', 10 | padding: '$inputPadding', 11 | cursor: 'text', 12 | borderWidth: '$inputBorderWidth', 13 | borderColor: '$inputBorder', 14 | borderStyle: 'solid', 15 | fontSize: '$baseInputSize', 16 | width: '100%', 17 | color: '$inputText', 18 | boxSizing: 'border-box', 19 | '&:hover': { 20 | borderColor: '$inputBorderHover', 21 | outline: 'none', 22 | }, 23 | '&:focus': { 24 | borderColor: '$inputBorderFocus', 25 | outline: 'none', 26 | }, 27 | '&::placeholder': { 28 | color: '$inputPlaceholder', 29 | letterSpacing: 'initial', 30 | }, 31 | transitionProperty: 'background-color, border', 32 | transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)', 33 | transitionDuration: '100ms', 34 | variants: { 35 | type: { 36 | default: { 37 | letterSpacing: '0px', 38 | }, 39 | password: { 40 | letterSpacing: '0px', 41 | }, 42 | }, 43 | }, 44 | }) 45 | 46 | interface InputProps extends JSX.InputHTMLAttributes { 47 | children?: JSXElement 48 | type: 'text' | 'password' | 'email' 49 | appearance?: Appearance 50 | } 51 | 52 | const Input: Component = (props) => { 53 | const classNames = generateClassNames( 54 | 'input', 55 | inputDefaultStyles({ 56 | type: props.type === 'password' ? 'password' : 'default', 57 | }), 58 | props.appearance 59 | ) 60 | 61 | return ( 62 | 67 | {props.children} 68 | 69 | ) 70 | } 71 | 72 | export { Input } 73 | -------------------------------------------------------------------------------- /packages/react/src/components/UI/Loader.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | 5 | const loaderDefaultStyles = css({ 6 | borderRadius: '50%', 7 | width: '10em', 8 | height: '10em', 9 | margin: '60px auto', 10 | fontSize: '10px', 11 | position: 'relative', 12 | textIndent: '-9999em', 13 | 14 | borderTop: '1.1em solid rgba(255, 255, 255, 0.2)', 15 | borderRight: '1.1em solid rgba(255, 255, 255, 0.2)', 16 | borderBottom: '1.1em solid rgba(255, 255, 255, 0.2)', 17 | borderLeft: '1.1em solid #ffffff', 18 | 19 | '-webkit-transform': 'translateZ(0)', 20 | '-ms-transform': 'translateZ(0)', 21 | transform: 'translateZ(0)', 22 | '-webkit-animation': 'load8 1.1s infinite linear', 23 | animation: 'load8 1.1s infinite linear', 24 | 25 | '&:after': { 26 | borderRadius: '50%', 27 | width: '10em', 28 | height: '10em', 29 | }, 30 | 31 | // @-webkit-keyframes load8 { 32 | // 0% { 33 | // -webkit-transform: rotate(0deg); 34 | // transform: rotate(0deg); 35 | // } 36 | // 100% { 37 | // -webkit-transform: rotate(360deg); 38 | // transform: rotate(360deg); 39 | // } 40 | // } 41 | // @keyframes load8 { 42 | // 0% { 43 | // -webkit-transform: rotate(0deg); 44 | // transform: rotate(0deg); 45 | // } 46 | // 100% { 47 | // -webkit-transform: rotate(360deg); 48 | // transform: rotate(360deg); 49 | // } 50 | // } 51 | }) 52 | 53 | export interface LoaderProps extends React.HtmlHTMLAttributes { 54 | appearance?: Appearance 55 | } 56 | 57 | function Loader({ appearance, ...props }: LoaderProps) { 58 | const classNames = generateClassNames( 59 | 'loader', 60 | loaderDefaultStyles(), 61 | appearance 62 | ) 63 | 64 | return ( 65 |
70 | ) 71 | } 72 | 73 | export { Loader } 74 | -------------------------------------------------------------------------------- /packages/solid/src/components/UI/Loader.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | import { JSX } from 'solid-js/jsx-runtime' 5 | 6 | const loaderDefaultStyles = css({ 7 | borderRadius: '50%', 8 | width: '10em', 9 | height: '10em', 10 | margin: '60px auto', 11 | fontSize: '10px', 12 | position: 'relative', 13 | textIndent: '-9999em', 14 | 15 | borderTop: '1.1em solid rgba(255, 255, 255, 0.2)', 16 | borderRight: '1.1em solid rgba(255, 255, 255, 0.2)', 17 | borderBottom: '1.1em solid rgba(255, 255, 255, 0.2)', 18 | borderLeft: '1.1em solid #ffffff', 19 | 20 | '-webkit-transform': 'translateZ(0)', 21 | '-ms-transform': 'translateZ(0)', 22 | transform: 'translateZ(0)', 23 | '-webkit-animation': 'load8 1.1s infinite linear', 24 | animation: 'load8 1.1s infinite linear', 25 | 26 | '&:after': { 27 | borderRadius: '50%', 28 | width: '10em', 29 | height: '10em', 30 | }, 31 | 32 | // @-webkit-keyframes load8 { 33 | // 0% { 34 | // -webkit-transform: rotate(0deg); 35 | // transform: rotate(0deg); 36 | // } 37 | // 100% { 38 | // -webkit-transform: rotate(360deg); 39 | // transform: rotate(360deg); 40 | // } 41 | // } 42 | // @keyframes load8 { 43 | // 0% { 44 | // -webkit-transform: rotate(0deg); 45 | // transform: rotate(0deg); 46 | // } 47 | // 100% { 48 | // -webkit-transform: rotate(360deg); 49 | // transform: rotate(360deg); 50 | // } 51 | // } 52 | }) 53 | 54 | export interface LoaderProps extends JSX.HTMLAttributes { 55 | appearance?: Appearance 56 | } 57 | 58 | function Loader(props: LoaderProps) { 59 | const classNames = generateClassNames( 60 | 'loader', 61 | loaderDefaultStyles(), 62 | props.appearance 63 | ) 64 | 65 | return ( 66 |
71 | ) 72 | } 73 | 74 | export { Loader } 75 | -------------------------------------------------------------------------------- /packages/solid/src/components/UI/Button.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | import { JSXElement, JSX, Component, createMemo, createEffect } from 'solid-js' 5 | 6 | const buttonDefaultStyles = css({ 7 | fontFamily: '$buttonFontFamily', 8 | display: 'flex', 9 | alignItems: 'center', 10 | justifyContent: 'center', 11 | gap: '8px', 12 | borderRadius: '$borderRadiusButton', 13 | fontSize: '$baseButtonSize', 14 | padding: '$buttonPadding', 15 | cursor: 'pointer', 16 | borderWidth: '$buttonBorderWidth', 17 | borderStyle: 'solid', 18 | width: '100%', 19 | 20 | transitionProperty: 'background-color', 21 | transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)', 22 | transitionDuration: '100ms', 23 | 24 | variants: { 25 | color: { 26 | default: { 27 | backgroundColor: '$defaultButtonBackground', 28 | color: '$defaultButtonText', 29 | borderColor: '$defaultButtonBorder', 30 | '&:hover': { 31 | backgroundColor: '$defaultButtonBackgroundHover', 32 | }, 33 | }, 34 | primary: { 35 | backgroundColor: '$brand', 36 | color: '$brandButtonText', 37 | borderColor: '$brandAccent', 38 | '&:hover': { 39 | backgroundColor: '$brandAccent', 40 | }, 41 | }, 42 | }, 43 | }, 44 | }) 45 | 46 | interface ButtonProps extends JSX.ButtonHTMLAttributes { 47 | children: JSXElement 48 | icon?: JSXElement 49 | color?: 'default' | 'primary' 50 | loading?: boolean 51 | appearance?: Appearance 52 | } 53 | 54 | const Button: Component = (props) => { 55 | const classNames = createMemo(() => 56 | generateClassNames( 57 | 'button', 58 | buttonDefaultStyles({ color: props.color }), 59 | props.appearance 60 | ) 61 | ) 62 | 63 | return ( 64 | 73 | ) 74 | } 75 | 76 | export { Button } 77 | -------------------------------------------------------------------------------- /packages/react/src/components/UI/Button.tsx: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/core' 2 | import { generateClassNames } from '@supabase/auth-ui-shared' 3 | import { Appearance } from '../../types' 4 | 5 | const buttonDefaultStyles = css({ 6 | fontFamily: '$buttonFontFamily', 7 | display: 'flex', 8 | alignItems: 'center', 9 | justifyContent: 'center', 10 | gap: '8px', 11 | borderRadius: '$borderRadiusButton', 12 | fontSize: '$baseButtonSize', 13 | padding: '$buttonPadding', 14 | cursor: 'pointer', 15 | borderWidth: '$buttonBorderWidth', 16 | borderStyle: 'solid', 17 | width: '100%', 18 | 19 | transitionProperty: 'background-color', 20 | transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)', 21 | transitionDuration: '100ms', 22 | '&:disabled': { 23 | opacity: 0.7, 24 | cursor: 'unset', 25 | }, 26 | variants: { 27 | color: { 28 | default: { 29 | backgroundColor: '$defaultButtonBackground', 30 | color: '$defaultButtonText', 31 | borderColor: '$defaultButtonBorder', 32 | '&:hover:not(:disabled)': { 33 | backgroundColor: '$defaultButtonBackgroundHover', 34 | }, 35 | }, 36 | primary: { 37 | backgroundColor: '$brand', 38 | color: '$brandButtonText', 39 | borderColor: '$brandAccent', 40 | '&:hover:not(:disabled)': { 41 | backgroundColor: '$brandAccent', 42 | }, 43 | }, 44 | }, 45 | }, 46 | }) 47 | 48 | interface ButtonProps extends React.ButtonHTMLAttributes { 49 | children: React.ReactNode 50 | icon?: React.ReactNode 51 | color?: 'default' | 'primary' 52 | loading?: boolean 53 | appearance?: Appearance 54 | } 55 | 56 | const Button: React.FC = ({ 57 | children, 58 | color = 'default', 59 | appearance, 60 | icon, 61 | loading = false, 62 | ...props 63 | }) => { 64 | const classNames = generateClassNames( 65 | 'button', 66 | buttonDefaultStyles({ color: color }), 67 | appearance 68 | ) 69 | 70 | return ( 71 | 80 | ) 81 | } 82 | 83 | export { Button } 84 | -------------------------------------------------------------------------------- /examples/solidjs/src/muiswitch.tsx: -------------------------------------------------------------------------------- 1 | import styled from '@suid/material/styles/styled' 2 | import Switch from '@suid/material/Switch'; 3 | 4 | export const MaterialUISwitch = styled(Switch)(({ theme }) => ({ 5 | width: 62, 6 | height: 34, 7 | padding: 7, 8 | '& .MuiSwitch-switchBase': { 9 | margin: 1, 10 | padding: 0, 11 | transform: 'translateX(6px)', 12 | '&.Mui-checked': { 13 | color: '#fff', 14 | transform: 'translateX(22px)', 15 | '& .MuiSwitch-thumb:before': { 16 | backgroundImage: `url('data:image/svg+xml;utf8,')`, 19 | }, 20 | '& + .MuiSwitch-track': { 21 | opacity: 1, 22 | backgroundColor: theme.palette.mode === 'dark' ? '#8796A5' : '#aab4be', 23 | }, 24 | }, 25 | }, 26 | '& .MuiSwitch-thumb': { 27 | backgroundColor: theme.palette.mode === 'dark' ? '#003892' : '#001e3c', 28 | width: 32, 29 | height: 32, 30 | '&:before': { 31 | content: "''", 32 | position: 'absolute', 33 | width: '100%', 34 | height: '100%', 35 | left: 0, 36 | top: 0, 37 | backgroundRepeat: 'no-repeat', 38 | backgroundPosition: 'center', 39 | backgroundImage: `url('data:image/svg+xml;utf8,')`, 42 | }, 43 | }, 44 | '& .MuiSwitch-track': { 45 | opacity: 1, 46 | backgroundColor: theme.palette.mode === 'dark' ? '#8796A5' : '#aab4be', 47 | borderRadius: 20 / 2, 48 | }, 49 | })); -------------------------------------------------------------------------------- /packages/shared/src/localization/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "sign_up": { 3 | "email_label": "Email address", 4 | "password_label": "Create a Password", 5 | "email_input_placeholder": "Your email address", 6 | "password_input_placeholder": "Your password", 7 | "button_label": "Sign up", 8 | "loading_button_label": "Signing up ...", 9 | "social_provider_text": "Sign in with {{provider}}", 10 | "link_text": "Don't have an account? Sign up", 11 | "confirmation_text": "Check your email for the confirmation link" 12 | }, 13 | "sign_in": { 14 | "email_label": "Email address", 15 | "password_label": "Your Password", 16 | "email_input_placeholder": "Your email address", 17 | "password_input_placeholder": "Your password", 18 | "button_label": "Sign in", 19 | "loading_button_label": "Signing in ...", 20 | "social_provider_text": "Sign in with {{provider}}", 21 | "link_text": "Already have an account? Sign in" 22 | }, 23 | "magic_link": { 24 | "email_input_label": "Email address", 25 | "email_input_placeholder": "Your email address", 26 | "button_label": "Send Magic Link", 27 | "loading_button_label": "Sending Magic Link ...", 28 | "link_text": "Send a magic link email", 29 | "confirmation_text": "Check your email for the magic link" 30 | }, 31 | "forgotten_password": { 32 | "email_label": "Email address", 33 | "password_label": "Your Password", 34 | "email_input_placeholder": "Your email address", 35 | "button_label": "Send reset password instructions", 36 | "loading_button_label": "Sending reset instructions ...", 37 | "link_text": "Forgot your password?", 38 | "confirmation_text": "Check your email for the password reset link" 39 | }, 40 | "update_password": { 41 | "password_label": "New password", 42 | "password_input_placeholder": "Your new password", 43 | "button_label": "Update password", 44 | "loading_button_label": "Updating password ...", 45 | "confirmation_text": "Your password has been updated" 46 | }, 47 | "verify_otp": { 48 | "email_input_label": "Email address", 49 | "email_input_placeholder": "Your email address", 50 | "phone_input_label": "Phone number", 51 | "phone_input_placeholder": "Your phone number", 52 | "token_input_label": "Token", 53 | "token_input_placeholder": "Your Otp token", 54 | "button_label": "Verify token", 55 | "loading_button_label": "Signing in ..." 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/solid/README.md: -------------------------------------------------------------------------------- 1 | # Supabase Auth UI Solid.js 2 | 3 | Supabase Auth UI is a collection of pre built UI components that work seamlessly with @supabase/auth-helpers. 4 | 5 | The main purpose of these components is to allow developers to get working on their apps quickly, but also be able to use their own style/css. 6 | 7 | Auth UI is kept deliberately separate from @supabase/auth-helpers so that developers can migrate away from pre-built UI components as their UI system naturally matures. 8 | 9 | ## How to use? 10 | 11 | In order to make use of the Solid.js Supabase Auth UI you'll need to have a few things ready first. Let's talk about those things step by step: 12 | 13 | #### Install Supabase and the Solid.js Supabase-auth-ui 14 | 15 | First let us install Supabase into our Solid.js project. 16 | 17 | ```bash 18 | npm install @supabase/supabase-js @supabase/auth-ui-solid 19 | # or 20 | yarn add @supabase/supabase-js @supabase/auth-ui-solid 21 | ``` 22 | 23 | #### Create you Supabase client 24 | 25 | Let's create our Supabase client 26 | 27 | ```js 28 | import { createClient } from '@supabase/supabase-js' 29 | 30 | const supabase = createClient( 31 | '', 32 | '' 33 | ) 34 | ``` 35 | 36 | #### Passing your Supabase client to the Auth component as a prop 37 | 38 | ```js 39 | import { createClient } from '@supabase/supabase-js' 40 | import { Auth } from '@supabase/auth-ui-solid' 41 | 42 | const supabase = createClient( 43 | '', 44 | '' 45 | ) 46 | 47 | const App = () => 48 | ``` 49 | 50 | And voila we're done! This will give you the bare minimum of what you'll need to get started with supabase-auth-ui. In order to add styling to your Auth component checkout our full documentation [here](https://supabase.com/docs/guides/auth/auth-helpers/auth-ui#customization) 51 | 52 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/interfaces/SocialAuth.svelte: -------------------------------------------------------------------------------- 1 | 54 | 55 | {#if providers.length} 56 | 57 | 62 | {#each providers as provider} 63 | 76 | {/each} 77 | 78 | 79 | {#if !onlyThirdPartyProviders} 80 | 81 | {/if} 82 | {/if} 83 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/interfaces/MagicLink.svelte: -------------------------------------------------------------------------------- 1 | 39 | 40 | 83 | 84 | 89 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/interfaces/ForgottenPassword.svelte: -------------------------------------------------------------------------------- 1 | 36 | 37 |
38 | 39 | 40 |
41 | 42 | 52 |
53 | 56 |
57 | 58 | {#if showLinks} 59 | { 61 | e.preventDefault(); 62 | authView = VIEWS.SIGN_IN; 63 | }} 64 | href="#auth-magic-link" 65 | {appearance}>{i18n?.sign_in?.link_text} 67 | {/if} 68 | {#if message} 69 | 70 | {message} 71 | 72 | {/if} 73 | {#if error} 74 | 75 | {error} 76 | 77 | {/if} 78 |
79 |
80 | 81 | 86 | -------------------------------------------------------------------------------- /packages/react/src/components/Auth/interfaces/UpdatePassword.tsx: -------------------------------------------------------------------------------- 1 | import { SupabaseClient } from '@supabase/supabase-js' 2 | import React, { useState } from 'react' 3 | import { I18nVariables } from '@supabase/auth-ui-shared' 4 | import { Appearance } from '../../../types' 5 | import { Button, Container, Input, Label, Message } from './../../UI/index.js' 6 | 7 | function UpdatePassword({ 8 | supabaseClient, 9 | i18n, 10 | appearance, 11 | passwordLimit = false, 12 | }: { 13 | supabaseClient: SupabaseClient 14 | i18n?: I18nVariables 15 | appearance?: Appearance 16 | passwordLimit?: boolean 17 | }) { 18 | const [password, setPassword] = useState('') 19 | const [error, setError] = useState('') 20 | const [message, setMessage] = useState('') 21 | const [loading, setLoading] = useState(false) 22 | 23 | const handlePasswordReset = async (e: React.FormEvent) => { 24 | e.preventDefault() 25 | setError('') 26 | setMessage('') 27 | setLoading(true) 28 | if (passwordLimit && password.length > 72) { 29 | setError('Password exceeds maxmium length of 72 characters') 30 | setLoading(false) 31 | return 32 | } 33 | const { error } = await supabaseClient.auth.updateUser({ password }) 34 | if (error) setError(error.message) 35 | else setMessage(i18n?.update_password?.confirmation_text as string) 36 | setLoading(false) 37 | } 38 | 39 | const labels = i18n?.update_password 40 | 41 | return ( 42 |
43 | 44 |
45 | 48 | ) => 55 | setPassword(e.target.value) 56 | } 57 | appearance={appearance} 58 | /> 59 |
60 | 68 | {message && {message}} 69 | {error && ( 70 | 71 | {error} 72 | 73 | )} 74 |
75 |
76 | ) 77 | } 78 | 79 | export { UpdatePassword } 80 | -------------------------------------------------------------------------------- /examples/solidjs/src/App.module.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .logo { 6 | animation: logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | pointer-events: none; 9 | } 10 | 11 | .container-redshadow { 12 | min-width: 300px; 13 | box-shadow: -2px 1px 69px 5px rgb(202, 37, 37); 14 | -webkit-box-shadow: -2px 1px 69px 5px rgb(202, 37, 37); 15 | -moz-box-shadow: -2px 1px 69px 5px rgb(202, 37, 37); 16 | padding: 2rem; 17 | border-radius: 1rem; 18 | } 19 | 20 | .container-greenshadow { 21 | min-width: 300px; 22 | box-shadow: -2px 1px 69px 5px rgb(65, 163, 35); 23 | -webkit-box-shadow: -2px 1px 69px 5px rgb(65, 163, 35); 24 | -moz-box-shadow: -2px 1px 69px 5px rgb(65, 163, 35); 25 | padding: 2rem; 26 | border-radius: 1rem; 27 | } 28 | 29 | .container-blueshadow { 30 | min-width: 300px; 31 | box-shadow: -2px 1px 69px 5px rgb(8, 107, 177); 32 | -webkit-box-shadow: -2px 1px 69px 5px rgb(8, 107, 177); 33 | -moz-box-shadow: -2px 1px 69px 5px rgb(8, 107, 177); 34 | padding: 2rem; 35 | border-radius: 1rem; 36 | } 37 | 38 | .container-orangeshadow { 39 | min-width: 300px; 40 | box-shadow: -2px 1px 69px 5px rgb(235, 115, 29); 41 | -webkit-box-shadow: -2px 1px 69px 5px rgb(235, 115, 29); 42 | -moz-box-shadow: -2px 1px 69px 5px rgb(235, 115, 29); 43 | padding: 2rem; 44 | border-radius: 1rem; 45 | } 46 | 47 | .auth-container { 48 | width: 50%; 49 | display: flex; 50 | align-items: center; 51 | justify-content: center; 52 | } 53 | 54 | .selectors-container { 55 | width: 50%; 56 | padding: 2rem; 57 | } 58 | 59 | .solidrow { 60 | display: flex; 61 | align-items: center; 62 | } 63 | 64 | .toggles-grid { 65 | display: grid; 66 | grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); 67 | gap: 1rem; 68 | } 69 | 70 | .header { 71 | min-height: 100vh; 72 | max-width: 1200px; 73 | margin-inline: auto; 74 | display: flex; 75 | flex-direction: row; 76 | align-items: center; 77 | justify-content: space-around; 78 | font-size: calc(10px + 2vmin); 79 | color: white; 80 | } 81 | 82 | .link { 83 | color: #b318f0; 84 | } 85 | 86 | @media (max-width: 600px) { 87 | .header { 88 | background-color: #282c34; 89 | min-height: 100vh; 90 | display: flex; 91 | flex-direction: column; 92 | align-items: center; 93 | justify-content: space-around; 94 | font-size: calc(10px + 2vmin); 95 | color: white; 96 | } 97 | 98 | .container{ 99 | min-width: 250px; 100 | } 101 | 102 | .selectors-container { 103 | width: fit-content; 104 | max-width: 80vw; 105 | margin-inline:auto ; 106 | } 107 | 108 | .auth-container{ 109 | width: fit-content; 110 | } 111 | } -------------------------------------------------------------------------------- /localization/french/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "sign_up": { 3 | "email_label": "Adresse e-mail", 4 | "password_label": "Mot de passe", 5 | "email_input_placeholder": "Votre adresse e-mail", 6 | "password_input_placeholder": "Votre mot de passe", 7 | "button_label": "S'inscrire", 8 | "loading_button_label": "Inscription ...", 9 | "social_provider_text": "S'inscrire avec {{provider}}", 10 | "link_text": "Pas de compte ? Inscrivez-vous", 11 | "confirmation_text": "Vérifiez votre boîte de réception pour le lien de confirmation" 12 | }, 13 | "sign_in": { 14 | "email_label": "Adresse e-mail", 15 | "password_label": "Mot de passe", 16 | "email_input_placeholder": "Votre adresse e-mail", 17 | "password_input_placeholder": "Votre mot de passe", 18 | "button_label": "Se connecter", 19 | "loading_button_label": "Connexion ...", 20 | "social_provider_text": "S'identifier avec {{provider}}", 21 | "link_text": "Déjà un compte ? Connectez-vous" 22 | }, 23 | "magic_link": { 24 | "email_input_label": "Adresse e-mail", 25 | "email_input_placeholder": "Votre adresse e-mail", 26 | "button_label": "Envoyer le lien magique", 27 | "loading_button_label": "Envoi du lien magique ...", 28 | "link_text": "Envoie un e-mail contenant un lien magique", 29 | "confirmation_text": "Vérifiez votre boîte de réception pour le lien magique" 30 | }, 31 | "forgotten_password": { 32 | "email_label": "Adresse e-mail", 33 | "password_label": "Mot de passe", 34 | "email_input_placeholder": "Votre adresse e-mail", 35 | "button_label": "Envoyer les instructions de réinitialisation de mot de passe", 36 | "loading_button_label": "Envoie des instructions ...", 37 | "link_text": "Vous avez oublié votre mot de passe ?", 38 | "confirmation_text": "Vérifiez votre boîte de réception pour le lien de confirmation de réinitialisation" 39 | }, 40 | "update_password": { 41 | "password_label": "Nouveau mot de passe", 42 | "password_input_placeholder": "Votre nouveau mot de passe", 43 | "button_label": "Modifier le mot de passe", 44 | "loading_button_label": "Modification du mot de passe ...", 45 | "confirmation_text": "Votre mot de passe a été modifié" 46 | }, 47 | "verify_otp": { 48 | "email_input_label": "Adresse e-mail", 49 | "email_input_placeholder": "Votre adresse e-mail", 50 | "phone_input_label": "Numéro de téléphone", 51 | "phone_input_placeholder": "Votre numéro de téléphone", 52 | "token_input_label": "Code", 53 | "token_input_placeholder": "Votre code unique", 54 | "button_label": "Vérifier le code", 55 | "loading_button_label": "Connexion ..." 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/svelte/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @supabase/auth-ui-svelte 2 | 3 | ## 0.2.9 4 | 5 | ### Patch Changes 6 | 7 | - ac80a298: fix: update password placeholder prop 8 | 9 | ## 0.2.8 10 | 11 | ### Patch Changes 12 | 13 | - ae22ff23: Message styling change 14 | 15 | ## 0.2.7 16 | 17 | ### Patch Changes 18 | 19 | - Updated dependencies [a8f9395d] 20 | - @supabase/auth-ui-shared@0.1.8 21 | 22 | ## 0.2.6 23 | 24 | ### Patch Changes 25 | 26 | - 4969cb44: Fix button label loading state 27 | 28 | ## 0.2.5 29 | 30 | ### Patch Changes 31 | 32 | - a80400e2: Fix password letter spacing 33 | - 819666db: Make additionalData optional by default 34 | - Updated dependencies [2b252910] 35 | - @supabase/auth-ui-shared@0.1.7 36 | 37 | ## 0.2.4 38 | 39 | ### Patch Changes 40 | 41 | - 75a62d3e: Add Kakao icon 42 | 43 | ## 0.2.3 44 | 45 | ### Patch Changes 46 | 47 | - da4efa6e: fix: pass the missing redirectTo field to ForgottenPassword component. 48 | 49 | ## 0.2.2 50 | 51 | ### Patch Changes 52 | 53 | - 8ca7a586: Add additional data to component to store in user_metadata 54 | - Updated dependencies [8ca7a586] 55 | - @supabase/auth-ui-shared@0.1.6 56 | 57 | ## 0.2.1 58 | 59 | ### Patch Changes 60 | 61 | - 65e36a57: Add verify otp component 62 | - Updated dependencies [3aa2c54d] 63 | - @supabase/auth-ui-shared@0.1.5 64 | 65 | ## 0.2.0 66 | 67 | ### Minor Changes 68 | 69 | - 74821092: Add individual components to Svelte Auth UI 70 | 71 | ## 0.1.6 72 | 73 | ### Patch Changes 74 | 75 | - d5052260: Add providerScopes property for setting social auth scopes 76 | - Updated dependencies [d5052260] 77 | - @supabase/auth-ui-shared@0.1.4 78 | 79 | ## 0.1.5 80 | 81 | ### Patch Changes 82 | 83 | - 42d2fd91: Change UpdatePassword component input type to password 84 | 85 | ## 0.1.4 86 | 87 | ### Patch Changes 88 | 89 | - a814f486: Change icon size default change to 21px 90 | 91 | ## 0.1.3 92 | 93 | ### Patch Changes 94 | 95 | - 11ebb978: Update i18n for confirmation messages 96 | - Updated dependencies [11ebb978] 97 | - @supabase/auth-ui-shared@0.1.3 98 | 99 | ## 0.1.2 100 | 101 | ### Patch Changes 102 | 103 | - Updated dependencies [b8e6e3b4] 104 | - Updated dependencies [b8e6e3b4] 105 | - @supabase/auth-ui-shared@0.1.2 106 | 107 | ## 0.1.1 108 | 109 | ### Patch Changes 110 | 111 | - 121e88d1: Add html input autofocus 112 | - 121e88d1: Add event listener to show update form on password reset 113 | - e1fa4ee4: Update forms to select input when label is pressed 114 | - 32d5d0ef: Update to handle templated variable for provider 115 | - Updated dependencies [0d794741] 116 | - @supabase/auth-ui-shared@0.1.1 117 | 118 | ## 0.1.0 119 | 120 | ### Minor Changes 121 | 122 | - a7b625f7: Using shared package with Auth UI Svelte 123 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/interfaces/UpdatePassword.svelte: -------------------------------------------------------------------------------- 1 | 41 | 42 |
43 | 44 | 45 |
46 | 49 | 59 |
60 | 65 |
66 | 67 | {#if showLinks} 68 | { 70 | e.preventDefault(); 71 | authView = VIEWS.SIGN_IN; 72 | }} 73 | href="#auth-magic-link" 74 | {appearance}>{i18n?.sign_in?.link_text} 76 | {/if} 77 | {#if message} 78 | 79 | {message} 80 | 81 | {/if} 82 | {#if error} 83 | 84 | {error} 85 | 86 | {/if} 87 |
88 |
89 | 90 | 95 | -------------------------------------------------------------------------------- /packages/solid/src/components/Auth/interfaces/UpdatePassword.tsx: -------------------------------------------------------------------------------- 1 | import { SupabaseClient } from '@supabase/supabase-js' 2 | import { createSignal, Show } from 'solid-js' 3 | import { I18nVariables } from '@supabase/auth-ui-shared' 4 | import { Appearance, FormEvent } from '../../../types' 5 | import { Button, Container, Input, Label, Message } from '../../UI' 6 | 7 | function UpdatePassword(props: { 8 | supabaseClient: SupabaseClient 9 | i18n: I18nVariables 10 | passwordLimit: boolean 11 | appearance?: Appearance 12 | }) { 13 | const [password, setPassword] = createSignal('') 14 | const [error, setError] = createSignal('') 15 | const [message, setMessage] = createSignal('') 16 | const [loading, setLoading] = createSignal(false) 17 | 18 | const handlePasswordReset = async (e: FormEvent) => { 19 | e.preventDefault() 20 | setError('') 21 | setMessage('') 22 | setLoading(true) 23 | if (props.passwordLimit && password().length > 72) { 24 | setError('Password exceeds maxmium length of 72 characters') 25 | setLoading(false) 26 | return 27 | } 28 | const { error } = await props.supabaseClient.auth.updateUser({ 29 | password: password(), 30 | }) 31 | if (error) setError(error.message) 32 | else setMessage(props.i18n.update_password?.confirmation_text as string) 33 | setLoading(false) 34 | } 35 | 36 | return ( 37 |
38 | 43 | 48 |
49 | 52 | setPassword(e.currentTarget.value)} 61 | appearance={props.appearance} 62 | /> 63 |
64 | 72 |
73 | 74 | 75 | {message()} 76 | 77 | 78 | {message()} 79 | 80 |
81 |
82 | ) 83 | } 84 | 85 | export { UpdatePassword } 86 | -------------------------------------------------------------------------------- /packages/solid/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @supabase/auth-ui-solid 2 | 3 | ## 0.3.8 4 | 5 | ### Patch Changes 6 | 7 | - ac80a298: fix: update password placeholder prop 8 | 9 | ## 0.3.7 10 | 11 | ### Patch Changes 12 | 13 | - ae22ff23: Message styling change 14 | 15 | ## 0.3.6 16 | 17 | ### Patch Changes 18 | 19 | - Updated dependencies [a8f9395d] 20 | - @supabase/auth-ui-shared@0.1.8 21 | 22 | ## 0.3.5 23 | 24 | ### Patch Changes 25 | 26 | - a80400e2: Fix password letter spacing 27 | - Updated dependencies [2b252910] 28 | - @supabase/auth-ui-shared@0.1.7 29 | 30 | ## 0.3.4 31 | 32 | ### Patch Changes 33 | 34 | - 75a62d3e: Add Kakao icon 35 | 36 | ## 0.3.3 37 | 38 | ### Patch Changes 39 | 40 | - 653f1254: Update auth icons loading 41 | 42 | ## 0.3.2 43 | 44 | ### Patch Changes 45 | 46 | - 8ca7a586: Add additional data to component to store in user_metadata 47 | - Updated dependencies [8ca7a586] 48 | - @supabase/auth-ui-shared@0.1.6 49 | 50 | ## 0.3.1 51 | 52 | ### Patch Changes 53 | 54 | - eadd6019: Add verify otp component 55 | - Updated dependencies [3aa2c54d] 56 | - @supabase/auth-ui-shared@0.1.5 57 | 58 | ## 0.3.0 59 | 60 | ### Minor Changes 61 | 62 | - 4ee84375: Add individual components to SolidJS Auth UI 63 | 64 | ## 0.2.5 65 | 66 | ### Patch Changes 67 | 68 | - d5052260: Add providerScopes property for setting social auth scopes 69 | - Updated dependencies [d5052260] 70 | - @supabase/auth-ui-shared@0.1.4 71 | 72 | ## 0.2.4 73 | 74 | ### Patch Changes 75 | 76 | - a814f486: Change icon size default change to 21px 77 | 78 | ## 0.2.3 79 | 80 | ### Patch Changes 81 | 82 | - 11ebb978: Update i18n for confirmation messages 83 | - Updated dependencies [11ebb978] 84 | - @supabase/auth-ui-shared@0.1.3 85 | 86 | ## 0.2.2 87 | 88 | ### Patch Changes 89 | 90 | - b8e6e3b4: Update social layout type to only include keys 91 | - Updated dependencies [b8e6e3b4] 92 | - Updated dependencies [b8e6e3b4] 93 | - @supabase/auth-ui-shared@0.1.2 94 | 95 | ## 0.2.1 96 | 97 | ### Patch Changes 98 | 99 | - 121e88d1: Add html input autofocus 100 | - 32d5d0ef: Update to handle templated variable for provider 101 | - Updated dependencies [0d794741] 102 | - @supabase/auth-ui-shared@0.1.1 103 | 104 | ## 0.2.0 105 | 106 | ### Minor Changes 107 | 108 | - 1349aa6: Updated to share common files using the auth-ui-shared package 109 | Removed storybook from the react package 110 | Add examples to showcase the Auth UI 111 | Moved localizations to their own directory 112 | 113 | ### Patch Changes 114 | 115 | - Updated dependencies [1349aa6] 116 | - @supabase/auth-ui-shared@0.1.0 117 | 118 | ## 0.1.1 119 | 120 | ### Patch Changes 121 | 122 | - 11a09a6: Fix path to dist for esm and cjs 123 | 124 | ## 0.1.0 125 | 126 | ### Minor Changes 127 | 128 | - e70c1e8: Update dependencies to latest version 129 | 130 | ## 0.2.0 131 | 132 | #### Initial Release 133 | 134 | - 7f6c920: Initial release of auth-ui-solid 135 | -------------------------------------------------------------------------------- /packages/react/src/components/Auth/ui/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode } from 'react' 2 | import Auth from '../Auth' 3 | import { Auth as AuthProps } from '../../../types' 4 | import { PREPENDED_CLASS_NAMES } from '@supabase/auth-ui-shared' 5 | import { css } from '@stitches/core' 6 | import { CssComponent } from '@stitches/core/types/styled-component' 7 | 8 | const containerDefaultStyles = css({ 9 | borderRadius: '12px', 10 | boxShadow: 'rgba(100, 100, 111, 0.2) 0px 7px 29px 0px', 11 | width: '360px', 12 | padding: '28px 32px', 13 | }) 14 | 15 | interface Card { 16 | className?: string | CssComponent 17 | } 18 | 19 | export const AuthCard = ({ 20 | children, 21 | appearance, 22 | }: { 23 | children?: ReactNode 24 | appearance?: Card 25 | }) => { 26 | const classNames = [ 27 | `${PREPENDED_CLASS_NAMES}_ui-card`, 28 | containerDefaultStyles(), 29 | appearance?.className, 30 | ] 31 | return
{children}
32 | } 33 | 34 | export const SignUp = ( 35 | props: Omit 36 | ) => { 37 | return ( 38 | 44 | ) 45 | } 46 | 47 | export const SignIn = ( 48 | props: Omit 49 | ) => { 50 | return ( 51 | 57 | ) 58 | } 59 | 60 | export const MagicLink = ( 61 | props: Omit< 62 | AuthProps, 63 | | 'view' 64 | | 'onlyThirdPartyProviders' 65 | | 'magicLink' 66 | | 'showLinks' 67 | | 'additionalData' 68 | > 69 | ) => { 70 | return 71 | } 72 | 73 | export const SocialAuth = ( 74 | props: Omit< 75 | AuthProps, 76 | | 'view' 77 | | 'onlyThirdPartyProviders' 78 | | 'magicLink' 79 | | 'showLinks' 80 | | 'additionalData' 81 | > 82 | ) => { 83 | return ( 84 | 90 | ) 91 | } 92 | 93 | export const ForgottenPassword = ( 94 | props: Pick< 95 | AuthProps, 96 | | 'supabaseClient' 97 | | 'appearance' 98 | | 'localization' 99 | | 'theme' 100 | | 'showLinks' 101 | | 'redirectTo' 102 | > 103 | ) => { 104 | return 105 | } 106 | 107 | export const UpdatePassword = ( 108 | props: Pick< 109 | AuthProps, 110 | 'supabaseClient' | 'appearance' | 'localization' | 'theme' 111 | > 112 | ) => { 113 | return 114 | } 115 | 116 | export const VerifyOtp = ( 117 | props: Pick< 118 | AuthProps, 119 | 'supabaseClient' | 'appearance' | 'localization' | 'theme' | 'otpType' 120 | > 121 | ) => { 122 | return 123 | } 124 | -------------------------------------------------------------------------------- /packages/solid/src/components/Auth/interfaces/MagicLink.tsx: -------------------------------------------------------------------------------- 1 | import { SupabaseClient } from '@supabase/supabase-js' 2 | import { createSignal, Setter } from 'solid-js' 3 | import { 4 | I18nVariables, 5 | RedirectTo, 6 | ViewType, 7 | VIEWS, 8 | } from '@supabase/auth-ui-shared' 9 | import { Appearance, FormEvent } from '../../../types' 10 | import { Anchor, Button, Container, Input, Label, Message } from '../../UI' 11 | 12 | function MagicLink(props: { 13 | setAuthView: Setter 14 | supabaseClient: SupabaseClient 15 | redirectTo?: RedirectTo 16 | i18n: I18nVariables 17 | appearance?: Appearance 18 | showLinks?: boolean 19 | }) { 20 | const [email, setEmail] = createSignal('') 21 | const [error, setError] = createSignal('') 22 | const [message, setMessage] = createSignal('') 23 | const [loading, setLoading] = createSignal(false) 24 | 25 | const handleMagicLinkSignIn = async (e: FormEvent) => { 26 | e.preventDefault() 27 | setError('') 28 | setMessage('') 29 | setLoading(true) 30 | const { error } = await props.supabaseClient.auth.signInWithOtp({ 31 | email: email(), 32 | options: { emailRedirectTo: props.redirectTo }, 33 | }) 34 | if (error) setError(error.message) 35 | else setMessage(props.i18n.magic_link?.confirmation_text as string) 36 | setLoading(false) 37 | } 38 | 39 | return ( 40 | 92 | ) 93 | } 94 | 95 | export { MagicLink } 96 | -------------------------------------------------------------------------------- /packages/solid/src/components/Auth/ui/index.tsx: -------------------------------------------------------------------------------- 1 | import Auth from '../Auth' 2 | import { Auth as AuthProps } from '../../../types' 3 | import { PREPENDED_CLASS_NAMES } from '@supabase/auth-ui-shared' 4 | import { css } from '@stitches/core' 5 | import { CssComponent } from '@stitches/core/types/styled-component' 6 | import { JSXElement } from 'solid-js' 7 | 8 | const containerDefaultStyles = css({ 9 | borderRadius: '12px', 10 | boxShadow: 'rgba(100, 100, 111, 0.2) 0px 7px 29px 0px', 11 | width: '360px', 12 | padding: '28px 32px', 13 | }) 14 | 15 | interface Card { 16 | className?: string | CssComponent 17 | } 18 | 19 | export const AuthCard = ({ 20 | children, 21 | appearance, 22 | }: { 23 | children?: JSXElement 24 | appearance?: Card 25 | }) => { 26 | const classNames = [ 27 | `${PREPENDED_CLASS_NAMES}_ui-card`, 28 | containerDefaultStyles(), 29 | appearance?.className, 30 | ] 31 | return
{children}
32 | } 33 | 34 | export const SignUp = ( 35 | props: Omit 36 | ) => { 37 | return ( 38 | 44 | {props.children} 45 | 46 | ) 47 | } 48 | 49 | export const SignIn = ( 50 | props: Omit 51 | ) => { 52 | return ( 53 | 59 | ) 60 | } 61 | 62 | export const MagicLink = ( 63 | props: Omit< 64 | AuthProps, 65 | | 'view' 66 | | 'onlyThirdPartyProviders' 67 | | 'magicLink' 68 | | 'showLinks' 69 | | 'additionalData' 70 | > 71 | ) => { 72 | return 73 | } 74 | 75 | export const SocialAuth = ( 76 | props: Omit< 77 | AuthProps, 78 | | 'view' 79 | | 'onlyThirdPartyProviders' 80 | | 'magicLink' 81 | | 'showLinks' 82 | | 'children' 83 | | 'additionalData' 84 | > 85 | ) => { 86 | return ( 87 | 93 | ) 94 | } 95 | 96 | export const ForgottenPassword = ( 97 | props: Pick< 98 | AuthProps, 99 | | 'supabaseClient' 100 | | 'appearance' 101 | | 'localization' 102 | | 'theme' 103 | | 'showLinks' 104 | | 'redirectTo' 105 | > 106 | ) => { 107 | return 108 | } 109 | 110 | export const UpdatePassword = ( 111 | props: Pick< 112 | AuthProps, 113 | 'supabaseClient' | 'appearance' | 'localization' | 'theme' 114 | > 115 | ) => { 116 | return 117 | } 118 | 119 | export const VerifyOtp = ( 120 | props: Pick< 121 | AuthProps, 122 | 'supabaseClient' | 'appearance' | 'localization' | 'theme' | 'otpType' 123 | > 124 | ) => { 125 | return 126 | } 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Maintenance Mode 3 | 4 | > [!IMPORTANT] 5 | > As of 7th Feb 2024, this repository is no longer maintained by the Supabase Team. At the moment, the team does not have capacity to give the expected level of care to this repository. We may revisit Auth UI in the future but regrettably have to leave it on hold for now as we focus on other priorities such as improving the Auth Helpers and advanced Auth primitives. 6 | 7 | > The repository itself will continue to exist and a subset of components within the Next.js ecosystem, such as Forgot Password Pages, will be iterated on. We will continue to keep the latest packages for frameworks available at `@supabase/auth-ui-svelte`. 8 | 9 | > We would like to thank everyone for your contributions to the repository. Please feel free to open an issue if you have any questions or concerns. 10 | 11 | > Thank you. 12 | 13 | # Supabase Auth UI 14 | 15 | Supabase Auth UI is a collection of pre built UI components that work seamlessly with @supabase/auth-helpers. 16 | 17 | The main purpose of these components is to allow developers to get working on their apps quickly, but also be able to use their own style/css. 18 | 19 | Auth UI is kept deliberately separate from @supabase/auth-helpers so that developers can migrate away from pre-built UI components as their UI system naturally matures. 20 | 21 | Screenshot 2022-04-30 at 9 30 25 PM 22 | 23 | 24 | ## Supported frameworks 25 | 26 | - [React.js](https://reactjs.org/) [[Documentation](https://supabase.com/docs/guides/auth/auth-helpers/auth-ui)] 27 | - [Solid.js](https://www.solidjs.com/) 28 | - [Svelte](https://svelte.dev/) 29 | 30 | ### Examples and Packages 31 | 32 | - Examples 33 | - `@example/react`: a [React.js](./examples/react) app 34 | - `@example/solid`: a [Solid.js](./examples/solidjs) app 35 | - `@example/svelte`: a [Svelte](./examples/svelte) app 36 | - Packages 37 | - `@supabase/auth-ui-react`: the supabase auth ui reactjs library used by `react` application 38 | - `@supabase/auth-ui-solid`: the supabase auth ui solid.js library used by `solid.js` application 39 | - `@supabase/auth-ui-svelte`: the supabase auth ui svelte library used by `svelte` application 40 | - `shared`: shared typescript types used by `@supabase/auth-ui-[framework]` library 41 | - `tsconfig`: `tsconfig.json`s used throughout the monorepo 42 | 43 | Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). 44 | 45 | ## Localization 46 | 47 | Localizations are no longer distributed with the package in order to keep the package size small. You can now import the localization you need by copying the file from this repo and importing it into your project then passing it to the `localization.variables` param of the Auth component. 48 | 49 | ```tsx 50 | import { Auth } from '@supabase/auth-ui-react' 51 | import * as ja from './path-to-localization-file.json' 52 | ... 53 | 59 | ... 60 | ``` 61 | 62 | ## Development 63 | 64 | Read the [development.md](./development.md) for more information. 65 | 66 | Using a `@supabase/auth-ui-[framework-name]` naming convention for packages 67 | -------------------------------------------------------------------------------- /packages/solid/src/components/Auth/interfaces/ForgottenPassword.tsx: -------------------------------------------------------------------------------- 1 | import { SupabaseClient } from '@supabase/supabase-js' 2 | import { createSignal, Setter } from 'solid-js' 3 | import { 4 | I18nVariables, 5 | RedirectTo, 6 | ViewType, 7 | VIEWS, 8 | } from '@supabase/auth-ui-shared' 9 | import { Appearance, FormEvent } from '../../../types' 10 | import { Anchor, Button, Container, Input, Label, Message } from '../../UI' 11 | 12 | function ForgottenPassword(props: { 13 | setAuthView: Setter 14 | supabaseClient: SupabaseClient 15 | redirectTo?: RedirectTo 16 | i18n: I18nVariables 17 | appearance?: Appearance 18 | showLinks?: boolean 19 | }) { 20 | const [email, setEmail] = createSignal('') 21 | const [error, setError] = createSignal('') 22 | const [message, setMessage] = createSignal('') 23 | const [loading, setLoading] = createSignal(false) 24 | 25 | const handlePasswordReset = async (e: FormEvent) => { 26 | e.preventDefault() 27 | setError('') 28 | setMessage('') 29 | setLoading(true) 30 | const { error } = await props.supabaseClient.auth.resetPasswordForEmail( 31 | email(), 32 | { 33 | redirectTo: props.redirectTo, 34 | } 35 | ) 36 | if (error) setError(error.message) 37 | else setMessage(props.i18n.forgotten_password?.confirmation_text as string) 38 | setLoading(false) 39 | } 40 | 41 | return ( 42 |
43 | 44 | 49 |
50 | 53 | setEmail(e.currentTarget.value)} 62 | appearance={props.appearance} 63 | /> 64 |
65 | 73 |
74 | {props.showLinks && ( 75 | { 78 | e.preventDefault() 79 | props.setAuthView(VIEWS.SIGN_IN) 80 | }} 81 | appearance={props.appearance} 82 | > 83 | {props.i18n?.sign_in?.link_text} 84 | 85 | )} 86 | {message && ( 87 | {message()} 88 | )} 89 | {error && ( 90 | 91 | {error()} 92 | 93 | )} 94 |
95 |
96 | ) 97 | } 98 | 99 | export { ForgottenPassword } 100 | -------------------------------------------------------------------------------- /packages/react/src/components/Auth/interfaces/ForgottenPassword.tsx: -------------------------------------------------------------------------------- 1 | import { SupabaseClient } from '@supabase/supabase-js' 2 | import React, { useState } from 'react' 3 | import { VIEWS, I18nVariables, RedirectTo } from '@supabase/auth-ui-shared' 4 | import { Appearance } from '../../../types' 5 | import { 6 | Anchor, 7 | Button, 8 | Container, 9 | Input, 10 | Label, 11 | Message, 12 | } from './../../UI/index.js' 13 | 14 | function ForgottenPassword({ 15 | setAuthView = () => {}, 16 | supabaseClient, 17 | redirectTo, 18 | i18n, 19 | appearance, 20 | showLinks = false, 21 | }: { 22 | setAuthView?: any 23 | supabaseClient: SupabaseClient 24 | redirectTo?: RedirectTo 25 | i18n?: I18nVariables 26 | appearance?: Appearance 27 | showLinks?: boolean 28 | }) { 29 | const [email, setEmail] = useState('') 30 | const [error, setError] = useState('') 31 | const [message, setMessage] = useState('') 32 | const [loading, setLoading] = useState(false) 33 | 34 | const handlePasswordReset = async (e: React.FormEvent) => { 35 | e.preventDefault() 36 | setError('') 37 | setMessage('') 38 | setLoading(true) 39 | const { error } = await supabaseClient.auth.resetPasswordForEmail(email, { 40 | redirectTo, 41 | }) 42 | if (error) setError(error.message) 43 | else setMessage(i18n?.forgotten_password?.confirmation_text as string) 44 | setLoading(false) 45 | } 46 | 47 | const labels = i18n?.forgotten_password 48 | 49 | return ( 50 |
51 | 52 | 53 |
54 | 57 | ) => 64 | setEmail(e.target.value) 65 | } 66 | appearance={appearance} 67 | /> 68 |
69 | 77 | {showLinks && ( 78 | ) => { 81 | e.preventDefault() 82 | setAuthView(VIEWS.SIGN_IN) 83 | }} 84 | appearance={appearance} 85 | > 86 | {i18n?.sign_in?.link_text} 87 | 88 | )} 89 | {message && {message}} 90 | {error && ( 91 | 92 | {error} 93 | 94 | )} 95 |
96 |
97 |
98 | ) 99 | } 100 | 101 | export { ForgottenPassword } 102 | -------------------------------------------------------------------------------- /packages/react/src/components/Auth/interfaces/MagicLink.tsx: -------------------------------------------------------------------------------- 1 | import { SupabaseClient } from '@supabase/supabase-js' 2 | import React, { useState } from 'react' 3 | import { VIEWS, I18nVariables, RedirectTo, en } from '@supabase/auth-ui-shared' 4 | import { Appearance } from '../../../types' 5 | import { 6 | Anchor, 7 | Button, 8 | Container, 9 | Input, 10 | Label, 11 | Message, 12 | } from './../../UI/index.js' 13 | 14 | function MagicLink({ 15 | setAuthView = () => {}, 16 | supabaseClient, 17 | redirectTo, 18 | i18n, 19 | appearance, 20 | showLinks = false, 21 | }: { 22 | setAuthView?: any 23 | supabaseClient: SupabaseClient 24 | redirectTo?: RedirectTo 25 | i18n?: I18nVariables 26 | appearance?: Appearance 27 | showLinks?: boolean 28 | }) { 29 | const [email, setEmail] = useState('') 30 | const [error, setError] = useState('') 31 | const [message, setMessage] = useState('') 32 | const [loading, setLoading] = useState(false) 33 | 34 | const handleMagicLinkSignIn = async (e: React.FormEvent) => { 35 | e.preventDefault() 36 | setError('') 37 | setMessage('') 38 | setLoading(true) 39 | 40 | if (email.length === 0) { 41 | setError(i18n?.magic_link?.empty_email_address as string) 42 | setLoading(false) 43 | return 44 | } 45 | const { error } = await supabaseClient.auth.signInWithOtp({ 46 | email, 47 | options: { emailRedirectTo: redirectTo }, 48 | }) 49 | if (error) setError(error.message) 50 | else setMessage(i18n?.magic_link?.confirmation_text as string) 51 | setLoading(false) 52 | } 53 | 54 | const labels = i18n?.magic_link 55 | 56 | return ( 57 | 104 | ) 105 | } 106 | 107 | export { MagicLink } 108 | -------------------------------------------------------------------------------- /packages/solid/src/components/Auth/interfaces/SocialAuth.tsx: -------------------------------------------------------------------------------- 1 | import { Provider, SupabaseClient } from '@supabase/supabase-js' 2 | import { createSignal, For, Show } from 'solid-js' 3 | import { 4 | I18nVariables, 5 | ProviderScopes, 6 | SocialLayout, 7 | template, 8 | } from '@supabase/auth-ui-shared' 9 | import { Appearance } from '../../../types' 10 | import { Button, Container, Divider } from '../../UI' 11 | import { Icons } from '../Icons' 12 | 13 | interface SocialAuthProps { 14 | supabaseClient: SupabaseClient 15 | socialLayout: SocialLayout | string 16 | providers?: Provider[] 17 | providerScopes?: Partial 18 | queryParams?: { [key: string]: string } 19 | redirectTo: RedirectTo 20 | onlyThirdPartyProviders: boolean 21 | view: 'sign_in' | 'sign_up' | 'magic_link' 22 | i18n: I18nVariables 23 | appearance?: Appearance 24 | } 25 | 26 | type RedirectTo = undefined | string 27 | 28 | function SocialAuth(props: SocialAuthProps) { 29 | const [loading, setLoading] = createSignal(false) 30 | const [error, setError] = createSignal('') 31 | 32 | const currentView = props.view === 'magic_link' ? 'sign_in' : props.view 33 | 34 | const handleProviderSignIn = async (provider: Provider) => { 35 | setLoading(true) 36 | const { error } = await props.supabaseClient.auth.signInWithOAuth({ 37 | provider, 38 | options: { 39 | redirectTo: props.redirectTo, 40 | scopes: props.providerScopes?.[provider], 41 | queryParams: props.queryParams, 42 | }, 43 | }) 44 | if (error) setError(error.message) 45 | setLoading(false) 46 | } 47 | 48 | function capitalize(word: string) { 49 | const lower = word.toLowerCase() 50 | return word.charAt(0).toUpperCase() + lower.slice(1) 51 | } 52 | 53 | return ( 54 | <> 55 | {props.providers && props.providers.length > 0 && ( 56 | <> 57 | 62 | 67 | 68 | {(provider: Provider) => { 69 | return ( 70 | 86 | ) 87 | }} 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | )} 96 | 97 | ) 98 | } 99 | 100 | export { SocialAuth } 101 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/interfaces/VerifyOtp.svelte: -------------------------------------------------------------------------------- 1 | 53 | 54 | 123 | 124 | 129 | -------------------------------------------------------------------------------- /packages/react/src/components/Auth/interfaces/SocialAuth.tsx: -------------------------------------------------------------------------------- 1 | import { Provider, SupabaseClient } from '@supabase/supabase-js' 2 | import { useState } from 'react' 3 | import { 4 | I18nVariables, 5 | ProviderScopes, 6 | SocialLayout, 7 | template, 8 | } from '@supabase/auth-ui-shared' 9 | import { Appearance } from '../../../types' 10 | import { Button, Container, Divider } from './../../UI/index.js' 11 | import { Icons } from './../Icons.js' 12 | 13 | interface SocialAuthProps { 14 | supabaseClient: SupabaseClient 15 | socialLayout?: SocialLayout 16 | providers?: Provider[] 17 | providerScopes?: Partial 18 | queryParams?: { [key: string]: string } 19 | redirectTo?: RedirectTo 20 | onlyThirdPartyProviders?: boolean 21 | view?: 'sign_in' | 'sign_up' | 'magic_link' 22 | i18n?: I18nVariables 23 | appearance?: Appearance 24 | } 25 | 26 | type RedirectTo = undefined | string 27 | 28 | function SocialAuth({ 29 | supabaseClient, 30 | socialLayout = 'vertical', 31 | providers = ['github', 'google', 'azure'], 32 | providerScopes, 33 | queryParams, 34 | redirectTo, 35 | onlyThirdPartyProviders = true, 36 | view = 'sign_in', 37 | i18n, 38 | appearance, 39 | }: SocialAuthProps) { 40 | const [loading, setLoading] = useState(false) 41 | const [error, setError] = useState('') 42 | 43 | const verticalSocialLayout = socialLayout === 'vertical' ? true : false 44 | 45 | const currentView = view === 'magic_link' ? 'sign_in' : view 46 | 47 | const handleProviderSignIn = async (provider: Provider) => { 48 | setLoading(true) 49 | const { error } = await supabaseClient.auth.signInWithOAuth({ 50 | provider, 51 | options: { 52 | redirectTo, 53 | scopes: providerScopes?.[provider], 54 | queryParams, 55 | }, 56 | }) 57 | if (error) setError(error.message) 58 | setLoading(false) 59 | } 60 | 61 | function handleProviderNameEdgeCases(provider: string) { 62 | if (provider === 'linkedin_oidc') { 63 | return 'LinkedIn' 64 | } 65 | return provider 66 | } 67 | 68 | function capitalize(word: string) { 69 | const lower = word.toLowerCase() 70 | return word.charAt(0).toUpperCase() + lower.slice(1) 71 | } 72 | 73 | return ( 74 | <> 75 | {providers && providers.length > 0 && ( 76 | <> 77 | 78 | 83 | {providers.map((provider: Provider) => { 84 | return ( 85 | 103 | ) 104 | })} 105 | 106 | 107 | {!onlyThirdPartyProviders && } 108 | 109 | )} 110 | 111 | ) 112 | } 113 | 114 | export { SocialAuth } 115 | -------------------------------------------------------------------------------- /examples/react/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/svelte/src/lib/Auth/Auth.svelte: -------------------------------------------------------------------------------- 1 | 73 | 74 |
75 | {#if SignView} 76 | 87 | {/if} 88 | {#if view === VIEWS.SIGN_IN} 89 | {#if !onlyThirdPartyProviders} 90 | 100 | {/if} 101 | {/if} 102 | {#if view === VIEWS.SIGN_UP} 103 | {#if !onlyThirdPartyProviders} 104 | 115 | {/if} 116 | {/if} 117 | {#if view === VIEWS.FORGOTTEN_PASSWORD} 118 | 126 | {/if} 127 | {#if view === VIEWS.MAGIC_LINK} 128 | 129 | {/if} 130 | {#if view === VIEWS.UPDATE_PASSWORD} 131 | 139 | {/if} 140 | {#if view === VIEWS.VERIFY_OTP} 141 | 142 | {/if} 143 |
144 | -------------------------------------------------------------------------------- /packages/shared/src/theming/Themes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Create default theme 3 | * 4 | * createStitches() 5 | * https://stitches.dev/docs/api#theme 6 | * 7 | * to add a new theme use createTheme({}) 8 | * https://stitches.dev/docs/api#theme 9 | */ 10 | 11 | import { ThemeVariables } from './Types' 12 | 13 | // brand: 'hsl(252 62% 55%)', 14 | // brandAccent: 'hsl(252 62% 45%)', 15 | 16 | const supabase: ThemeVariables = { 17 | colors: { 18 | brand: 'hsl(153 60.0% 53.0%)', 19 | brandAccent: 'hsl(154 54.8% 45.1%)', 20 | brandButtonText: 'white', 21 | defaultButtonBackground: 'white', 22 | defaultButtonBackgroundHover: '#eaeaea', 23 | defaultButtonBorder: 'lightgray', 24 | defaultButtonText: 'gray', 25 | dividerBackground: '#eaeaea', 26 | inputBackground: 'transparent', 27 | inputBorder: 'lightgray', 28 | inputBorderHover: 'gray', 29 | inputBorderFocus: 'gray', 30 | inputText: 'black', 31 | inputLabelText: 'gray', 32 | inputPlaceholder: 'darkgray', 33 | messageText: 'gray', 34 | messageTextDanger: 'red', 35 | anchorTextColor: 'gray', 36 | anchorTextHoverColor: 'darkgray', 37 | }, 38 | space: { 39 | spaceSmall: '4px', 40 | spaceMedium: '8px', 41 | spaceLarge: '16px', 42 | labelBottomMargin: '8px', 43 | anchorBottomMargin: '4px', 44 | emailInputSpacing: '4px', 45 | socialAuthSpacing: '4px', 46 | buttonPadding: '10px 15px', 47 | inputPadding: '10px 15px', 48 | }, 49 | fontSizes: { 50 | baseBodySize: '13px', 51 | baseInputSize: '14px', 52 | baseLabelSize: '14px', 53 | baseButtonSize: '14px', 54 | }, 55 | fonts: { 56 | bodyFontFamily: `ui-sans-serif, sans-serif`, 57 | buttonFontFamily: `ui-sans-serif, sans-serif`, 58 | inputFontFamily: `ui-sans-serif, sans-serif`, 59 | labelFontFamily: `ui-sans-serif, sans-serif`, 60 | }, 61 | // fontWeights: {}, 62 | // lineHeights: {}, 63 | // letterSpacings: {}, 64 | // sizes: {}, 65 | borderWidths: { 66 | buttonBorderWidth: '1px', 67 | inputBorderWidth: '1px', 68 | }, 69 | // borderStyles: {}, 70 | radii: { 71 | borderRadiusButton: '4px', 72 | buttonBorderRadius: '4px', 73 | inputBorderRadius: '4px', 74 | }, 75 | // shadows: {}, 76 | // zIndices: {}, 77 | // transitions: {}, 78 | } 79 | 80 | const defaultDarkTheme: ThemeVariables = { 81 | colors: { 82 | brandButtonText: 'white', 83 | defaultButtonBackground: '#2e2e2e', 84 | defaultButtonBackgroundHover: '#3e3e3e', 85 | defaultButtonBorder: '#3e3e3e', 86 | defaultButtonText: 'white', 87 | dividerBackground: '#2e2e2e', 88 | inputBackground: '#1e1e1e', 89 | inputBorder: '#3e3e3e', 90 | inputBorderHover: 'gray', 91 | inputBorderFocus: 'gray', 92 | inputText: 'white', 93 | inputPlaceholder: 'darkgray', 94 | }, 95 | } 96 | 97 | const minimal: ThemeVariables = { 98 | colors: { 99 | brand: 'black', 100 | brandAccent: '#333333', 101 | brandButtonText: 'white', 102 | defaultButtonBackground: 'white', 103 | defaultButtonBorder: 'lightgray', 104 | defaultButtonText: 'gray', 105 | dividerBackground: '#eaeaea', 106 | inputBackground: 'transparent', 107 | inputBorder: 'lightgray', 108 | inputText: 'black', 109 | inputPlaceholder: 'darkgray', 110 | }, 111 | space: { 112 | spaceSmall: '4px', 113 | spaceMedium: '8px', 114 | spaceLarge: '16px', 115 | }, 116 | fontSizes: { 117 | baseInputSize: '14px', 118 | baseLabelSize: '12px', 119 | }, 120 | fonts: { 121 | bodyFontFamily: '', 122 | inputFontFamily: '', 123 | buttonFontFamily: '', 124 | labelFontFamily: '', 125 | // linkFontFamily: '', 126 | }, 127 | // fontWeights: {}, 128 | // lineHeights: {}, 129 | // letterSpacings: {}, 130 | // sizes: {}, 131 | borderWidths: {}, 132 | // borderStyles: {}, 133 | radii: {}, 134 | // shadows: {}, 135 | // zIndices: {}, 136 | // transitions: {}, 137 | } 138 | 139 | const minimalDark: ThemeVariables = { 140 | colors: { 141 | brand: 'white', 142 | brandAccent: '#afafaf', 143 | brandButtonText: 'black', 144 | defaultButtonBackground: '#080808', 145 | defaultButtonBorder: 'black', 146 | defaultButtonText: 'white', 147 | dividerBackground: 'black', 148 | inputBackground: 'transparent', 149 | inputBorder: 'gray', 150 | inputText: 'black', 151 | inputPlaceholder: 'darkgray', 152 | }, 153 | } 154 | 155 | const darkThemes = { 156 | supabase: defaultDarkTheme, 157 | minimal: minimalDark, 158 | } 159 | 160 | export { supabase, minimal, darkThemes } 161 | --------------------------------------------------------------------------------