From b82b940be20d9175243791cdc53e15e520b69da5 Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Mon, 20 Dec 2021 06:00:55 +0800 Subject: [PATCH] Add formatted category, fix option types The formatted category accepts input of pre-defined formats (email, url, telephone number). The option types for components have been fixed because of `uncheckedLabel` prop not present before, which was introduced for ToggleSwitch. --- docs/todo.md | 32 ++- .../EmailAddressInput.test.tsx | 210 ++++++++++++++++++ .../components/EmailAddressInput/index.tsx | 124 +++++++++++ .../PhoneNumberInput.test.tsx | 210 ++++++++++++++++++ .../components/PhoneNumberInput/index.tsx | 124 +++++++++++ .../components/UrlInput/UrlInput.test.tsx | 210 ++++++++++++++++++ .../formatted/components/UrlInput/index.tsx | 124 +++++++++++ src/modules/formatted/index.ts | 3 + .../formatted/web-freeform-react.test.ts | 11 + .../option/components/RadioButton/index.tsx | 1 + .../option/components/RadioTickBox/index.tsx | 1 + .../option/components/ToggleButton/index.tsx | 1 + .../option/components/ToggleTickBox/index.tsx | 1 + tsconfig.json | 5 +- 14 files changed, 1052 insertions(+), 5 deletions(-) create mode 100644 src/modules/formatted/components/EmailAddressInput/EmailAddressInput.test.tsx create mode 100644 src/modules/formatted/components/EmailAddressInput/index.tsx create mode 100644 src/modules/formatted/components/PhoneNumberInput/PhoneNumberInput.test.tsx create mode 100644 src/modules/formatted/components/PhoneNumberInput/index.tsx create mode 100644 src/modules/formatted/components/UrlInput/UrlInput.test.tsx create mode 100644 src/modules/formatted/components/UrlInput/index.tsx create mode 100644 src/modules/formatted/index.ts create mode 100644 src/modules/formatted/web-freeform-react.test.ts diff --git a/docs/todo.md b/docs/todo.md index 27c74d2..99cd57b 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -2,12 +2,22 @@ - [X] `ActionButton` +# Code + +- [ ] `CodeBlock` +- [ ] `CodeInput` +- [ ] `VerificationCodeInput` + # Color - [ ] `ColorSlider` - [ ] `Palette` - [ ] `Swatch` +# DataGrid + +- [ ] `DataGridView` + # File - [ ] `FileArea` @@ -15,10 +25,10 @@ # Formatted +- [X] `EmailInput` - [ ] `SuggestionInput` -- [ ] `EmailInput` -- [ ] `TelInput` -- [ ] `UrlInput` +- [X] `TelInput` +- [X] `UrlInput` # Freeform @@ -34,6 +44,10 @@ - [X] `Badge` +# MIDI + +- [ ] `MusicalKeyboard` + # Navigation - [ ] `Breadcrumb` @@ -59,6 +73,14 @@ - [X] `ToggleSwitch` - [X] `ToggleTickBox` +# Rating + +- [ ] `Rating` + +# RichText + +- [ ] `WysiwygTextInput` + # Temporal - [ ] `Calendar` @@ -68,3 +90,7 @@ - [ ] `MonthDaySpinner` - [ ] `TimeSpinner` - [ ] `YearMonthSpinner` + +# Tree + +- [ ] `TreeView` diff --git a/src/modules/formatted/components/EmailAddressInput/EmailAddressInput.test.tsx b/src/modules/formatted/components/EmailAddressInput/EmailAddressInput.test.tsx new file mode 100644 index 0000000..d5374ac --- /dev/null +++ b/src/modules/formatted/components/EmailAddressInput/EmailAddressInput.test.tsx @@ -0,0 +1,210 @@ +import * as React from 'react'; +import { + render, + screen +} from '@testing-library/react'; +import '@testing-library/jest-dom'; +import userEvent from '@testing-library/user-event'; +import * as TextControlBase from '@tesseract-design/web-base-textcontrol'; +import { + EmailAddressInput, +} from '.'; + +jest.mock('@tesseract-design/web-base-textcontrol'); + +describe('EmailAddressInput', () => { + it('should render a textbox', () => { + render( + + ); + const textbox = screen.getByRole('textbox'); + expect(textbox).toBeInTheDocument(); + expect(textbox).toHaveProperty('type', 'email'); + }); + + it('should render a border', () => { + render( + + ); + const border = screen.getByTestId('border'); + expect(border).toBeInTheDocument(); + }); + + it('should render a label', () => { + render( + + ); + const textbox = screen.getByLabelText('foo'); + expect(textbox).toBeInTheDocument(); + const label = screen.getByTestId('label'); + expect(label).toHaveTextContent('foo'); + }); + + it('should render a hidden label', () => { + render( + + ); + const textbox = screen.getByLabelText('foo'); + expect(textbox).toBeInTheDocument(); + const label = screen.queryByTestId('label'); + expect(label).toBeNull(); + }); + + it('should render a hint', () => { + render( + + ); + const hint = screen.getByTestId('hint'); + expect(hint).toBeInTheDocument(); + }); + + it('should render an indicator', () => { + render( + + } + /> + ); + const indicator = screen.getByTestId('indicator'); + expect(indicator).toBeInTheDocument(); + }); + + describe.each([ + TextControlBase.TextControlSize.SMALL, + TextControlBase.TextControlSize.MEDIUM, + TextControlBase.TextControlSize.LARGE, + ])('on %s size', (size) => { + it('should render input styles', () => { + render( + + ); + + expect(TextControlBase.Input).toBeCalledWith(expect.objectContaining({ + size, + })); + }); + + it('should render hint styles', () => { + render( + + ); + + expect(TextControlBase.HintWrapper).toBeCalledWith(expect.objectContaining({ + size, + })); + }); + + it('should render indicator styles', () => { + render( + + } + /> + ); + + expect(TextControlBase.IndicatorWrapper).toBeCalledWith(expect.objectContaining({ + size, + })); + }); + }); + + it('should render a block textbox', () => { + render( + + ); + + expect(TextControlBase.Root).toBeCalledWith(expect.objectContaining({ + block: true, + })); + }); + + describe.each([ + TextControlBase.TextControlStyle.DEFAULT, + TextControlBase.TextControlStyle.ALTERNATE, + ])('on %s style', (style) => { + it('should render input styles', () => { + render( + + ); + + expect(TextControlBase.Input).toBeCalledWith(expect.objectContaining({ + style, + })); + }); + + it('should render hint styles', () => { + render( + + ); + + expect(TextControlBase.HintWrapper).toBeCalledWith(expect.objectContaining({ + style, + })); + }); + + it('should render indicator styles', () => { + render( + + } + /> + ); + + expect(TextControlBase.IndicatorWrapper).toBeCalledWith(expect.objectContaining({ + style, + })); + }); + }); + + it('should handle change events', () => { + const onChange = jest.fn(); + render( + + ); + const textbox: HTMLInputElement = screen.getByRole('textbox'); + userEvent.type(textbox, 'foobar'); + expect(onChange).toBeCalled(); + }); + + it('should handle input events', () => { + const onInput = jest.fn(); + render( + + ); + const textbox: HTMLInputElement = screen.getByTestId('input'); + userEvent.type(textbox, 'foobar'); + expect(onInput).toBeCalled(); + }); +}); diff --git a/src/modules/formatted/components/EmailAddressInput/index.tsx b/src/modules/formatted/components/EmailAddressInput/index.tsx new file mode 100644 index 0000000..9c01387 --- /dev/null +++ b/src/modules/formatted/components/EmailAddressInput/index.tsx @@ -0,0 +1,124 @@ +import * as React from 'react'; +import * as TextControlBase from '@tesseract-design/web-base-textcontrol'; + +export type EmailAddressInputProps = Omit, 'size' | 'style'> & { + /** + * Short textual description indicating the nature of the component's value. + */ + label?: React.ReactNode, + /** + * Short textual description as guidelines for valid input values. + */ + hint?: React.ReactNode, + /** + * Size of the component. + */ + size?: TextControlBase.TextControlSize, + /** + * Additional description, usually graphical, indicating the nature of the component's value. + */ + indicator?: React.ReactNode, + /** + * Should the component display a border? + */ + border?: boolean, + /** + * Should the component occupy the whole width of its parent? + */ + block?: boolean, + /** + * Style of the component. + */ + style?: TextControlBase.TextControlStyle, + /** + * Is the label hidden? + */ + hiddenLabel?: boolean, +} + +/** + * Component for inputting email address values. + */ +export const EmailAddressInput = React.forwardRef( + ( + { + label = '', + hint = '', + indicator = null, + size = TextControlBase.TextControlSize.MEDIUM, + border = false, + block = false, + style = TextControlBase.TextControlStyle.DEFAULT, + hiddenLabel = false, + type: _type, + className: _className, + placeholder: _placeholder, + as: _as, + ...etcProps + }: EmailAddressInputProps, + ref, + ) => { + const styleArgs = React.useMemo(() => ({ + block, + border, + size, + indicator: Boolean(indicator), + style, + resizable: false, + predefinedValues: false, + }), [block, border, size, indicator, style]); + + return ( +
+ + { + border && ( + + ) + } + { + label && !hiddenLabel && ( +
+ {label} +
+ ) + } + {hint && ( +
+
+ {hint} +
+
+ )} + {indicator && ( +
+ {indicator} +
+ )} +
+ ); + } +); + +EmailAddressInput.displayName = 'EmailAddressInput'; diff --git a/src/modules/formatted/components/PhoneNumberInput/PhoneNumberInput.test.tsx b/src/modules/formatted/components/PhoneNumberInput/PhoneNumberInput.test.tsx new file mode 100644 index 0000000..48debff --- /dev/null +++ b/src/modules/formatted/components/PhoneNumberInput/PhoneNumberInput.test.tsx @@ -0,0 +1,210 @@ +import * as React from 'react'; +import { + render, + screen +} from '@testing-library/react'; +import '@testing-library/jest-dom'; +import userEvent from '@testing-library/user-event'; +import * as TextControlBase from '@tesseract-design/web-base-textcontrol'; +import { + PhoneNumberInput, +} from '.'; + +jest.mock('@tesseract-design/web-base-textcontrol'); + +describe('PhoneNumberInput', () => { + it('should render a textbox', () => { + render( + + ); + const textbox = screen.getByRole('textbox'); + expect(textbox).toBeInTheDocument(); + expect(textbox).toHaveProperty('type', 'tel'); + }); + + it('should render a border', () => { + render( + + ); + const border = screen.getByTestId('border'); + expect(border).toBeInTheDocument(); + }); + + it('should render a label', () => { + render( + + ); + const textbox = screen.getByLabelText('foo'); + expect(textbox).toBeInTheDocument(); + const label = screen.getByTestId('label'); + expect(label).toHaveTextContent('foo'); + }); + + it('should render a hidden label', () => { + render( + + ); + const textbox = screen.getByLabelText('foo'); + expect(textbox).toBeInTheDocument(); + const label = screen.queryByTestId('label'); + expect(label).toBeNull(); + }); + + it('should render a hint', () => { + render( + + ); + const hint = screen.getByTestId('hint'); + expect(hint).toBeInTheDocument(); + }); + + it('should render an indicator', () => { + render( + + } + /> + ); + const indicator = screen.getByTestId('indicator'); + expect(indicator).toBeInTheDocument(); + }); + + describe.each([ + TextControlBase.TextControlSize.SMALL, + TextControlBase.TextControlSize.MEDIUM, + TextControlBase.TextControlSize.LARGE, + ])('on %s size', (size) => { + it('should render input styles', () => { + render( + + ); + + expect(TextControlBase.Input).toBeCalledWith(expect.objectContaining({ + size, + })); + }); + + it('should render hint styles', () => { + render( + + ); + + expect(TextControlBase.HintWrapper).toBeCalledWith(expect.objectContaining({ + size, + })); + }); + + it('should render indicator styles', () => { + render( + + } + /> + ); + + expect(TextControlBase.IndicatorWrapper).toBeCalledWith(expect.objectContaining({ + size, + })); + }); + }); + + it('should render a block textbox', () => { + render( + + ); + + expect(TextControlBase.Root).toBeCalledWith(expect.objectContaining({ + block: true, + })); + }); + + describe.each([ + TextControlBase.TextControlStyle.DEFAULT, + TextControlBase.TextControlStyle.ALTERNATE, + ])('on %s style', (style) => { + it('should render input styles', () => { + render( + + ); + + expect(TextControlBase.Input).toBeCalledWith(expect.objectContaining({ + style, + })); + }); + + it('should render hint styles', () => { + render( + + ); + + expect(TextControlBase.HintWrapper).toBeCalledWith(expect.objectContaining({ + style, + })); + }); + + it('should render indicator styles', () => { + render( + + } + /> + ); + + expect(TextControlBase.IndicatorWrapper).toBeCalledWith(expect.objectContaining({ + style, + })); + }); + }); + + it('should handle change events', () => { + const onChange = jest.fn(); + render( + + ); + const textbox: HTMLInputElement = screen.getByRole('textbox'); + userEvent.type(textbox, 'foobar'); + expect(onChange).toBeCalled(); + }); + + it('should handle input events', () => { + const onInput = jest.fn(); + render( + + ); + const textbox: HTMLInputElement = screen.getByTestId('input'); + userEvent.type(textbox, 'foobar'); + expect(onInput).toBeCalled(); + }); +}); diff --git a/src/modules/formatted/components/PhoneNumberInput/index.tsx b/src/modules/formatted/components/PhoneNumberInput/index.tsx new file mode 100644 index 0000000..89858f6 --- /dev/null +++ b/src/modules/formatted/components/PhoneNumberInput/index.tsx @@ -0,0 +1,124 @@ +import * as React from 'react'; +import * as TextControlBase from '@tesseract-design/web-base-textcontrol'; + +export type PhoneNumberInputProps = Omit, 'size' | 'style'> & { + /** + * Short textual description indicating the nature of the component's value. + */ + label?: React.ReactNode, + /** + * Short textual description as guidelines for valid input values. + */ + hint?: React.ReactNode, + /** + * Size of the component. + */ + size?: TextControlBase.TextControlSize, + /** + * Additional description, usually graphical, indicating the nature of the component's value. + */ + indicator?: React.ReactNode, + /** + * Should the component display a border? + */ + border?: boolean, + /** + * Should the component occupy the whole width of its parent? + */ + block?: boolean, + /** + * Style of the component. + */ + style?: TextControlBase.TextControlStyle, + /** + * Is the label hidden? + */ + hiddenLabel?: boolean, +} + +/** + * Component for inputting phone number values. + */ +export const PhoneNumberInput = React.forwardRef( + ( + { + label = '', + hint = '', + indicator = null, + size = TextControlBase.TextControlSize.MEDIUM, + border = false, + block = false, + style = TextControlBase.TextControlStyle.DEFAULT, + hiddenLabel = false, + type: _type, + className: _className, + placeholder: _placeholder, + as: _as, + ...etcProps + }: PhoneNumberInputProps, + ref, + ) => { + const styleArgs = React.useMemo(() => ({ + block, + border, + size, + indicator: Boolean(indicator), + style, + resizable: false, + predefinedValues: false, + }), [block, border, size, indicator, style]); + + return ( +
+ + { + border && ( + + ) + } + { + label && !hiddenLabel && ( +
+ {label} +
+ ) + } + {hint && ( +
+
+ {hint} +
+
+ )} + {indicator && ( +
+ {indicator} +
+ )} +
+ ); + } +); + +PhoneNumberInput.displayName = 'PhoneNumberInput'; diff --git a/src/modules/formatted/components/UrlInput/UrlInput.test.tsx b/src/modules/formatted/components/UrlInput/UrlInput.test.tsx new file mode 100644 index 0000000..6344418 --- /dev/null +++ b/src/modules/formatted/components/UrlInput/UrlInput.test.tsx @@ -0,0 +1,210 @@ +import * as React from 'react'; +import { + render, + screen +} from '@testing-library/react'; +import '@testing-library/jest-dom'; +import userEvent from '@testing-library/user-event'; +import * as TextControlBase from '@tesseract-design/web-base-textcontrol'; +import { + UrlInput, +} from '.'; + +jest.mock('@tesseract-design/web-base-textcontrol'); + +describe('UrlInput', () => { + it('should render a textbox', () => { + render( + + ); + const textbox = screen.getByRole('textbox'); + expect(textbox).toBeInTheDocument(); + expect(textbox).toHaveProperty('type', 'url'); + }); + + it('should render a border', () => { + render( + + ); + const border = screen.getByTestId('border'); + expect(border).toBeInTheDocument(); + }); + + it('should render a label', () => { + render( + + ); + const textbox = screen.getByLabelText('foo'); + expect(textbox).toBeInTheDocument(); + const label = screen.getByTestId('label'); + expect(label).toHaveTextContent('foo'); + }); + + it('should render a hidden label', () => { + render( + + ); + const textbox = screen.getByLabelText('foo'); + expect(textbox).toBeInTheDocument(); + const label = screen.queryByTestId('label'); + expect(label).toBeNull(); + }); + + it('should render a hint', () => { + render( + + ); + const hint = screen.getByTestId('hint'); + expect(hint).toBeInTheDocument(); + }); + + it('should render an indicator', () => { + render( + + } + /> + ); + const indicator = screen.getByTestId('indicator'); + expect(indicator).toBeInTheDocument(); + }); + + describe.each([ + TextControlBase.TextControlSize.SMALL, + TextControlBase.TextControlSize.MEDIUM, + TextControlBase.TextControlSize.LARGE, + ])('on %s size', (size) => { + it('should render input styles', () => { + render( + + ); + + expect(TextControlBase.Input).toBeCalledWith(expect.objectContaining({ + size, + })); + }); + + it('should render hint styles', () => { + render( + + ); + + expect(TextControlBase.HintWrapper).toBeCalledWith(expect.objectContaining({ + size, + })); + }); + + it('should render indicator styles', () => { + render( + + } + /> + ); + + expect(TextControlBase.IndicatorWrapper).toBeCalledWith(expect.objectContaining({ + size, + })); + }); + }); + + it('should render a block textbox', () => { + render( + + ); + + expect(TextControlBase.Root).toBeCalledWith(expect.objectContaining({ + block: true, + })); + }); + + describe.each([ + TextControlBase.TextControlStyle.DEFAULT, + TextControlBase.TextControlStyle.ALTERNATE, + ])('on %s style', (style) => { + it('should render input styles', () => { + render( + + ); + + expect(TextControlBase.Input).toBeCalledWith(expect.objectContaining({ + style, + })); + }); + + it('should render hint styles', () => { + render( + + ); + + expect(TextControlBase.HintWrapper).toBeCalledWith(expect.objectContaining({ + style, + })); + }); + + it('should render indicator styles', () => { + render( + + } + /> + ); + + expect(TextControlBase.IndicatorWrapper).toBeCalledWith(expect.objectContaining({ + style, + })); + }); + }); + + it('should handle change events', () => { + const onChange = jest.fn(); + render( + + ); + const textbox: HTMLInputElement = screen.getByRole('textbox'); + userEvent.type(textbox, 'foobar'); + expect(onChange).toBeCalled(); + }); + + it('should handle input events', () => { + const onInput = jest.fn(); + render( + + ); + const textbox: HTMLInputElement = screen.getByTestId('input'); + userEvent.type(textbox, 'foobar'); + expect(onInput).toBeCalled(); + }); +}); diff --git a/src/modules/formatted/components/UrlInput/index.tsx b/src/modules/formatted/components/UrlInput/index.tsx new file mode 100644 index 0000000..c416819 --- /dev/null +++ b/src/modules/formatted/components/UrlInput/index.tsx @@ -0,0 +1,124 @@ +import * as React from 'react'; +import * as TextControlBase from '@tesseract-design/web-base-textcontrol'; + +export type UrlInputProps = Omit, 'size' | 'style'> & { + /** + * Short textual description indicating the nature of the component's value. + */ + label?: React.ReactNode, + /** + * Short textual description as guidelines for valid input values. + */ + hint?: React.ReactNode, + /** + * Size of the component. + */ + size?: TextControlBase.TextControlSize, + /** + * Additional description, usually graphical, indicating the nature of the component's value. + */ + indicator?: React.ReactNode, + /** + * Should the component display a border? + */ + border?: boolean, + /** + * Should the component occupy the whole width of its parent? + */ + block?: boolean, + /** + * Style of the component. + */ + style?: TextControlBase.TextControlStyle, + /** + * Is the label hidden? + */ + hiddenLabel?: boolean, +} + +/** + * Component for inputting URL values. + */ +export const UrlInput = React.forwardRef( + ( + { + label = '', + hint = '', + indicator = null, + size = TextControlBase.TextControlSize.MEDIUM, + border = false, + block = false, + style = TextControlBase.TextControlStyle.DEFAULT, + hiddenLabel = false, + type: _type, + className: _className, + placeholder: _placeholder, + as: _as, + ...etcProps + }: UrlInputProps, + ref, + ) => { + const styleArgs = React.useMemo(() => ({ + block, + border, + size, + indicator: Boolean(indicator), + style, + resizable: false, + predefinedValues: false, + }), [block, border, size, indicator, style]); + + return ( +
+ + { + border && ( + + ) + } + { + label && !hiddenLabel && ( +
+ {label} +
+ ) + } + {hint && ( +
+
+ {hint} +
+
+ )} + {indicator && ( +
+ {indicator} +
+ )} +
+ ); + } +); + +UrlInput.displayName = 'UrlInput'; diff --git a/src/modules/formatted/index.ts b/src/modules/formatted/index.ts new file mode 100644 index 0000000..f4a2222 --- /dev/null +++ b/src/modules/formatted/index.ts @@ -0,0 +1,3 @@ +export * from './components/EmailAddressInput'; +export * from './components/PhoneNumberInput'; +export * from './components/UrlInput'; diff --git a/src/modules/formatted/web-freeform-react.test.ts b/src/modules/formatted/web-freeform-react.test.ts new file mode 100644 index 0000000..90366d5 --- /dev/null +++ b/src/modules/formatted/web-freeform-react.test.ts @@ -0,0 +1,11 @@ +import * as WebFormattedReact from '.'; + +describe('web-formatted-react', () => { + it.each([ + 'EmailAddressInput', + 'PhoneNumberInput', + 'UrlInput', + ])('should export %s', (namedExport) => { + expect(WebFormattedReact).toHaveProperty(namedExport); + }); +}); diff --git a/src/modules/option/components/RadioButton/index.tsx b/src/modules/option/components/RadioButton/index.tsx index 534d11d..0eca1f9 100644 --- a/src/modules/option/components/RadioButton/index.tsx +++ b/src/modules/option/components/RadioButton/index.tsx @@ -66,6 +66,7 @@ export const RadioButton = React.forwardRef( disabled, appearance: CheckControlBase.CheckControlAppearance.BUTTON, type: 'radio', + uncheckedLabel: false, }), [size, block, variant, border, compact, disabled]); return ( diff --git a/src/modules/option/components/RadioTickBox/index.tsx b/src/modules/option/components/RadioTickBox/index.tsx index 483a0bf..e03f1e5 100644 --- a/src/modules/option/components/RadioTickBox/index.tsx +++ b/src/modules/option/components/RadioTickBox/index.tsx @@ -39,6 +39,7 @@ export const RadioTickBox = React.forwardRef(null); const theRef = (ref ?? defaultRef) as React.MutableRefObject; diff --git a/src/modules/option/components/ToggleTickBox/index.tsx b/src/modules/option/components/ToggleTickBox/index.tsx index a799dc1..c9c1c4c 100644 --- a/src/modules/option/components/ToggleTickBox/index.tsx +++ b/src/modules/option/components/ToggleTickBox/index.tsx @@ -44,6 +44,7 @@ export const ToggleTickBox = React.forwardRef(null); const theRef = (ref ?? defaultRef) as React.MutableRefObject; diff --git a/tsconfig.json b/tsconfig.json index f08b6ef..4603a9c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,9 @@ "jsx": "preserve", "baseUrl": ".", "paths": { + "@tesseract-design/css-utils": ["./src/modules/css-utils"], "@tesseract-design/web-action-react": ["./src/modules/action"], + "@tesseract-design/web-formatted-react": ["./src/modules/formatted"], "@tesseract-design/web-freeform-react": ["./src/modules/freeform"], "@tesseract-design/web-information-react": ["./src/modules/information"], "@tesseract-design/web-navigation-react": ["./src/modules/navigation"], @@ -24,8 +26,7 @@ "@tesseract-design/web-base-button": ["./src/modules/base-button"], "@tesseract-design/web-base-checkcontrol": ["./src/modules/base-checkcontrol"], "@tesseract-design/web-base-selectcontrol": ["./src/modules/base-selectcontrol"], - "@tesseract-design/web-base-textcontrol": ["./src/modules/base-textcontrol"], - "@tesseract-design/css-utils": ["./src/modules/css-utils"] + "@tesseract-design/web-base-textcontrol": ["./src/modules/base-textcontrol"] } }, "include": [