Skip to content

Commit

Permalink
Merge pull request #908 from thunderstore-io/RHF-and-create-team-form
Browse files Browse the repository at this point in the history
Add RHF and CreateTeamForm
  • Loading branch information
MythicManiac authored Nov 20, 2023
2 parents 875ff01 + 903f46d commit 37ffb59
Show file tree
Hide file tree
Showing 51 changed files with 831 additions and 137 deletions.
3 changes: 3 additions & 0 deletions packages/cyberstorm-forms/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/dist/
/node_modules/
/tsconfig.tsbuildinfo
8 changes: 8 additions & 0 deletions packages/cyberstorm-forms/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# cyberstorm-forms

Cyberstorm form components

## Scripts

- `yarn run build`: Builds the project
- `yarn run dev`: Builds the project & watches files for changes, triggering a rebuild
27 changes: 27 additions & 0 deletions packages/cyberstorm-forms/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "@thunderstore/cyberstorm-forms",
"version": "0.1.0",
"description": "Cyberstorm form components",
"repository": "https://github.com/thunderstore-io/thunderstore-ui/",
"main": "dist/thunderstore-cyberstorm-forms.cjs.js",
"module": "dist/thunderstore-cyberstorm-forms.esm.js",
"types": "dist/thunderstore-cyberstorm-forms.cjs.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"dev": "tsc --watch"
},
"dependencies": {
"@thunderstore/cyberstorm": "*",
"@types/react": "^18.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.48.2",
"zod": "^3.22.2"
},
"devDependencies": {
"typescript-plugin-css-modules": "^3.4.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.spinningIcon {
animation: rotate 2s linear infinite;
}

@keyframes rotate {
100% {
transform: rotate(360deg);
}
}
39 changes: 39 additions & 0 deletions packages/cyberstorm-forms/src/components/FormSubmitButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"use client";

import { Button } from "@thunderstore/cyberstorm";
import React from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowsRotate } from "@fortawesome/free-solid-svg-icons";
import { useFormState } from "react-hook-form";
import styles from "./FormSubmitButton.module.css";

const SubmitButtonContent = React.memo((props: { isSubmitting: boolean }) => {
if (props.isSubmitting) {
return (
<Button.ButtonIcon iconClasses={styles.spinningIcon}>
<FontAwesomeIcon icon={faArrowsRotate} />
</Button.ButtonIcon>
);
} else {
return <Button.ButtonLabel>Create</Button.ButtonLabel>;
}
});

SubmitButtonContent.displayName = "SubmitButtonContent";

export function FormSubmitButton() {
const { isSubmitting, disabled } = useFormState();

return (
<Button.Root
type="submit"
paddingSize="large"
colorScheme="success"
disabled={isSubmitting || disabled}
>
<SubmitButtonContent isSubmitting={isSubmitting} />
</Button.Root>
);
}

FormSubmitButton.displayName = "FormSubmitButton";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.errorMessage {
color: #f1385a;
font-weight: 500;
font-size: 0.75rem;
}
42 changes: 42 additions & 0 deletions packages/cyberstorm-forms/src/components/FormTextInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use client";

import { z, ZodObject } from "zod";
import { ZodRawShape } from "zod/lib/types";
import { Path, useController } from "react-hook-form";
import { TextInput } from "@thunderstore/cyberstorm";
import styles from "./FormTextInput.module.css";

export type FormTextInputProps<
Schema extends ZodObject<Z>,
Z extends ZodRawShape
> = {
// The schema is required to allow TS to infer valid values for the name field
schema: Schema;
name: Path<z.infer<Schema>>;
placeholder?: string;
};
export function FormTextInput<
Schema extends ZodObject<Z>,
Z extends ZodRawShape
>({ name, placeholder }: FormTextInputProps<Schema, Z>) {
const {
field,
fieldState: { isDirty, invalid, error },
formState: { isSubmitting, disabled },
} = useController({ name });

return (
<>
<TextInput
{...field}
ref={field.ref}
placeholder={placeholder}
color={isDirty ? (invalid ? "red" : "green") : undefined}
disabled={isSubmitting || disabled}
/>
{error && <span className={styles.errorMessage}>{error.message}</span>}
</>
);
}

FormTextInput.displayName = "FormTextInput";
27 changes: 27 additions & 0 deletions packages/cyberstorm-forms/src/forms/CreateTeamForm.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.root {
display: flex;
flex-direction: column;
gap: 2rem;
}

.dialog {
display: flex;
flex-direction: column;
gap: 1.5rem;
}

.dialogText {
color: var(--color-text--secondary);
font-weight: var(--font-weight-medium);
font-size: var(--font-size--l);
line-height: var(--line-height--l);
}

.footer {
display: flex;
flex-direction: row-reverse;
gap: 1rem;
justify-content: space-between;
padding-top: var(--space--16);
border-top: var(--border);
}
47 changes: 47 additions & 0 deletions packages/cyberstorm-forms/src/forms/CreateTeamForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use client";

import styles from "./CreateTeamForm.module.css";
import { createTeam } from "@thunderstore/thunderstore-api";
import {
ApiForm,
createTeamFormSchema,
} from "@thunderstore/ts-api-react-forms";
import {
FormSubmitButton,
FormTextInput,
useFormToaster,
} from "@thunderstore/cyberstorm-forms";

export function CreateTeamForm() {
const toaster = useFormToaster({
successMessage: "Team created",
});

return (
<ApiForm
{...toaster}
schema={createTeamFormSchema}
endpoint={createTeam}
formProps={{ className: styles.root }}
>
<div className={styles.dialog}>
<div className={styles.dialogText}>
Enter the name of the team you wish to create. Team names can contain
the characters a-z A-Z 0-9 _ and must not start or end with an _
</div>
<div>
<FormTextInput
schema={createTeamFormSchema}
name={"name"}
placeholder={"ExampleName"}
/>
</div>
</div>
<div className={styles.footer}>
<FormSubmitButton />
</div>
</ApiForm>
);
}

CreateTeamForm.displayName = "CreateTeamForm";
4 changes: 4 additions & 0 deletions packages/cyberstorm-forms/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { useFormToaster } from "./useFormToaster";
export { FormSubmitButton } from "./components/FormSubmitButton";
export { FormTextInput } from "./components/FormTextInput";
export { CreateTeamForm } from "./forms/CreateTeamForm";
1 change: 1 addition & 0 deletions packages/cyberstorm-forms/src/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module "*.module.css";
32 changes: 32 additions & 0 deletions packages/cyberstorm-forms/src/useFormToaster.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use client";

import { useToast } from "@thunderstore/cyberstorm/src/components/Toast/Provider";

export type UseFormToasterArgs = {
successMessage: string;
};
export type UseFormToasterReturn = {
onSubmitSuccess: () => void;
onSubmitError: () => void;
};
export function useFormToaster({
successMessage,
}: UseFormToasterArgs): UseFormToasterReturn {
const toast = useToast();

return {
onSubmitSuccess: () => {
toast.addToast({
variant: "success",
message: successMessage,
duration: 30000,
});
},
onSubmitError: () => {
toast.addToast({
variant: "danger",
message: "Unknown error occurred. The error has been logged",
});
},
};
}
34 changes: 34 additions & 0 deletions packages/cyberstorm-forms/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"compilerOptions": {
"target": "es5",
"module": "ES2020",
"skipLibCheck": true,
"moduleResolution": "node",
"removeComments": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"forceConsistentCasingInFileNames": true,
"composite": true,
"outDir": "./dist",
"rootDir": "./src",
"jsx": "react-jsx",
"plugins": [
{
"name": "typescript-plugin-css-modules"
}
]
},
"include": ["./src/**/*.tsx", "./src/**/*.ts"],
"exclude": ["node_modules"]
}
1 change: 1 addition & 0 deletions packages/cyberstorm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@radix-ui/react-tooltip": "^1.0.2",
"@thunderstore/dapper": "^0.1.0",
"@thunderstore/use-promise": "^0.1.0",
"@thunderstore/thunderstore-api": "*",
"@types/react": "^18.0.0",
"react": "^18.2.0",
"react-data-table-component": "^7.5.3",
Expand Down
4 changes: 4 additions & 0 deletions packages/cyberstorm/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface ButtonProps {
style?: { [key: string]: string };
type?: "button" | "submit" | "reset";
tooltipText?: string;
disabled?: boolean;
}

const TooltipWrapper = (props: TooltipWrapperProps) =>
Expand Down Expand Up @@ -82,6 +83,7 @@ const Button = React.forwardRef<
paddingSize = "medium",
iconAlignment = "default",
tooltipText,
disabled = false,
...forwardedProps
} = props;

Expand All @@ -90,6 +92,7 @@ const Button = React.forwardRef<
if (plain) {
const fRef = forwardedRef as React.ForwardedRef<HTMLDivElement>;
const ref = fRef || fallbackRef;
// TODO: Add disabled mode
return (
<TooltipWrapper tooltipText={tooltipText}>
<div
Expand Down Expand Up @@ -124,6 +127,7 @@ const Button = React.forwardRef<
getPaddingSize(paddingSize)
)}
onClick={onClick}
disabled={disabled}
>
{children}
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ export function CommunityListLayout() {
<div className={styles.filters}>
<div className={styles.searchTextInput}>
<TextInput
setValue={setSearchValue}
onChange={(e) => setSearchValue(e.target.value)}
value={searchValue}
placeHolder="Search communities..."
placeholder="Search communities..."
leftIcon={<FontAwesomeIcon icon={faSearch} />}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import * as Button from "../../../Button/";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import { BaseLayout } from "../../BaseLayout/BaseLayout";
import { CreateTeamForm } from "@thunderstore/cyberstorm-forms";
import { Dialog } from "../../../..";

/**
* Cyberstorm PackageUpload Layout
Expand All @@ -34,14 +36,19 @@ export function PackageUploadLayout() {
title="Team"
description="No teams available?"
additionalLeftColumnContent={
<div>
<Button.Root>
<Button.ButtonLabel>Create Team</Button.ButtonLabel>
<Button.ButtonIcon>
<FontAwesomeIcon icon={faPlus} />
</Button.ButtonIcon>
</Button.Root>
</div>
<Dialog.Root
title="Create Team"
trigger={
<Button.Root colorScheme="primary" paddingSize="large">
<Button.ButtonLabel>Create team</Button.ButtonLabel>
<Button.ButtonIcon>
<FontAwesomeIcon icon={faPlus} />
</Button.ButtonIcon>
</Button.Root>
}
>
<CreateTeamForm />
</Dialog.Root>
}
content={<TextInput />}
/>
Expand Down
Loading

0 comments on commit 37ffb59

Please sign in to comment.