diff --git a/README.md b/README.md index d0b44edb5..dffb72c5f 100644 --- a/README.md +++ b/README.md @@ -22,20 +22,19 @@ This project was generated using [Nx](https://nx.dev). The TUP dashboard is accessed at http://localhost:8000/portal. To bring containers down after development, run `npx nx down tup-cms`. - - ## Contributing To contribute, first read [How to Contirbute](./docs/contributing.md). --- + +

🔎 **Smart, Fast and Extensible Build System** diff --git a/apps/tup-cms/Dockerfile b/apps/tup-cms/Dockerfile index 0522fa346..629f5931f 100644 --- a/apps/tup-cms/Dockerfile +++ b/apps/tup-cms/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20 as node_build +FROM --platform=linux/amd64 node:20 as node_build COPY package.json package-lock.json /code/ WORKDIR /code RUN npm ci diff --git a/apps/ui-patterns/src/app/UIPatternsComplexWizard/UIPatternsComplexWizard.tsx b/apps/ui-patterns/src/app/UIPatternsComplexWizard/UIPatternsComplexWizard.tsx index a7d4d677b..cfb88fe87 100644 --- a/apps/ui-patterns/src/app/UIPatternsComplexWizard/UIPatternsComplexWizard.tsx +++ b/apps/ui-patterns/src/app/UIPatternsComplexWizard/UIPatternsComplexWizard.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useMemo } from 'react'; import useWizardValues, { UIWizardProvider } from './useWizardValues'; import { UIWizardStep, UIWizardSchema, UIWizardExtra } from '.'; -import { Wizard, WizardStep } from '@tacc/core-wrappers'; +import { Wizard, WizardStep } from '@tacc/core-components'; import wizardSteps from './steps'; export const UIPatternsComplexWizardRender: React.FC<{ @@ -26,7 +26,7 @@ export const UIPatternsComplexWizardRender: React.FC<{ [add] ); - // Map Array of UIWizardSteps into an array of @tacc/core-wrappers/WizardStep + // Map Array of UIWizardSteps into an array of @tacc/core-components/WizardStep const steps: Array> = useMemo(() => { return wizardSteps.map((jobStep) => { const { generateInitialValues, validateThunk, ...stepProps } = jobStep; diff --git a/apps/ui-patterns/src/app/UIPatternsComplexWizard/index.ts b/apps/ui-patterns/src/app/UIPatternsComplexWizard/index.ts index 53e0e5225..00748dfc3 100644 --- a/apps/ui-patterns/src/app/UIPatternsComplexWizard/index.ts +++ b/apps/ui-patterns/src/app/UIPatternsComplexWizard/index.ts @@ -34,7 +34,7 @@ export type InitialValueGenerator = (hookValues: { extra: UIWizardExtra; }) => Partial; -// An adapter type for mapping additional values to @tacc/core-wrappers/Wizard +// An adapter type for mapping additional values to @tacc/core-coponents/Wizard export type UIWizardStep = { id: string; name: string; diff --git a/apps/ui-patterns/src/app/UIPatternsComplexWizard/steps/LastStep.tsx b/apps/ui-patterns/src/app/UIPatternsComplexWizard/steps/LastStep.tsx index e1b380919..e5b9c7424 100644 --- a/apps/ui-patterns/src/app/UIPatternsComplexWizard/steps/LastStep.tsx +++ b/apps/ui-patterns/src/app/UIPatternsComplexWizard/steps/LastStep.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useState, useMemo } from 'react'; import * as Yup from 'yup'; import { UIWizardStep, UIWizardSchema, InitialValueGenerator } from '..'; import { Button } from '@tacc/core-components'; -import { SubmitWrapper } from '@tacc/core-wrappers'; +import { SubmitWrapper } from '@tacc/core-components'; import { validationSchema as stepOneValidationSchema } from './StepOne'; import { validationSchema as stepTwoValidationSchema } from './StepTwo'; import { validationSchema as stepThreeValidationSchema } from './StepThree'; diff --git a/apps/ui-patterns/src/app/UIPatternsComplexWizard/steps/StepOne.tsx b/apps/ui-patterns/src/app/UIPatternsComplexWizard/steps/StepOne.tsx index 22477602f..d5e0e8691 100644 --- a/apps/ui-patterns/src/app/UIPatternsComplexWizard/steps/StepOne.tsx +++ b/apps/ui-patterns/src/app/UIPatternsComplexWizard/steps/StepOne.tsx @@ -1,19 +1,22 @@ -import { FormikInput } from '@tacc/core-wrappers'; +import { FormikInput } from '@tacc/core-components'; import * as Yup from 'yup'; import { UIWizardStep, useWizardValues, InitialValueGenerator } from '..'; +import { Field } from 'formik'; export const StepOne: React.FC = () => { const { extra } = useWizardValues(); return (

Step One: Extra value two is {extra.extraTwo}

- - = ({ note="more values inside" className={fieldArrayStyles.item} > - - = ({ title={`Field Array ${outerIndex}`} className={fieldArrayStyles.item} > - = ({ note="more values inside" className={fieldArrayStyles.item} > - - ({ diff --git a/apps/ui-patterns/src/app/UIPatternsWizard/UIPatternsWizard.tsx b/apps/ui-patterns/src/app/UIPatternsWizard/UIPatternsWizard.tsx index f802807cb..d2e2c21cc 100644 --- a/apps/ui-patterns/src/app/UIPatternsWizard/UIPatternsWizard.tsx +++ b/apps/ui-patterns/src/app/UIPatternsWizard/UIPatternsWizard.tsx @@ -8,7 +8,7 @@ import React, { useCallback } from 'react'; import { UIWizardSchema } from '.'; import { UIWizardProvider, useWizardValues } from '.'; -import { Wizard } from '@tacc/core-wrappers'; +import { Wizard } from '@tacc/core-components'; import wizardSteps from './steps'; const UIPatternsWizardRender: React.FC = () => { diff --git a/apps/ui-patterns/src/app/UIPatternsWizard/steps/LastStep.tsx b/apps/ui-patterns/src/app/UIPatternsWizard/steps/LastStep.tsx index 0f11bd5a9..5f15b1143 100644 --- a/apps/ui-patterns/src/app/UIPatternsWizard/steps/LastStep.tsx +++ b/apps/ui-patterns/src/app/UIPatternsWizard/steps/LastStep.tsx @@ -2,8 +2,8 @@ import React, { useCallback, useState, useMemo } from 'react'; import * as Yup from 'yup'; import { UIWizardSchema, useWizardValues } from '..'; import { Button } from '@tacc/core-components'; -import { SubmitWrapper } from '@tacc/core-wrappers'; -import { WizardStep } from '@tacc/core-wrappers'; +import { SubmitWrapper } from '@tacc/core-components'; +import { WizardStep } from '@tacc/core-components'; import { validationSchema as stepOneValidationSchema } from './StepOne'; import { validationSchema as stepTwoValidationSchema } from './StepTwo'; import { validationSchema as stepThreeValidationSchema } from './StepThree'; diff --git a/apps/ui-patterns/src/app/UIPatternsWizard/steps/StepOne.tsx b/apps/ui-patterns/src/app/UIPatternsWizard/steps/StepOne.tsx index 68f1d7ebf..ea0e8fa5d 100644 --- a/apps/ui-patterns/src/app/UIPatternsWizard/steps/StepOne.tsx +++ b/apps/ui-patterns/src/app/UIPatternsWizard/steps/StepOne.tsx @@ -1,19 +1,22 @@ -import { FormikInput } from '@tacc/core-wrappers'; -import { WizardStep } from '@tacc/core-wrappers'; +import { FormikInput } from '@tacc/core-components'; +import { WizardStep } from '@tacc/core-components'; import * as Yup from 'yup'; import { useWizardValues, UIWizardSchema } from '..'; +import { Field } from 'formik'; export const StepOne: React.FC = () => { return (

Step One

- - { return (

Step Three

- { return (

Step Two

- (); diff --git a/libs/core-components/.gitignore b/libs/core-components/.gitignore new file mode 100644 index 000000000..7e012f6d7 --- /dev/null +++ b/libs/core-components/.gitignore @@ -0,0 +1,4 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +dist diff --git a/libs/core-components/.storybook/main.ts b/libs/core-components/.storybook/main.ts new file mode 100644 index 000000000..6de5be102 --- /dev/null +++ b/libs/core-components/.storybook/main.ts @@ -0,0 +1,20 @@ +import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { + stories: ['../src/lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'], + addons: ['@storybook/addon-essentials'], + framework: { + name: '@storybook/react-vite', + options: { + builder: { + viteConfigPath: 'libs/core-components/vite.config.ts', + }, + }, + }, +}; + +export default config; + +// To customize your Vite configuration you can use the viteFinal field. +// Check https://storybook.js.org/docs/react/builders/vite#configuration +// and https://nx.dev/recipes/storybook/custom-builder-configs diff --git a/libs/core-components/.storybook/preview.global.css b/libs/core-components/.storybook/preview.global.css new file mode 100644 index 000000000..e07fb8df6 --- /dev/null +++ b/libs/core-components/.storybook/preview.global.css @@ -0,0 +1,4 @@ +/* https://tacc-main.atlassian.net/wiki/x/hRlv */ +@import url('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css') layer(foundation); +@import url('@tacc/core-styles/dist/core-styles.base.css') layer(base); +@import url('@tacc/core-styles/dist/core-styles.portal.css') layer(base); diff --git a/libs/core-components/.storybook/preview.ts b/libs/core-components/.storybook/preview.ts new file mode 100644 index 000000000..204ab3b31 --- /dev/null +++ b/libs/core-components/.storybook/preview.ts @@ -0,0 +1 @@ +import './preview.global.css'; diff --git a/libs/core-components/README.md b/libs/core-components/README.md index 07b575dad..3a99c18ac 100644 --- a/libs/core-components/README.md +++ b/libs/core-components/README.md @@ -1,7 +1,146 @@ -# core-components +# TACC Core-Components -This library was generated with [Nx](https://nx.dev). +The shared components for TACC WMA Workspace Portals & Websites -## Running unit tests +## Known Clients + +- [TUP UI], the client code for TACC User Portal +- [Hazmapper], a TACC application for geospatial data + +[tup ui]: https://github.com/TACC/tup-ui +[hazmapper]: https://github.com/TACC-Cloud/hazmapper + +## Table of Contents + +- [Related Repositories](#related-repositories) +- [Project Architecture](#project-architecture) +- [Prerequisites](#prerequisites) +- [Getting Started](#getting-started) +- [Developing](#developing) +- [Contributing](#contributing) +- [Testing](#testing) + +## Related Repositories + +- [Core Styles], the shared UI pattern code for TACC WMA CMS Websites + +## Project Architecture + +| directory | contents | +| --------- | ---------------------------- | +| `src/lib` | components, tests, [stories] | + +## Prerequisites + +- [Node.js] + +## Getting Started + +1. Install with any package manager e.g. + + - `npm install @tacc/core-styles` + - `yarn add @tacc/core-styles` + +2. Import component(s) e.g. + + ```ts + import { Button } from '@tacc/core-components'; + ``` + + ```ts + import { + FormikInput, + FormikTextarea, + FormikCheck, + } from '@tacc/core-components'; + ``` + +3. Use component(s)… + + > **Sorry.** Examples are limited and incomplete: + > + > - [TACC-Cloud/hazmapper#239](https://github.com/TACC-Cloud/hazmapper/pull/239/files) + > - [TACC/tup-ui#465](https://github.com/TACC/tup-ui/pull/465/files) + > - [TACC/tup-ui@ee5e73b:`/.../Button.stories.tsx`](https://github.com/TACC/tup-ui/blob/ee5e73b/libs/core-components/src/lib/Button/Button.stories.tsx#L26-L37) + +## Developing + +The components are [React components](https://react.dev/learn) that should be [written in TypeScript](https://react.dev/learn/typescript#typescript-with-react-components). + +### Setup + +0. [Clone this Repository.](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) +1. Enter the Repository Clone: + + ```sh + cd tup-ui + ``` + +2. Install Dependencies: + + ```sh + npm install --include=optional --workspace=libs/core-components + ``` + +3. Start demo: + + ```sh + npx nx serve core-components + ``` + +For more commands, see [Commands](#commands). + +## Contributing + +### to Components + +#### Minimum Viable Product + +0. Create or Improve a common component in a TACC repository e.g. + + - https://github.com/TACC/tup-ui + - https://github.com/TACC/Core-Portal + - https://github.com/TACC-Cloud/hazmapper + +1. Put your work in a branch in this repository. +2. Open a [Pull Request](https://github.com/TACC/tup-ui/pulls). +3. [Test your work in a client repository.](#end-to-end-tests) + +#### Complete Contribution + +4. [Create a story](https://storybook.js.org/docs/writing-stories) to demo the component. +5. Create [unit tests](#unit-tests). + +### in the Demo + +| task | reference | +| ------------------ | ------------------------------------------------- | +| add/edit component | https://storybook.js.org/docs/writing-stories | +| change interaction | https://storybook.js.org/docs/essentials/controls | + +## Testing + +### Unit Tests Run `nx test core-components` to execute the unit tests via [Vitest](https://vitest.dev/). + +### End-to-End Tests + +Perform manually by installing and testing the components in a separate respository. See [different approaches to testing your own packages](https://dev.to/one-beyond/different-approaches-to-testing-your-own-packages-1kdg). + +## Resources + +### Commands + +| command | task | service | +| ---------------------------------------- | ------------------ | -------------------------------------- | +| `npx nx serve core-components` | start demo | [Storybook](https://storybook.js.org/) | +| `npx nx build core-components` | build components | [Vite](https://vitejs.dev/) | +| `npx nx build-storybook core-components` | build demo | [Storybook](https://storybook.js.org/) | +| `npx nx test core-components` | execute unit tests | [Vitest](https://vitest.dev/) | + + + +[core styles]: https://github.com/TACC/Core-Styles +[node.js]: https://nodejs.org/ +[stories]: https://storybook.js.org/docs/get-started/whats-a-story diff --git a/libs/core-components/package.json b/libs/core-components/package.json new file mode 100644 index 000000000..67b323249 --- /dev/null +++ b/libs/core-components/package.json @@ -0,0 +1,55 @@ +{ + "name": "@tacc/core-components", + "version": "0.0.3-beta.0", + "license": "MIT", + "author": "TACC ACI WMA ", + "contributors": [ + "TACC COA CMD " + ], + "description": "React component library for TACC applications.", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "homepage": "https://github.com/TACC/tup-ui/libs/core-components", + "scripts": { + "build": "vite build --outDir dist" + }, + "dependencies": { + "uuid": "^8 || ^9" + }, + "peerDependencies": { + "formik": "^2.2.9", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-dropzone": "^14.2.3", + "react-resize-detector": "^7.1.2", + "react-router-dom": "^6.11.2", + "react-step-wizard": "^5.3.11", + "react-table": "^7.8.0", + "reactstrap": "^9.1.5" + }, + "devDependencies": { + "@nx/react": "^17.2.8", + "@nx/vite": "^17.2.8", + "@tacc/core-styles": "^2.25.1", + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^14.0.0", + "@testing-library/user-event": "^14.5.2", + "@vitejs/plugin-react-swc": "^3.5.0", + "vite": "^5.0.11", + "vite-plugin-dts": "^2.3.0", + "vite-plugin-lib-inject-css": "^2.1.1", + "vite-tsconfig-paths": "^4.2.0" + }, + "sideEffects": [ + "libs/core-componets/**/*.css" + ], + "optionalDependencies": { + "@nx/storybook": "^17.2.8", + "@storybook/addon-essentials": "^7.6.19", + "@storybook/core-server": "^7.6.19", + "@storybook/react-vite": "^7.6.19" + } +} diff --git a/libs/core-components/project.json b/libs/core-components/project.json index e3c325928..9a3d48a0f 100644 --- a/libs/core-components/project.json +++ b/libs/core-components/project.json @@ -5,6 +5,14 @@ "projectType": "library", "tags": [], "targets": { + "build": { + "executor": "@nx/vite:build", + "outputs": ["{options.outputPath}"], + "defaultConfiguration": "production", + "options": { + "outputPath": "libs/core-components/dist" + } + }, "lint": { "executor": "@nx/eslint:lint", "outputs": ["{options.outputFile}"] @@ -16,6 +24,43 @@ "passWithNoTests": true, "reportsDirectory": "../../coverage/libs/core-components" } + }, + "serve": { + "executor": "@nx/storybook:storybook", + "options": { + "port": 4400, + "configDir": "libs/core-components/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + }, + "storybook": { + "executor": "@nx/storybook:storybook", + "options": { + "port": 4400, + "configDir": "libs/core-components/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } + }, + "build-storybook": { + "executor": "@nx/storybook:build", + "outputs": ["{options.outputDir}"], + "options": { + "outputDir": "dist/storybook/core-components", + "configDir": "libs/core-components/.storybook" + }, + "configurations": { + "ci": { + "quiet": true + } + } } } } diff --git a/libs/core-components/src/index.ts b/libs/core-components/src/index.ts index 10c8cfafe..e396bb4c0 100644 --- a/libs/core-components/src/index.ts +++ b/libs/core-components/src/index.ts @@ -1,3 +1,5 @@ +import { WizardStep as WizardStepType } from './lib/Wizard'; + export { default as Button } from './lib/Button'; export { default as Icon } from './lib/Icon'; export { default as Section } from './lib/Section'; @@ -18,3 +20,19 @@ export { default as HistoryBadge } from './lib/HistoryBadge'; export { default as Collapse } from './lib/Collapse'; export { default as TextCopyField } from './lib/TextCopyField'; export * from './lib/Form'; + +export { Navbar, NavItem, QueryNavItem, AnchorNavItem } from './lib/Navbar'; +export { default as QueryWrapper } from './lib/QueryWrapper'; +export { default as SubmitWrapper } from './lib/SubmitWrapper'; +export { default as Wizard, useWizard, WizardNavigation } from './lib/Wizard'; +export type WizardStep = WizardStepType; +export { + FieldWrapperFormik, + FormikInput, + FormikSelect, + FormikCheck, + FormikTextarea, + FormikFileInput, +} from './lib/FieldWrapperFormik'; + +export { default as withBuilder } from './utils/withBuilder'; diff --git a/libs/core-components/src/lib/Button/Button.stories.module.css b/libs/core-components/src/lib/Button/Button.stories.module.css new file mode 100644 index 000000000..e5e1d8654 --- /dev/null +++ b/libs/core-components/src/lib/Button/Button.stories.module.css @@ -0,0 +1,3 @@ +.button + .button { + margin-left: 1em; +} diff --git a/libs/core-components/src/lib/Button/Button.stories.tsx b/libs/core-components/src/lib/Button/Button.stories.tsx new file mode 100644 index 000000000..57d6a08cd --- /dev/null +++ b/libs/core-components/src/lib/Button/Button.stories.tsx @@ -0,0 +1,44 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import Button, { SIZE_MAP } from './Button'; + +import styles from './Button.stories.module.css'; + +const meta: Meta = { + component: Button, + argTypes: { + size: { + options: Object.keys(SIZE_MAP), + control: { type: 'inline-radio' }, + }, + }, +}; +export default meta; + +type Story = StoryObj; + +export const Types: Story = { + render: (args) => { + const { size, ...argsSansSize } = args; + + return ( + <> + + + + + + ); + }, + args: { + className: styles['button'] + ' ', + }, +}; diff --git a/libs/core-wrappers/src/lib/FieldWrapperFormik/FieldWrapperFormik.global.css b/libs/core-components/src/lib/FieldWrapperFormik/FieldWrapperFormik.global.css similarity index 100% rename from libs/core-wrappers/src/lib/FieldWrapperFormik/FieldWrapperFormik.global.css rename to libs/core-components/src/lib/FieldWrapperFormik/FieldWrapperFormik.global.css diff --git a/libs/core-wrappers/src/lib/FieldWrapperFormik/FieldWrapperFormik.tsx b/libs/core-components/src/lib/FieldWrapperFormik/FieldWrapperFormik.tsx similarity index 63% rename from libs/core-wrappers/src/lib/FieldWrapperFormik/FieldWrapperFormik.tsx rename to libs/core-components/src/lib/FieldWrapperFormik/FieldWrapperFormik.tsx index 96a2dc6a9..a5c8ae4c5 100644 --- a/libs/core-wrappers/src/lib/FieldWrapperFormik/FieldWrapperFormik.tsx +++ b/libs/core-components/src/lib/FieldWrapperFormik/FieldWrapperFormik.tsx @@ -1,42 +1,42 @@ import React from 'react'; -import { ErrorMessage } from 'formik'; +import { FieldProps } from 'formik'; import { Badge } from 'reactstrap'; import './FieldWrapperFormik.global.css'; export type FieldWrapperProps = { - name: string; + id?: string; label: React.ReactNode; required?: boolean; className?: string; description?: React.ReactNode; + formik: FieldProps; }; + const FieldWrapper: React.FC> = ({ - name, + id, label, required, description, className, children, + formik: { field, form }, }) => { return (
-
); diff --git a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikCheck.module.css b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikCheck.module.css similarity index 100% rename from libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikCheck.module.css rename to libs/core-components/src/lib/FieldWrapperFormik/fields/FormikCheck.module.css diff --git a/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikCheck.tsx b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikCheck.tsx new file mode 100644 index 000000000..72788a730 --- /dev/null +++ b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikCheck.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import FieldWrapper from '../FieldWrapperFormik'; +import { FormikInputProps } from '.'; + +const FormikCheck: React.FC = ({ + id, + name, + label, + required, + description, + field, + form, + meta, + ...props +}: FormikInputProps) => { + return ( + + + + ); +}; + +export default FormikCheck; diff --git a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.module.css b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.module.css similarity index 100% rename from libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.module.css rename to libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.module.css diff --git a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.spec.tsx b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.test.tsx similarity index 86% rename from libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.spec.tsx rename to libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.test.tsx index 8ac0f7dbf..d187df31e 100644 --- a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.spec.tsx +++ b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.test.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react'; -import { testRender } from '@tacc/tup-testing'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; import FileDropzone from './FileDropzone'; import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -28,7 +29,7 @@ describe('dropzone', () => { const smallFile = new File(['file'], 'myfile.json', { type: 'application/json', }); - testRender(); + render(); const input = screen.getByTestId('dropzone-input'); await userEvent.upload(input, smallFile); expect(screen.getByText('myfile.json')).toBeDefined(); @@ -37,7 +38,7 @@ describe('dropzone', () => { it('Shows error when file is too big.', async () => { const bigFile = new File(['hi'], 'myfile', { type: 'image/jpeg' }); - testRender(); + render(); const input = screen.getByTestId('dropzone-input'); await userEvent.upload(input, bigFile); expect(screen.getByText(/Exceeds File Size Limit/)).toBeDefined(); diff --git a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.tsx b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.tsx similarity index 95% rename from libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.tsx rename to libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.tsx index 27f8a704c..7ee0ea8c1 100644 --- a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.tsx +++ b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FileDropzone.tsx @@ -1,10 +1,11 @@ /* FP-993: Allow use by DataFilesUploadModal */ import React, { useCallback, useState } from 'react'; import { useDropzone, FileRejection } from 'react-dropzone'; -import { InlineMessage, Button } from '@tacc/core-components'; +import { InlineMessage, Button } from '../../../..'; import styles from './FileDropzone.module.css'; interface FileInputDropzoneProps { + id: string; files: File[]; onDrop: (files: File[]) => void; onRemoveFile: (index: number) => void; @@ -18,6 +19,7 @@ interface FileInputDropzoneProps { * and user can manage (e.g. delete those files) directly in this component. */ const FileInputDropZone: React.FC = ({ + id, files, onDrop, maxSize, @@ -60,7 +62,7 @@ const FileInputDropZone: React.FC = ({ return ( // eslint-disable-next-line react/jsx-props-no-spreading
- + {!showFileList && (
diff --git a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FormikFileInput.tsx b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FormikFileInput.tsx similarity index 80% rename from libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FormikFileInput.tsx rename to libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FormikFileInput.tsx index e44a5e506..14754e93c 100644 --- a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikFileInput/FormikFileInput.tsx +++ b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikFileInput/FormikFileInput.tsx @@ -1,10 +1,11 @@ /* FP-993: Allow use by DataFilesUploadModal */ import React from 'react'; -import { useField } from 'formik'; +import { useField, FieldProps } from 'formik'; import FileInputDropZone from './FileDropzone'; import FieldWrapper from '../../FieldWrapperFormik'; -interface FormikFileInputProps { +interface FormikFileInputProps extends FieldProps { + id: string; name: string; label: string; required: boolean; @@ -14,14 +15,18 @@ interface FormikFileInputProps { } const FileInputDropZoneFormField: React.FC = ({ + id, name, label, description, maxSizeMessage, maxSize, required, + field, + form, + meta, }) => { - const [field, , helpers] = useField(name); + const [, , helpers] = useField(name); const onSetFiles = (acceptedFiles: File[]) => { const newAcceptedFiles = acceptedFiles.filter( @@ -35,12 +40,14 @@ const FileInputDropZoneFormField: React.FC = ({ }; return ( = ({ + id, name, label, required, description, + field, + form, + meta, ...props }: FormikInputProps) => { - const [field] = useField(name); return ( - + ); }; diff --git a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikSelect.tsx b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikSelect.tsx similarity index 75% rename from libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikSelect.tsx rename to libs/core-components/src/lib/FieldWrapperFormik/fields/FormikSelect.tsx index 30ac325f2..a80cea141 100644 --- a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikSelect.tsx +++ b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikSelect.tsx @@ -1,25 +1,28 @@ import React from 'react'; import FieldWrapper from '../FieldWrapperFormik'; -import { useField } from 'formik'; import { FormikSelectProps } from '.'; const FormikTextarea: React.FC = ({ + id, name, label, required, description, children, + field, + form, + meta, ...props }: FormikSelectProps) => { - const [field] = useField(name); return ( - {children} diff --git a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikTextarea.tsx b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikTextarea.tsx similarity index 73% rename from libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikTextarea.tsx rename to libs/core-components/src/lib/FieldWrapperFormik/fields/FormikTextarea.tsx index 0e1a5972c..bef566585 100644 --- a/libs/core-wrappers/src/lib/FieldWrapperFormik/fields/FormikTextarea.tsx +++ b/libs/core-components/src/lib/FieldWrapperFormik/fields/FormikTextarea.tsx @@ -1,24 +1,27 @@ import React from 'react'; import FieldWrapper from '../FieldWrapperFormik'; -import { useField } from 'formik'; import { FormikTextareaProps } from '.'; const FormikTextarea: React.FC = ({ + id, name, label, required, description, + field, + form, + meta, ...props }: FormikTextareaProps) => { - const [field] = useField(name); return ( -