@wasp.sh/wasp-cli-darwin-arm64-unknown 0.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/Cli/bash-completion +5 -0
- package/data/Cli/starters/README.md +22 -0
- package/data/Cli/starters/basic/.prettierignore +2 -0
- package/data/Cli/starters/basic/.prettierrc +3 -0
- package/data/Cli/starters/basic/README.md +35 -0
- package/data/Cli/starters/basic/eslint.config.js +15 -0
- package/data/Cli/starters/basic/main.wasp +100 -0
- package/data/Cli/starters/basic/package.json +27 -0
- package/data/Cli/starters/basic/postcss.config.cjs +6 -0
- package/data/Cli/starters/basic/schema.prisma +42 -0
- package/data/Cli/starters/basic/src/App.css +13 -0
- package/data/Cli/starters/basic/src/App.tsx +12 -0
- package/data/Cli/starters/basic/src/assets/logo.svg +1 -0
- package/data/Cli/starters/basic/src/auth/AuthLayout.tsx +10 -0
- package/data/Cli/starters/basic/src/auth/email/EmailVerificationPage.tsx +19 -0
- package/data/Cli/starters/basic/src/auth/email/LoginPage.tsx +27 -0
- package/data/Cli/starters/basic/src/auth/email/PasswordResetPage.tsx +19 -0
- package/data/Cli/starters/basic/src/auth/email/RequestPasswordResetPage.tsx +10 -0
- package/data/Cli/starters/basic/src/auth/email/SignupPage.tsx +34 -0
- package/data/Cli/starters/basic/src/auth/email/userSignupFields.ts +13 -0
- package/data/Cli/starters/basic/src/shared/components/Button.tsx +90 -0
- package/data/Cli/starters/basic/src/shared/components/Dialog.tsx +85 -0
- package/data/Cli/starters/basic/src/shared/components/Header.tsx +39 -0
- package/data/Cli/starters/basic/src/shared/components/Input.tsx +36 -0
- package/data/Cli/starters/basic/src/shared/components/Portal.tsx +26 -0
- package/data/Cli/starters/basic/src/tags/actions.ts +23 -0
- package/data/Cli/starters/basic/src/tags/components/ColorRadioButton.tsx +44 -0
- package/data/Cli/starters/basic/src/tags/components/ColorRadioButtons.tsx +59 -0
- package/data/Cli/starters/basic/src/tags/components/CreateTagDialog.tsx +50 -0
- package/data/Cli/starters/basic/src/tags/components/CreateTagForm.tsx +100 -0
- package/data/Cli/starters/basic/src/tags/components/TagLabel.tsx +55 -0
- package/data/Cli/starters/basic/src/tags/components/colors.ts +8 -0
- package/data/Cli/starters/basic/src/tags/queries.ts +14 -0
- package/data/Cli/starters/basic/src/tasks/TasksPage.tsx +19 -0
- package/data/Cli/starters/basic/src/tasks/actions.ts +71 -0
- package/data/Cli/starters/basic/src/tasks/components/CreateTaskForm.tsx +103 -0
- package/data/Cli/starters/basic/src/tasks/components/TaskList.tsx +68 -0
- package/data/Cli/starters/basic/src/tasks/components/TaskListItem.tsx +56 -0
- package/data/Cli/starters/basic/src/tasks/queries.ts +21 -0
- package/data/Cli/starters/basic/tailwind.config.cjs +30 -0
- package/data/Cli/starters/basic/vite.config.ts +7 -0
- package/data/Cli/starters/minimal/main.wasp +14 -0
- package/data/Cli/starters/minimal/package.json +16 -0
- package/data/Cli/starters/minimal/schema.prisma +10 -0
- package/data/Cli/starters/minimal/src/Main.css +103 -0
- package/data/Cli/starters/minimal/src/MainPage.tsx +37 -0
- package/data/Cli/starters/minimal/src/assets/logo.svg +1 -0
- package/data/Cli/starters/minimal/vite.config.ts +7 -0
- package/data/Cli/starters/skeleton/.waspignore +4 -0
- package/data/Cli/starters/skeleton/.wasproot +1 -0
- package/data/Cli/starters/skeleton/public/.gitkeep +0 -0
- package/data/Cli/starters/skeleton/public/favicon.ico +0 -0
- package/data/Cli/starters/skeleton/src/vite-env.d.ts +7 -0
- package/data/Cli/starters/skeleton/tsconfig.json +28 -0
- package/data/Generator/templates/Dockerfile +72 -0
- package/data/Generator/templates/db/schema.prisma +24 -0
- package/data/Generator/templates/dockerignore +2 -0
- package/data/Generator/templates/react-app/README.md +21 -0
- package/data/Generator/templates/react-app/gitignore +23 -0
- package/data/Generator/templates/react-app/index.html +22 -0
- package/data/Generator/templates/react-app/netlify.toml +8 -0
- package/data/Generator/templates/react-app/npmrc +1 -0
- package/data/Generator/templates/react-app/package.json +30 -0
- package/data/Generator/templates/react-app/public/manifest.json +15 -0
- package/data/Generator/templates/react-app/src/auth/pages/OAuthCallback.tsx +96 -0
- package/data/Generator/templates/react-app/src/auth/pages/createAuthRequiredPage.jsx +40 -0
- package/data/Generator/templates/react-app/src/components/DefaultRootErrorBoundary.tsx +16 -0
- package/data/Generator/templates/react-app/src/components/FullPageWrapper.tsx +21 -0
- package/data/Generator/templates/react-app/src/components/Loader.module.css +37 -0
- package/data/Generator/templates/react-app/src/components/Loader.tsx +12 -0
- package/data/Generator/templates/react-app/src/components/Message.tsx +86 -0
- package/data/Generator/templates/react-app/src/index.tsx +47 -0
- package/data/Generator/templates/react-app/src/logo.png +0 -0
- package/data/Generator/templates/react-app/src/router.tsx +57 -0
- package/data/Generator/templates/react-app/src/stitches.config.js +33 -0
- package/data/Generator/templates/react-app/src/test/vitest/setup.ts +8 -0
- package/data/Generator/templates/react-app/src/utils.js +3 -0
- package/data/Generator/templates/react-app/src/vite-env.d.ts +1 -0
- package/data/Generator/templates/react-app/tsconfig.app.json +20 -0
- package/data/Generator/templates/react-app/tsconfig.json +11 -0
- package/data/Generator/templates/react-app/tsconfig.vite.json +16 -0
- package/data/Generator/templates/react-app/vite/detectServerImports.ts +53 -0
- package/data/Generator/templates/react-app/vite/validateEnv.ts +45 -0
- package/data/Generator/templates/react-app/vite.config.ts +74 -0
- package/data/Generator/templates/sdk/wasp/api/events.ts +11 -0
- package/data/Generator/templates/sdk/wasp/api/index.ts +136 -0
- package/data/Generator/templates/sdk/wasp/auth/email/actions/login.ts +13 -0
- package/data/Generator/templates/sdk/wasp/auth/email/actions/passwordReset.ts +22 -0
- package/data/Generator/templates/sdk/wasp/auth/email/actions/signup.ts +20 -0
- package/data/Generator/templates/sdk/wasp/auth/email/actions/verifyEmail.ts +14 -0
- package/data/Generator/templates/sdk/wasp/auth/email/index.ts +5 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/Auth.tsx +108 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/ForgotPassword.tsx +18 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/Login.tsx +18 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/ResetPassword.tsx +18 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/Signup.tsx +24 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/VerifyEmail.tsx +18 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/Form.tsx +107 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/Message.tsx +21 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/common/LoginSignupForm.tsx +356 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/ForgotPasswordForm.tsx +52 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/ResetPasswordForm.tsx +82 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/VerifyEmailForm.tsx +42 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/email/useEmail.ts +33 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialButton.tsx +33 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/social/SocialIcons.tsx +78 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/internal/usernameAndPassword/useUsernameAndPassword.ts +29 -0
- package/data/Generator/templates/sdk/wasp/auth/forms/types.ts +52 -0
- package/data/Generator/templates/sdk/wasp/auth/helpers/_Provider.tsx +17 -0
- package/data/Generator/templates/sdk/wasp/auth/helpers/user.ts +15 -0
- package/data/Generator/templates/sdk/wasp/auth/index.ts +9 -0
- package/data/Generator/templates/sdk/wasp/auth/jwt.ts +22 -0
- package/data/Generator/templates/sdk/wasp/auth/logout.ts +18 -0
- package/data/Generator/templates/sdk/wasp/auth/lucia.ts +53 -0
- package/data/Generator/templates/sdk/wasp/auth/password.ts +36 -0
- package/data/Generator/templates/sdk/wasp/auth/providers/index.ts +9 -0
- package/data/Generator/templates/sdk/wasp/auth/providers/types.ts +68 -0
- package/data/Generator/templates/sdk/wasp/auth/session.ts +78 -0
- package/data/Generator/templates/sdk/wasp/auth/types.ts +2 -0
- package/data/Generator/templates/sdk/wasp/auth/useAuth.ts +37 -0
- package/data/Generator/templates/sdk/wasp/auth/user.ts +63 -0
- package/data/Generator/templates/sdk/wasp/auth/username/actions/login.ts +13 -0
- package/data/Generator/templates/sdk/wasp/auth/username/actions/signup.ts +20 -0
- package/data/Generator/templates/sdk/wasp/auth/username/index.ts +2 -0
- package/data/Generator/templates/sdk/wasp/auth/utils.ts +369 -0
- package/data/Generator/templates/sdk/wasp/auth/validation.ts +83 -0
- package/data/Generator/templates/sdk/wasp/client/auth/discord.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/email.ts +5 -0
- package/data/Generator/templates/sdk/wasp/client/auth/github.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/google.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/index.ts +29 -0
- package/data/Generator/templates/sdk/wasp/client/auth/keycloak.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/slack.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/auth/ui.ts +32 -0
- package/data/Generator/templates/sdk/wasp/client/auth/username.ts +2 -0
- package/data/Generator/templates/sdk/wasp/client/config.ts +14 -0
- package/data/Generator/templates/sdk/wasp/client/crud/_crud.ts +89 -0
- package/data/Generator/templates/sdk/wasp/client/crud/index.ts +4 -0
- package/data/Generator/templates/sdk/wasp/client/crud/operationsHelpers.ts +21 -0
- package/data/Generator/templates/sdk/wasp/client/env/schema.ts +22 -0
- package/data/Generator/templates/sdk/wasp/client/env.ts +5 -0
- package/data/Generator/templates/sdk/wasp/client/index.ts +17 -0
- package/data/Generator/templates/sdk/wasp/client/operations/actions/core.ts +49 -0
- package/data/Generator/templates/sdk/wasp/client/operations/actions/index.ts +13 -0
- package/data/Generator/templates/sdk/wasp/client/operations/hooks.ts +347 -0
- package/data/Generator/templates/sdk/wasp/client/operations/index.ts +22 -0
- package/data/Generator/templates/sdk/wasp/client/operations/internal/index.ts +22 -0
- package/data/Generator/templates/sdk/wasp/client/operations/internal/resources.js +83 -0
- package/data/Generator/templates/sdk/wasp/client/operations/internal/updateHandlersMap.js +37 -0
- package/data/Generator/templates/sdk/wasp/client/operations/queries/core.ts +91 -0
- package/data/Generator/templates/sdk/wasp/client/operations/queries/index.ts +16 -0
- package/data/Generator/templates/sdk/wasp/client/operations/queryClient.ts +34 -0
- package/data/Generator/templates/sdk/wasp/client/operations/rpc.ts +96 -0
- package/data/Generator/templates/sdk/wasp/client/router/Link.tsx +21 -0
- package/data/Generator/templates/sdk/wasp/client/router/index.ts +53 -0
- package/data/Generator/templates/sdk/wasp/client/router/linkHelpers.ts +48 -0
- package/data/Generator/templates/sdk/wasp/client/router/types.ts +98 -0
- package/data/Generator/templates/sdk/wasp/client/test/index.ts +1 -0
- package/data/Generator/templates/sdk/wasp/client/test/vitest/helpers.tsx +95 -0
- package/data/Generator/templates/sdk/wasp/client/webSocket/WebSocketProvider.tsx +77 -0
- package/data/Generator/templates/sdk/wasp/client/webSocket/index.ts +39 -0
- package/data/Generator/templates/sdk/wasp/core/auth.ts +40 -0
- package/data/Generator/templates/sdk/wasp/core/serialization/custom-register.ts +21 -0
- package/data/Generator/templates/sdk/wasp/core/serialization/index.ts +56 -0
- package/data/Generator/templates/sdk/wasp/core/serialization/prisma.ts +54 -0
- package/data/Generator/templates/sdk/wasp/core/stitches.config.ts +39 -0
- package/data/Generator/templates/sdk/wasp/core/storage.ts +50 -0
- package/data/Generator/templates/sdk/wasp/dev/index.ts +19 -0
- package/data/Generator/templates/sdk/wasp/entities/index.ts +28 -0
- package/data/Generator/templates/sdk/wasp/env/index.ts +9 -0
- package/data/Generator/templates/sdk/wasp/env/validation.ts +38 -0
- package/data/Generator/templates/sdk/wasp/package.json +151 -0
- package/data/Generator/templates/sdk/wasp/prisma-runtime-library.d.ts +17 -0
- package/data/Generator/templates/sdk/wasp/server/HttpError.ts +30 -0
- package/data/Generator/templates/sdk/wasp/server/_types/index.ts +105 -0
- package/data/Generator/templates/sdk/wasp/server/_types/taggedEntities.ts +26 -0
- package/data/Generator/templates/sdk/wasp/server/api/index.ts +44 -0
- package/data/Generator/templates/sdk/wasp/server/auth/email/index.ts +20 -0
- package/data/Generator/templates/sdk/wasp/server/auth/email/utils.ts +104 -0
- package/data/Generator/templates/sdk/wasp/server/auth/hooks.ts +188 -0
- package/data/Generator/templates/sdk/wasp/server/auth/index.ts +49 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/index.ts +38 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/oneTimeCode.ts +50 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/provider.ts +20 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/discord.ts +22 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/github.ts +20 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/google.ts +22 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/keycloak.ts +23 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/providers/slack.ts +22 -0
- package/data/Generator/templates/sdk/wasp/server/auth/oauth/redirect.ts +43 -0
- package/data/Generator/templates/sdk/wasp/server/auth/user.ts +148 -0
- package/data/Generator/templates/sdk/wasp/server/auth/username.ts +1 -0
- package/data/Generator/templates/sdk/wasp/server/config.ts +47 -0
- package/data/Generator/templates/sdk/wasp/server/crud/_operationTypes.ts +134 -0
- package/data/Generator/templates/sdk/wasp/server/crud/index.ts +5 -0
- package/data/Generator/templates/sdk/wasp/server/dbClient.ts +35 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/helpers.ts +40 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/index.ts +17 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/providers/dummy.ts +34 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/providers/mailgun.ts +31 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/providers/sendgrid.ts +44 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/providers/smtp.ts +29 -0
- package/data/Generator/templates/sdk/wasp/server/email/core/types.ts +59 -0
- package/data/Generator/templates/sdk/wasp/server/email/index.ts +39 -0
- package/data/Generator/templates/sdk/wasp/server/env.ts +168 -0
- package/data/Generator/templates/sdk/wasp/server/index.ts +17 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/_job.ts +39 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/job.ts +28 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/index.ts +3 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/pgBoss.ts +76 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/pgBossJob.ts +230 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/core/pgBoss/types.ts +9 -0
- package/data/Generator/templates/sdk/wasp/server/jobs/index.ts +5 -0
- package/data/Generator/templates/sdk/wasp/server/middleware/globalMiddleware.ts +8 -0
- package/data/Generator/templates/sdk/wasp/server/middleware/index.ts +1 -0
- package/data/Generator/templates/sdk/wasp/server/operations/actions/index.ts +41 -0
- package/data/Generator/templates/sdk/wasp/server/operations/actions/types.ts +35 -0
- package/data/Generator/templates/sdk/wasp/server/operations/index.ts +13 -0
- package/data/Generator/templates/sdk/wasp/server/operations/queries/index.ts +42 -0
- package/data/Generator/templates/sdk/wasp/server/operations/queries/types.ts +36 -0
- package/data/Generator/templates/sdk/wasp/server/operations/wrappers.ts +242 -0
- package/data/Generator/templates/sdk/wasp/server/types/index.ts +11 -0
- package/data/Generator/templates/sdk/wasp/server/utils.ts +38 -0
- package/data/Generator/templates/sdk/wasp/server/webSocket/index.ts +57 -0
- package/data/Generator/templates/sdk/wasp/tsconfig.json +114 -0
- package/data/Generator/templates/sdk/wasp/universal/ansiColors.ts +14 -0
- package/data/Generator/templates/sdk/wasp/universal/predicates.ts +3 -0
- package/data/Generator/templates/sdk/wasp/universal/types.ts +74 -0
- package/data/Generator/templates/sdk/wasp/universal/url.ts +5 -0
- package/data/Generator/templates/sdk/wasp/universal/validators.ts +21 -0
- package/data/Generator/templates/sdk/wasp/vite-env.d.ts +1 -0
- package/data/Generator/templates/server/README.md +1 -0
- package/data/Generator/templates/server/gitignore +6 -0
- package/data/Generator/templates/server/nodemon.json +13 -0
- package/data/Generator/templates/server/npmrc +1 -0
- package/data/Generator/templates/server/package.json +27 -0
- package/data/Generator/templates/server/rollup.config.js +44 -0
- package/data/Generator/templates/server/src/actions/_action.ts +18 -0
- package/data/Generator/templates/server/src/app.js +36 -0
- package/data/Generator/templates/server/src/auth/hooks.ts +135 -0
- package/data/Generator/templates/server/src/auth/providers/config/discord.ts +69 -0
- package/data/Generator/templates/server/src/auth/providers/config/email.ts +96 -0
- package/data/Generator/templates/server/src/auth/providers/config/github.ts +78 -0
- package/data/Generator/templates/server/src/auth/providers/config/google.ts +65 -0
- package/data/Generator/templates/server/src/auth/providers/config/keycloak.ts +67 -0
- package/data/Generator/templates/server/src/auth/providers/config/slack.ts +65 -0
- package/data/Generator/templates/server/src/auth/providers/config/username.ts +33 -0
- package/data/Generator/templates/server/src/auth/providers/email/login.ts +66 -0
- package/data/Generator/templates/server/src/auth/providers/email/requestPasswordReset.ts +74 -0
- package/data/Generator/templates/server/src/auth/providers/email/resetPassword.ts +48 -0
- package/data/Generator/templates/server/src/auth/providers/email/signup.ts +165 -0
- package/data/Generator/templates/server/src/auth/providers/email/verifyEmail.ts +42 -0
- package/data/Generator/templates/server/src/auth/providers/index.ts +32 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/config.ts +19 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/cookies.ts +35 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/handler.ts +130 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/oneTimeCode.ts +39 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/state.ts +144 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/types.ts +7 -0
- package/data/Generator/templates/server/src/auth/providers/oauth/user.ts +139 -0
- package/data/Generator/templates/server/src/auth/providers/username/login.ts +64 -0
- package/data/Generator/templates/server/src/auth/providers/username/signup.ts +59 -0
- package/data/Generator/templates/server/src/crud/_operations.ts +184 -0
- package/data/Generator/templates/server/src/dbSeed.ts +37 -0
- package/data/Generator/templates/server/src/jobs/_job.ts +9 -0
- package/data/Generator/templates/server/src/jobs/core/allJobs.ts +8 -0
- package/data/Generator/templates/server/src/middleware/globalMiddleware.ts +45 -0
- package/data/Generator/templates/server/src/middleware/index.ts +1 -0
- package/data/Generator/templates/server/src/middleware/operations.ts +28 -0
- package/data/Generator/templates/server/src/queries/_query.ts +18 -0
- package/data/Generator/templates/server/src/routes/apis/index.ts +67 -0
- package/data/Generator/templates/server/src/routes/auth/index.js +16 -0
- package/data/Generator/templates/server/src/routes/auth/logout.ts +12 -0
- package/data/Generator/templates/server/src/routes/auth/me.ts +10 -0
- package/data/Generator/templates/server/src/routes/crud/_crud.ts +46 -0
- package/data/Generator/templates/server/src/routes/crud/index.ts +12 -0
- package/data/Generator/templates/server/src/routes/index.js +37 -0
- package/data/Generator/templates/server/src/routes/operations/_action.js +5 -0
- package/data/Generator/templates/server/src/routes/operations/_query.js +5 -0
- package/data/Generator/templates/server/src/routes/operations/index.js +18 -0
- package/data/Generator/templates/server/src/server.ts +76 -0
- package/data/Generator/templates/server/src/webSocket/initialization.ts +59 -0
- package/data/Generator/templates/server/tsconfig.json +41 -0
- package/data/Lsp/templates/ts/action.fn.ts +12 -0
- package/data/Lsp/templates/ts/operation.fn.js +7 -0
- package/data/Lsp/templates/ts/page.component.jsx +9 -0
- package/data/Lsp/templates/ts/query.fn.ts +12 -0
- package/main.js +9 -0
- package/package.json +1 -0
- package/readme.md +3 -0
- package/wasp-bin +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Wasp Starters
|
|
2
|
+
|
|
3
|
+
This directory contains starter templates for creating new Wasp projects.
|
|
4
|
+
|
|
5
|
+
## How Wasp Starters Work
|
|
6
|
+
|
|
7
|
+
When you create a new project using `wasp new`, Wasp creates the project in 3 steps:
|
|
8
|
+
|
|
9
|
+
1. **Copy skeleton files**: Wasp copies the [`skeleton`](./skeleton) files into the project directory
|
|
10
|
+
2. **Copy starter template files**: Wasp copies the chosen starter template files (e.g., `basic`) into the project directory
|
|
11
|
+
3. **Replace placeholders**: Wasp replaces template placeholders in the project files (e.g., app name)
|
|
12
|
+
|
|
13
|
+
Due to this behavior, all files shared by all starters are placed in the [`skeleton`](./skeleton) directory.
|
|
14
|
+
|
|
15
|
+
## Development Workflow
|
|
16
|
+
|
|
17
|
+
The recommended approach for developing starter templates:
|
|
18
|
+
|
|
19
|
+
1. **Create a test project**: Create a new project with the starter you want to modify
|
|
20
|
+
2. **Implement changes**: Make your required changes in the Wasp project
|
|
21
|
+
3. **Copy changes back**: Once satisfied with the implementation, copy the files from your project back to the starter templates
|
|
22
|
+
4. **Test the starter**: Create a new project with `wasp-cli` to verify it matches your previously created project
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Basic Starter – A Simple ToDo App
|
|
2
|
+
|
|
3
|
+
Basic starter is a well-rounded template that showcases the most important bits of working with Wasp.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- **Node.js** (newest LTS version recommended): We recommend install Node through a Node version manager, e.g. `nvm`.
|
|
8
|
+
- **Wasp** (latest version): Install via
|
|
9
|
+
```sh
|
|
10
|
+
curl -sSL https://get.wasp.sh/installer.sh | sh
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Using the template
|
|
14
|
+
|
|
15
|
+
You can use this template through the Wasp CLI:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
wasp new <project-name>
|
|
19
|
+
# or
|
|
20
|
+
wasp new <project-name> -t basic
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Development
|
|
24
|
+
|
|
25
|
+
To start the application locally for development or preview purposes:
|
|
26
|
+
|
|
27
|
+
1. Run `wasp db migrate-dev` to migrate the database to the latest migration
|
|
28
|
+
2. Run `wasp start` to start the Wasp application. If running for the first time, this will also install the client and the server dependencies for you.
|
|
29
|
+
3. The application should be running on `localhost:3000`. Open in it your browser to access the client.
|
|
30
|
+
|
|
31
|
+
To improve your Wasp development experience, we recommend installing the [Wasp extension for VSCode](https://marketplace.visualstudio.com/items?itemName=wasp-lang.wasp).
|
|
32
|
+
|
|
33
|
+
## Learn more
|
|
34
|
+
|
|
35
|
+
To find out more about Wasp, visit out [docs](https://wasp.sh/docs).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import eslintPrettier from "eslint-config-prettier/flat";
|
|
3
|
+
import eslintReact from "eslint-plugin-react";
|
|
4
|
+
import { defineConfig } from "eslint/config";
|
|
5
|
+
import globals from "globals";
|
|
6
|
+
import eslintTypescript from "typescript-eslint";
|
|
7
|
+
|
|
8
|
+
export default defineConfig([
|
|
9
|
+
{ files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], plugins: { js }, extends: ["js/recommended"] },
|
|
10
|
+
{ files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], languageOptions: { globals: { ...globals.browser, ...globals.node } } },
|
|
11
|
+
eslintTypescript.configs.recommended,
|
|
12
|
+
eslintReact.configs.flat.recommended,
|
|
13
|
+
eslintReact.configs.flat['jsx-runtime'],
|
|
14
|
+
eslintPrettier,
|
|
15
|
+
]);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
app __waspAppName__ {
|
|
2
|
+
wasp: {
|
|
3
|
+
version: "__waspVersion__"
|
|
4
|
+
},
|
|
5
|
+
title: "__waspProjectName__",
|
|
6
|
+
head: [
|
|
7
|
+
"<link rel='icon' href='/favicon.ico' />",
|
|
8
|
+
],
|
|
9
|
+
auth: {
|
|
10
|
+
userEntity: User,
|
|
11
|
+
methods: {
|
|
12
|
+
email: {
|
|
13
|
+
fromField: {
|
|
14
|
+
name: "Basic App",
|
|
15
|
+
email: "hello@example.com"
|
|
16
|
+
},
|
|
17
|
+
userSignupFields: import { userSignupFields } from "@src/auth/email/userSignupFields",
|
|
18
|
+
emailVerification: {
|
|
19
|
+
clientRoute: EmailVerificationRoute,
|
|
20
|
+
},
|
|
21
|
+
passwordReset: {
|
|
22
|
+
clientRoute: PasswordResetRoute,
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
onAuthSucceededRedirectTo: "/",
|
|
27
|
+
onAuthFailedRedirectTo: "/login",
|
|
28
|
+
},
|
|
29
|
+
emailSender: {
|
|
30
|
+
provider: Dummy,
|
|
31
|
+
},
|
|
32
|
+
client: {
|
|
33
|
+
rootComponent: import { App } from "@src/App.tsx",
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// #region Auth
|
|
38
|
+
route LoginRoute { path: "/login", to: LoginPage }
|
|
39
|
+
page LoginPage {
|
|
40
|
+
component: import { LoginPage } from "@src/auth/email/LoginPage.tsx"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
route SignupRoute { path: "/signup", to: SignupPage }
|
|
44
|
+
page SignupPage {
|
|
45
|
+
component: import { SignupPage } from "@src/auth/email/SignupPage.tsx"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
route RequestPasswordResetRoute { path: "/request-password-reset", to: RequestPasswordResetPage }
|
|
49
|
+
page RequestPasswordResetPage {
|
|
50
|
+
component: import { RequestPasswordResetPage } from "@src/auth/email/RequestPasswordResetPage.tsx",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
route PasswordResetRoute { path: "/password-reset", to: PasswordResetPage }
|
|
54
|
+
page PasswordResetPage {
|
|
55
|
+
component: import { PasswordResetPage } from "@src/auth/email/PasswordResetPage.tsx",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
route EmailVerificationRoute { path: "/email-verification", to: EmailVerificationPage }
|
|
59
|
+
page EmailVerificationPage {
|
|
60
|
+
component: import { EmailVerificationPage } from "@src/auth/email/EmailVerificationPage.tsx",
|
|
61
|
+
}
|
|
62
|
+
// #endregion Auth
|
|
63
|
+
|
|
64
|
+
// #region Tasks
|
|
65
|
+
route TasksRoute { path: "/", to: TasksPage }
|
|
66
|
+
page TasksPage {
|
|
67
|
+
authRequired: true,
|
|
68
|
+
component: import { TasksPage } from "@src/tasks/TasksPage.tsx"
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
query getTasks {
|
|
72
|
+
fn: import { getTasks } from "@src/tasks/queries",
|
|
73
|
+
entities: [Task, Tag]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
action createTask {
|
|
77
|
+
fn: import { createTask } from "@src/tasks/actions",
|
|
78
|
+
entities: [Task]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
action updateTaskStatus {
|
|
82
|
+
fn: import { updateTaskStatus } from "@src/tasks/actions",
|
|
83
|
+
entities: [Task]
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
action deleteCompletedTasks {
|
|
87
|
+
fn: import { deleteCompletedTasks } from "@src/tasks/actions",
|
|
88
|
+
entities: [Task],
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
query getTags {
|
|
92
|
+
fn: import { getTags } from "@src/tags/queries",
|
|
93
|
+
entities: [Tag]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
action createTag {
|
|
97
|
+
fn: import { createTag } from "@src/tags/actions",
|
|
98
|
+
entities: [Tag]
|
|
99
|
+
}
|
|
100
|
+
// #endregion Tasks
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__waspAppName__",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"react": "^18.2.0",
|
|
6
|
+
"react-dom": "^18.2.0",
|
|
7
|
+
"react-hook-form": "^7.57.0",
|
|
8
|
+
"react-router-dom": "^6.26.2",
|
|
9
|
+
"tailwind-merge": "~2.6.0",
|
|
10
|
+
"wasp": "file:.wasp/out/sdk/wasp"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@eslint/js": "^9.27.0",
|
|
14
|
+
"@types/react": "^18.0.37",
|
|
15
|
+
"eslint": "^9.27.0",
|
|
16
|
+
"eslint-config-prettier": "^10.1.5",
|
|
17
|
+
"eslint-plugin-react": "^7.37.5",
|
|
18
|
+
"globals": "^16.1.0",
|
|
19
|
+
"prettier": "^3.5.3",
|
|
20
|
+
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
21
|
+
"prisma": "5.19.1",
|
|
22
|
+
"tailwindcss": "^3.4.17",
|
|
23
|
+
"typescript": "5.8.2",
|
|
24
|
+
"typescript-eslint": "^8.32.1",
|
|
25
|
+
"vite": "^4.3.9"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
datasource db {
|
|
2
|
+
provider = "sqlite"
|
|
3
|
+
url = env("DATABASE_URL")
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
generator client {
|
|
7
|
+
provider = "prisma-client-js"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Use Prisma Schema file to define your entities: https://www.prisma.io/docs/concepts/components/prisma-schema.
|
|
11
|
+
// Run `wasp db migrate-dev` in the CLI to create the database tables,
|
|
12
|
+
// then run `wasp db studio` to open Prisma Studio and view your db models.
|
|
13
|
+
model User {
|
|
14
|
+
id String @id @default(uuid())
|
|
15
|
+
username String
|
|
16
|
+
|
|
17
|
+
tasks Task[]
|
|
18
|
+
tags Tag[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
model Task {
|
|
22
|
+
id String @id @default(uuid())
|
|
23
|
+
description String
|
|
24
|
+
isDone Boolean @default(false)
|
|
25
|
+
createdAt DateTime @default(now())
|
|
26
|
+
|
|
27
|
+
user User @relation(fields: [userId], references: [id])
|
|
28
|
+
userId String
|
|
29
|
+
|
|
30
|
+
tags Tag[]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
model Tag {
|
|
34
|
+
id String @id @default(uuid())
|
|
35
|
+
name String @unique
|
|
36
|
+
color String
|
|
37
|
+
|
|
38
|
+
user User @relation(fields: [userId], references: [id])
|
|
39
|
+
userId String
|
|
40
|
+
|
|
41
|
+
tasks Task[]
|
|
42
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@layer components {
|
|
6
|
+
.card {
|
|
7
|
+
@apply rounded-xl border border-neutral-200 bg-white shadow-sm transition-all duration-200;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.label {
|
|
11
|
+
@apply text-sm font-medium text-neutral-700;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Outlet } from "react-router-dom";
|
|
2
|
+
import "./App.css";
|
|
3
|
+
import { Header } from "./shared/components/Header";
|
|
4
|
+
|
|
5
|
+
export function App() {
|
|
6
|
+
return (
|
|
7
|
+
<main className="flex min-h-screen w-full flex-col bg-neutral-50 text-neutral-800">
|
|
8
|
+
<Header />
|
|
9
|
+
<Outlet />
|
|
10
|
+
</main>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 161 161"><defs><style>.cls-1{fill:#f5cc05;}.cls-2{fill-rule:evenodd;}</style></defs><g id="Page-1"><g id="Group-23"><circle id="Oval" class="cls-1" cx="80.5" cy="80.5" r="79"/><g id="Group-36"><g id="_" data-name="}"><path id="path-2" class="cls-2" d="M88.67,114.33h2.91q6,0,7.87-1.89c1.22-1.25,1.83-3.9,1.83-7.93V93.89c0-4.46.65-7.7,1.93-9.73s3.51-3.43,6.67-4.2q-4.69-1.08-6.65-4.12c-1.3-2-2-5.28-2-9.77V55.44q0-6-1.83-7.93t-7.87-1.88H88.67V39.5h2.65q10.65,0,14.24,3.15t3.59,12.62V65.56c0,4.28.77,7.24,2.29,8.87s4.3,2.44,8.32,2.44h2.74V83h-2.74q-6,0-8.32,2.49c-1.52,1.65-2.29,4.64-2.29,9v10.25q0,9.47-3.59,12.64T91.32,120.5H88.67Z"/><path id="path-2-2" data-name="path-2" class="cls-2" d="M88.67,114.33h2.91q6,0,7.87-1.89c1.22-1.25,1.83-3.9,1.83-7.93V93.89c0-4.46.65-7.7,1.93-9.73s3.51-3.43,6.67-4.2q-4.69-1.08-6.65-4.12c-1.3-2-2-5.28-2-9.77V55.44q0-6-1.83-7.93t-7.87-1.88H88.67V39.5h2.65q10.65,0,14.24,3.15t3.59,12.62V65.56c0,4.28.77,7.24,2.29,8.87s4.3,2.44,8.32,2.44h2.74V83h-2.74q-6,0-8.32,2.49c-1.52,1.65-2.29,4.64-2.29,9v10.25q0,9.47-3.59,12.64T91.32,120.5H88.67Z"/></g><g id="text831"><g id="_2" data-name="="><path id="path-3" class="cls-2" d="M38.5,85.15H75.83v7.58H38.5Zm0-17.88H75.83v7.49H38.5Z"/><path id="path-3-2" data-name="path-3" class="cls-2" d="M38.5,85.15H75.83v7.58H38.5Zm0-17.88H75.83v7.49H38.5Z"/></g></g></g></g></g></svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function AuthLayout({ children }: React.PropsWithChildren) {
|
|
2
|
+
return (
|
|
3
|
+
<div className="flex justify-center">
|
|
4
|
+
{/* Auth UI has margin-top on title, so we lower the top padding */}
|
|
5
|
+
<div className="card mt-32 h-fit w-full max-w-md px-8 py-10 pt-4">
|
|
6
|
+
{children}
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
);
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Link } from "react-router-dom";
|
|
2
|
+
import { VerifyEmailForm } from "wasp/client/auth";
|
|
3
|
+
import { AuthLayout } from "../AuthLayout";
|
|
4
|
+
|
|
5
|
+
export function EmailVerificationPage() {
|
|
6
|
+
return (
|
|
7
|
+
<AuthLayout>
|
|
8
|
+
<VerifyEmailForm />
|
|
9
|
+
<br />
|
|
10
|
+
<span className="text-sm font-medium text-neutral-900">
|
|
11
|
+
{"If everything is okay, "}
|
|
12
|
+
<Link to="/login" className="font-semibold underline">
|
|
13
|
+
go to login
|
|
14
|
+
</Link>
|
|
15
|
+
.
|
|
16
|
+
</span>
|
|
17
|
+
</AuthLayout>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Link } from "react-router-dom";
|
|
2
|
+
import { LoginForm } from "wasp/client/auth";
|
|
3
|
+
import { AuthLayout } from "../AuthLayout";
|
|
4
|
+
|
|
5
|
+
export function LoginPage() {
|
|
6
|
+
return (
|
|
7
|
+
<AuthLayout>
|
|
8
|
+
<LoginForm />
|
|
9
|
+
<br />
|
|
10
|
+
<span className="text-sm font-medium text-neutral-900">
|
|
11
|
+
{"Don't have an account yet? "}
|
|
12
|
+
<Link to="/signup" className="font-semibold underline">
|
|
13
|
+
Go to signup
|
|
14
|
+
</Link>
|
|
15
|
+
.
|
|
16
|
+
</span>
|
|
17
|
+
<br />
|
|
18
|
+
<span className="text-sm font-medium text-neutral-900">
|
|
19
|
+
{"Forgot your password? "}
|
|
20
|
+
<Link to="/request-password-reset" className="font-semibold underline">
|
|
21
|
+
Reset it
|
|
22
|
+
</Link>
|
|
23
|
+
.
|
|
24
|
+
</span>
|
|
25
|
+
</AuthLayout>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Link } from "react-router-dom";
|
|
2
|
+
import { ResetPasswordForm } from "wasp/client/auth";
|
|
3
|
+
import { AuthLayout } from "../AuthLayout";
|
|
4
|
+
|
|
5
|
+
export function PasswordResetPage() {
|
|
6
|
+
return (
|
|
7
|
+
<AuthLayout>
|
|
8
|
+
<ResetPasswordForm />
|
|
9
|
+
<br />
|
|
10
|
+
<span className="text-sm font-medium text-neutral-900">
|
|
11
|
+
{"If everything is okay, "}
|
|
12
|
+
<Link to="/login" className="font-semibold underline">
|
|
13
|
+
go to login
|
|
14
|
+
</Link>
|
|
15
|
+
.
|
|
16
|
+
</span>
|
|
17
|
+
</AuthLayout>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Link } from "react-router-dom";
|
|
2
|
+
import { SignupForm } from "wasp/client/auth";
|
|
3
|
+
import { AuthLayout } from "../AuthLayout";
|
|
4
|
+
|
|
5
|
+
export function SignupPage() {
|
|
6
|
+
return (
|
|
7
|
+
<AuthLayout>
|
|
8
|
+
<SignupForm
|
|
9
|
+
additionalFields={[
|
|
10
|
+
{
|
|
11
|
+
name: "username",
|
|
12
|
+
type: "input",
|
|
13
|
+
label: "Username",
|
|
14
|
+
validations: {
|
|
15
|
+
required: "Username is required",
|
|
16
|
+
minLength: {
|
|
17
|
+
value: 6,
|
|
18
|
+
message: "Username must be at least 6 characters long",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
]}
|
|
23
|
+
/>
|
|
24
|
+
<br />
|
|
25
|
+
<span className="text-sm font-medium text-neutral-900">
|
|
26
|
+
{"Already have an account? "}
|
|
27
|
+
<Link to="/login" className="font-semibold underline">
|
|
28
|
+
Go to login
|
|
29
|
+
</Link>
|
|
30
|
+
.
|
|
31
|
+
</span>
|
|
32
|
+
</AuthLayout>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineUserSignupFields } from "wasp/server/auth";
|
|
2
|
+
|
|
3
|
+
export const userSignupFields = defineUserSignupFields({
|
|
4
|
+
username: (data) => {
|
|
5
|
+
if (typeof data.username !== "string") {
|
|
6
|
+
throw new Error("Username is required.");
|
|
7
|
+
}
|
|
8
|
+
if (data.username.length < 6) {
|
|
9
|
+
throw new Error("Username must be at least 6 characters long.");
|
|
10
|
+
}
|
|
11
|
+
return data.username;
|
|
12
|
+
},
|
|
13
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { ClassNameValue, twJoin } from "tailwind-merge";
|
|
2
|
+
import { Link } from "wasp/client/router";
|
|
3
|
+
|
|
4
|
+
type ButtonSize = "md" | "sm" | "xs";
|
|
5
|
+
type ButtonVariant = "primary" | "danger" | "ghost";
|
|
6
|
+
|
|
7
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
8
|
+
size?: ButtonSize;
|
|
9
|
+
variant?: ButtonVariant;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function Button({
|
|
13
|
+
children,
|
|
14
|
+
className,
|
|
15
|
+
type = "button",
|
|
16
|
+
size = "md",
|
|
17
|
+
variant = "primary",
|
|
18
|
+
...props
|
|
19
|
+
}: ButtonProps) {
|
|
20
|
+
return (
|
|
21
|
+
<button
|
|
22
|
+
type={type}
|
|
23
|
+
className={getButtonClasses({
|
|
24
|
+
size,
|
|
25
|
+
variant,
|
|
26
|
+
className,
|
|
27
|
+
})}
|
|
28
|
+
{...props}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</button>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type ButtonLinkProps = React.ComponentProps<typeof Link> & {
|
|
36
|
+
size?: ButtonSize;
|
|
37
|
+
variant?: ButtonVariant;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export function ButtonLink({
|
|
41
|
+
children,
|
|
42
|
+
className,
|
|
43
|
+
size = "md",
|
|
44
|
+
variant = "primary",
|
|
45
|
+
...props
|
|
46
|
+
}: ButtonLinkProps) {
|
|
47
|
+
return (
|
|
48
|
+
<Link
|
|
49
|
+
className={getButtonClasses({
|
|
50
|
+
size,
|
|
51
|
+
variant,
|
|
52
|
+
className,
|
|
53
|
+
})}
|
|
54
|
+
{...props}
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
</Link>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function getButtonClasses({
|
|
62
|
+
size,
|
|
63
|
+
variant,
|
|
64
|
+
className,
|
|
65
|
+
}: {
|
|
66
|
+
size: ButtonSize;
|
|
67
|
+
variant: ButtonVariant;
|
|
68
|
+
className: ClassNameValue;
|
|
69
|
+
}): string {
|
|
70
|
+
return twJoin(
|
|
71
|
+
"rounded-md font-semibold",
|
|
72
|
+
variantStyles[variant],
|
|
73
|
+
sizeStyles[size],
|
|
74
|
+
className,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const sizeStyles: Record<ButtonSize, ClassNameValue> = {
|
|
79
|
+
md: "px-4 py-2",
|
|
80
|
+
sm: "px-3 py-1.5 text-sm",
|
|
81
|
+
xs: "px-2 py-1 text-xs",
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const variantStyles: Record<ButtonVariant, ClassNameValue> = {
|
|
85
|
+
primary:
|
|
86
|
+
"bg-primary-500 hover:bg-primary-400 active:bg-primary-300 text-neutral-800",
|
|
87
|
+
danger: "bg-red-600 text-white hover:bg-red-700 active:bg-red-800",
|
|
88
|
+
ghost:
|
|
89
|
+
"bg-transparent text-neutral-800 hover:bg-neutral-100 active:bg-neutral-200",
|
|
90
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { twJoin } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
interface DialogProps extends React.PropsWithChildren {
|
|
5
|
+
open: boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
closeOnClickOutside?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Dialog({
|
|
11
|
+
open,
|
|
12
|
+
onClose,
|
|
13
|
+
children,
|
|
14
|
+
closeOnClickOutside = true,
|
|
15
|
+
}: DialogProps) {
|
|
16
|
+
const dialogRef = React.useRef<HTMLDialogElement>(null);
|
|
17
|
+
|
|
18
|
+
React.useEffect(
|
|
19
|
+
function handleShowOrCloseDialog() {
|
|
20
|
+
const dialog = dialogRef.current;
|
|
21
|
+
if (!dialog) return;
|
|
22
|
+
|
|
23
|
+
if (open && !dialog.open) {
|
|
24
|
+
dialog.showModal();
|
|
25
|
+
} else if (!open && dialog.open) {
|
|
26
|
+
dialog.close();
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
[open],
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
React.useEffect(
|
|
33
|
+
function handleCloseOnClickOutside() {
|
|
34
|
+
if (!closeOnClickOutside) return;
|
|
35
|
+
|
|
36
|
+
const dialog = dialogRef.current;
|
|
37
|
+
if (!dialog) return;
|
|
38
|
+
|
|
39
|
+
const handleClick = (e: MouseEvent) => {
|
|
40
|
+
const rect = dialog.getBoundingClientRect();
|
|
41
|
+
const clickedOutside =
|
|
42
|
+
e.clientX < rect.left ||
|
|
43
|
+
e.clientX > rect.right ||
|
|
44
|
+
e.clientY < rect.top ||
|
|
45
|
+
e.clientY > rect.bottom;
|
|
46
|
+
|
|
47
|
+
if (clickedOutside) {
|
|
48
|
+
onClose();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
dialog.addEventListener("click", handleClick);
|
|
53
|
+
return () => {
|
|
54
|
+
dialog.removeEventListener("click", handleClick);
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
[closeOnClickOutside, onClose],
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
React.useEffect(
|
|
61
|
+
function handlePreventScroll() {
|
|
62
|
+
if (!open) return;
|
|
63
|
+
|
|
64
|
+
const originalOverflow = document.body.style.overflow;
|
|
65
|
+
document.body.style.overflow = "hidden";
|
|
66
|
+
return () => {
|
|
67
|
+
document.body.style.overflow = originalOverflow;
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
[open],
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<dialog
|
|
75
|
+
ref={dialogRef}
|
|
76
|
+
className={twJoin(
|
|
77
|
+
"max-h top-[20vh] my-0 flex max-h-[55vh]",
|
|
78
|
+
"bg-transparent backdrop:bg-black/50 backdrop:backdrop-blur-sm",
|
|
79
|
+
)}
|
|
80
|
+
onClose={onClose}
|
|
81
|
+
>
|
|
82
|
+
{children}
|
|
83
|
+
</dialog>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { logout, useAuth } from "wasp/client/auth";
|
|
2
|
+
import { Link } from "wasp/client/router";
|
|
3
|
+
import Logo from "../../assets/logo.svg";
|
|
4
|
+
import { Button, ButtonLink } from "./Button";
|
|
5
|
+
|
|
6
|
+
export function Header() {
|
|
7
|
+
const { data: user } = useAuth();
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<header className="sticky top-0 z-10 flex justify-center border-b border-neutral-200 bg-white shadow">
|
|
11
|
+
<div className="flex w-full max-w-screen-lg items-center justify-between p-4 px-12">
|
|
12
|
+
<Link to="/" className="flex items-center gap-2">
|
|
13
|
+
<img src={Logo} alt="Todo App Logo" className="h-10 w-10" />
|
|
14
|
+
<h1 className="text-2xl font-semibold">Todo App</h1>
|
|
15
|
+
</Link>
|
|
16
|
+
<nav>
|
|
17
|
+
<ul className="flex gap-4 font-semibold">
|
|
18
|
+
{user ? (
|
|
19
|
+
<li>
|
|
20
|
+
<Button onClick={logout}>Log out</Button>
|
|
21
|
+
</li>
|
|
22
|
+
) : (
|
|
23
|
+
<>
|
|
24
|
+
<li>
|
|
25
|
+
<ButtonLink to="/signup">Sign up</ButtonLink>
|
|
26
|
+
</li>
|
|
27
|
+
<li>
|
|
28
|
+
<ButtonLink to="/login" variant="ghost">
|
|
29
|
+
Login
|
|
30
|
+
</ButtonLink>
|
|
31
|
+
</li>
|
|
32
|
+
</>
|
|
33
|
+
)}
|
|
34
|
+
</ul>
|
|
35
|
+
</nav>
|
|
36
|
+
</div>
|
|
37
|
+
</header>
|
|
38
|
+
);
|
|
39
|
+
}
|