@@ -12,7 +12,7 @@ | |||
- [X] RadioTickBox | |||
- Color | |||
- [ ] ColorPicker | |||
- [X] Swatch | |||
- [X] Swatch (unify with color picker? Swatch is basically a readonly color picker with click-to-copy behavior) | |||
- Code | |||
- [ ] CodeInput (extract to own package) | |||
- [X] CodeBlock (`react-refractor`) | |||
@@ -24,7 +24,7 @@ | |||
- Freeform | |||
- [X] MaskedTextInput | |||
- [X] MultilineTextInput | |||
- [X] TextInput | |||
- [X] TextInput (add click-to-copy prop) | |||
- Geo | |||
- [ ] Map | |||
- Information | |||
@@ -66,4 +66,9 @@ | |||
# Others | |||
- [X] Add `select-none` to input labels, etc. | |||
- [ ] Add indicators to components (select, datetime input etc) | |||
- [ ] Test all components! | |||
- [ ] Where to put the "click-to-copy" textboxes? Does `Swatch` | |||
belong to this category? | |||
- [ ] Add `aria-*` attributes to all components | |||
- [ ] react-refractor, fix rendering on Lynx! |
@@ -28,7 +28,6 @@ | |||
"react-dom": "^18.2.0", | |||
"react-test-renderer": "^18.2.0", | |||
"tslib": "^2.5.0", | |||
"tsx": "^3.12.7", | |||
"typescript": "^4.9.5", | |||
"vitest": "^0.33.0" | |||
}, | |||
@@ -38,7 +37,7 @@ | |||
}, | |||
"scripts": { | |||
"prepublishOnly": "pridepack clean && pridepack build", | |||
"build": "pridepack build && tsx scripts/build.ts", | |||
"build": "pridepack build", | |||
"type-check": "pridepack check", | |||
"lint": "pridepack lint", | |||
"clean": "pridepack clean", | |||
@@ -63,7 +62,8 @@ | |||
}, | |||
"dependencies": { | |||
"@tesseract-design/web-base": "workspace:*", | |||
"clsx": "^1.2.1" | |||
"clsx": "^1.2.1", | |||
"tailwindcss": "3.3.2" | |||
}, | |||
"types": "./dist/types/index.d.ts", | |||
"main": "./dist/cjs/production/index.js", | |||
@@ -77,13 +77,9 @@ | |||
"require": "./dist/cjs/production/index.js", | |||
"import": "./dist/esm/production/index.js", | |||
"types": "./dist/types/index.d.ts" | |||
}, | |||
"./dist/DropdownSelect.css": "./dist/DropdownSelect.css", | |||
"./dist/MenuSelect.css": "./dist/MenuSelect.css", | |||
"./dist/RadioButton.css": "./dist/RadioButton.css", | |||
"./dist/RadioTickBox.css": "./dist/RadioTickBox.css" | |||
} | |||
}, | |||
"typesVersions": { | |||
"*": {} | |||
} | |||
} | |||
} |
@@ -1,22 +0,0 @@ | |||
import { copyFileSync, readFileSync, writeFileSync } from 'fs'; | |||
import { resolve } from 'path'; | |||
const doCopy = (src: string, dest: string) => { | |||
const trueSrc = resolve(src); | |||
const trueDest = resolve(dest); | |||
console.log('Copying...'); | |||
console.log(`${trueSrc} -> ${trueDest}`); | |||
copyFileSync(trueSrc, trueDest); | |||
const packageJsonContents = readFileSync('./package.json', 'utf-8'); | |||
const packageJson = JSON.parse(packageJsonContents); | |||
packageJson.exports[dest] = dest; | |||
const newPackageJsonContents = JSON.stringify(packageJson, null, 2); | |||
console.log('Updating package.json...'); | |||
writeFileSync('./package.json', newPackageJsonContents); | |||
console.log('Done'); | |||
} | |||
doCopy('./src/components/DropdownSelect/DropdownSelect.css', './dist/DropdownSelect.css'); | |||
doCopy('./src/components/MenuSelect/MenuSelect.css', './dist/MenuSelect.css'); | |||
doCopy('./src/components/RadioButton/RadioButton.css', './dist/RadioButton.css'); | |||
doCopy('./src/components/RadioTickBox/RadioTickBox.css', './dist/RadioTickBox.css'); |
@@ -115,6 +115,34 @@ export const ComboBox = React.forwardRef<ComboBoxDerivedElement, ComboBoxProps>( | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
size={length} | |||
@@ -156,31 +184,6 @@ export const ComboBox = React.forwardRef<ComboBoxDerivedElement, ComboBoxProps>( | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -1,17 +0,0 @@ | |||
.tesseract-design-dropdown-select optgroup { | |||
color: rgb(var(--color-positive) / 50%); | |||
text-transform: uppercase; | |||
font-size: 0.75em; | |||
margin-top: 0.5rem; | |||
user-select: none; | |||
} | |||
.tesseract-design-dropdown-select optgroup > option { | |||
color: rgb(var(--color-positive)); | |||
text-transform: none; | |||
font-size: 1.333333em; | |||
} | |||
.tesseract-design-dropdown-select option { | |||
user-select: none; | |||
} |
@@ -1,5 +1,6 @@ | |||
import * as React from 'react'; | |||
import { TextControl } from '@tesseract-design/web-base'; | |||
import plugin from 'tailwindcss/plugin'; | |||
import clsx from 'clsx'; | |||
/** | |||
@@ -45,6 +46,28 @@ export interface DropdownSelectProps extends Omit<React.HTMLProps<DropdownSelect | |||
hiddenLabel?: boolean, | |||
} | |||
export const dropdownSelectPlugin = plugin(({ addComponents }) => { | |||
addComponents({ | |||
'.dropdown-select': { | |||
'& optgroup': { | |||
'color': 'rgb(var(--color-positive) / 50%)', | |||
'text-transform': 'uppercase', | |||
'font-size': '0.75em', | |||
'margin-top': '0.5rem', | |||
'user-select': 'none', | |||
}, | |||
'& optgroup > option': { | |||
'color': 'rgb(var(--color-positive))', | |||
'text-transform': 'none', | |||
'font-size': '1.333333em', | |||
}, | |||
'& option': { | |||
'user-select': 'none', | |||
}, | |||
}, | |||
}); | |||
}); | |||
/** | |||
* Component for selecting a single value from a dropdown. | |||
*/ | |||
@@ -84,6 +107,34 @@ export const DropdownSelect = React.forwardRef<DropdownSelectDerivedElement, Dro | |||
data-testid="base" | |||
style={style} | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
htmlFor={id} | |||
data-testid="label" | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<select | |||
{...etcProps} | |||
ref={forwardedRef} | |||
@@ -92,7 +143,7 @@ export const DropdownSelect = React.forwardRef<DropdownSelectDerivedElement, Dro | |||
data-testid="input" | |||
role="combobox" | |||
className={clsx( | |||
'tesseract-design-dropdown-select bg-negative rounded-inherit w-full peer block appearance-none cursor-pointer select-none font-inherit', | |||
'dropdown-select bg-negative rounded-inherit w-full peer block appearance-none cursor-pointer select-none font-inherit', | |||
'focus:outline-0', | |||
'disabled:opacity-50 disabled:cursor-not-allowed', | |||
{ | |||
@@ -124,31 +175,6 @@ export const DropdownSelect = React.forwardRef<DropdownSelectDerivedElement, Dro | |||
> | |||
{children} | |||
</select> | |||
{label && ( | |||
<label | |||
htmlFor={id} | |||
data-testid="label" | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -1,17 +0,0 @@ | |||
.tesseract-design-menu-select optgroup { | |||
color: rgb(var(--color-positive) / 50%); | |||
text-transform: uppercase; | |||
font-size: 0.75em; | |||
margin-top: 0.5rem; | |||
user-select: none; | |||
} | |||
.tesseract-design-menu-select optgroup > option { | |||
color: rgb(var(--color-positive)); | |||
text-transform: none; | |||
font-size: 1.333333em; | |||
} | |||
.tesseract-design-menu-select option { | |||
user-select: none; | |||
} |
@@ -1,6 +1,7 @@ | |||
import * as React from 'react'; | |||
import { TextControl } from '@tesseract-design/web-base'; | |||
import clsx from 'clsx'; | |||
import plugin from 'tailwindcss/plugin'; | |||
/** | |||
* Derived HTML element of the {@link MenuSelect} component. | |||
@@ -49,6 +50,28 @@ export interface MenuSelectProps extends Omit<React.HTMLProps<MenuSelectDerivedE | |||
startingHeight?: number | string, | |||
} | |||
export const menuSelectPlugin = plugin(({ addComponents }) => { | |||
addComponents({ | |||
'.menu-select': { | |||
'& optgroup': { | |||
'color': 'rgb(var(--color-positive) / 50%)', | |||
'text-transform': 'uppercase', | |||
'font-size': '0.75em', | |||
'margin-top': '0.5rem', | |||
'user-select': 'none', | |||
}, | |||
'& optgroup > option': { | |||
'color': 'rgb(var(--color-positive))', | |||
'text-transform': 'none', | |||
'font-size': '1.333333em', | |||
}, | |||
'& option': { | |||
'user-select': 'none', | |||
}, | |||
}, | |||
}); | |||
}); | |||
/** | |||
* Component for selecting a single value from a menu. | |||
*/ | |||
@@ -86,6 +109,34 @@ export const MenuSelect = React.forwardRef<MenuSelectDerivedElement, MenuSelectP | |||
)} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
htmlFor={id} | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<select | |||
{...etcProps} | |||
ref={forwardedRef} | |||
@@ -97,7 +148,7 @@ export const MenuSelect = React.forwardRef<MenuSelectDerivedElement, MenuSelectP | |||
height: startingHeight, | |||
}} | |||
className={clsx( | |||
'tesseract-design-menu-select bg-negative rounded-inherit w-full peer block overflow-auto cursor-pointer font-inherit', | |||
'menu-select bg-negative rounded-inherit w-full peer block overflow-auto cursor-pointer font-inherit', | |||
'focus:outline-0', | |||
'disabled:opacity-50 disabled:cursor-not-allowed', | |||
{ | |||
@@ -138,31 +189,6 @@ export const MenuSelect = React.forwardRef<MenuSelectDerivedElement, MenuSelectP | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
htmlFor={id} | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -1,7 +0,0 @@ | |||
.tesseract-design-radio-button + label > :first-child > :first-child { | |||
display: none; | |||
} | |||
.tesseract-design-radio-button:checked + label > :first-child > :first-child { | |||
display: block; | |||
} |
@@ -1,6 +1,7 @@ | |||
import * as React from 'react'; | |||
import clsx from 'clsx'; | |||
import { Button } from '@tesseract-design/web-base'; | |||
import plugin from 'tailwindcss/plugin'; | |||
/** | |||
* Derived HTML element of the {@link RadioButton} component. | |||
@@ -37,6 +38,19 @@ export interface RadioButtonProps extends Omit<React.InputHTMLAttributes<RadioBu | |||
variant?: Button.Variant; | |||
} | |||
export const radioButtonPlugin = plugin(({ addComponents }) => { | |||
addComponents({ | |||
'.radio-button': { | |||
'& + label > :first-child > :first-child': { | |||
'display': 'none', | |||
}, | |||
'&:checked + label > :first-child > :first-child': { | |||
'display': 'block', | |||
}, | |||
}, | |||
}); | |||
}); | |||
/** | |||
* Component for selecting a single value from an array of choices grouped by name. | |||
* | |||
@@ -67,7 +81,7 @@ export const RadioButton = React.forwardRef<RadioButtonDerivedElement, RadioButt | |||
ref={forwardedRef} | |||
type="radio" | |||
id={id} | |||
className="sr-only peer tesseract-design-radio-button" | |||
className="sr-only peer radio-button" | |||
/> | |||
<label | |||
style={style} | |||
@@ -1,7 +0,0 @@ | |||
.tesseract-design-radio-tick-box + label + label > :first-child > :first-child { | |||
display: none; | |||
} | |||
.tesseract-design-radio-tick-box:checked + label + label > :first-child > :first-child { | |||
display: block; | |||
} |
@@ -1,5 +1,6 @@ | |||
import * as React from 'react'; | |||
import clsx from 'clsx'; | |||
import plugin from 'tailwindcss/plugin'; | |||
/** | |||
* Derived HTML element of the {@link RadioTickBox} component. | |||
@@ -20,6 +21,19 @@ export interface RadioTickBoxProps extends Omit<React.InputHTMLAttributes<RadioT | |||
subtext?: React.ReactNode; | |||
} | |||
export const radioTickBoxPlugin = plugin(({ addComponents }) => { | |||
addComponents({ | |||
'.radio-tick-box': { | |||
'& + label + label > :first-child > :first-child': { | |||
'display': 'none', | |||
}, | |||
'&:checked + label + label > :first-child > :first-child': { | |||
'display': 'block', | |||
}, | |||
}, | |||
}); | |||
}); | |||
/** | |||
* Component for selecting a single value from an array of choices grouped by name. | |||
* | |||
@@ -55,7 +69,7 @@ export const RadioTickBox = React.forwardRef<RadioTickBoxDerivedElement, RadioTi | |||
ref={forwardedRef} | |||
type="radio" | |||
id={id} | |||
className="sr-only peer/radio tesseract-design-radio-tick-box" | |||
className="sr-only peer/radio radio-tick-box" | |||
/> | |||
<label | |||
htmlFor={id} | |||
@@ -1,6 +1,7 @@ | |||
{ | |||
"root": true, | |||
"rules": { | |||
"quote-props": "off", | |||
"react/jsx-props-no-spreading": "off" | |||
}, | |||
"extends": [ | |||
@@ -27,7 +27,6 @@ | |||
"react-dom": "^18.2.0", | |||
"react-test-renderer": "^18.2.0", | |||
"tslib": "^2.5.0", | |||
"tsx": "^3.12.7", | |||
"typescript": "^4.9.5", | |||
"vitest": "^0.28.1" | |||
}, | |||
@@ -37,7 +36,7 @@ | |||
}, | |||
"scripts": { | |||
"prepublishOnly": "pridepack clean && pridepack build", | |||
"build": "pridepack build && tsx scripts/build.ts", | |||
"build": "pridepack build", | |||
"type-check": "pridepack check", | |||
"lint": "pridepack lint", | |||
"clean": "pridepack clean", | |||
@@ -63,7 +62,8 @@ | |||
"dependencies": { | |||
"clsx": "^1.2.1", | |||
"color": "^4.2.3", | |||
"color-convert": "^2.0.1" | |||
"color-convert": "^2.0.1", | |||
"tailwindcss": "3.3.2" | |||
}, | |||
"types": "./dist/types/index.d.ts", | |||
"main": "./dist/cjs/production/index.js", | |||
@@ -77,10 +77,9 @@ | |||
"require": "./dist/cjs/production/index.js", | |||
"import": "./dist/esm/production/index.js", | |||
"types": "./dist/types/index.d.ts" | |||
}, | |||
"./dist/ColorPicker.css": "./dist/ColorPicker.css" | |||
} | |||
}, | |||
"typesVersions": { | |||
"*": {} | |||
} | |||
} | |||
} |
@@ -1,19 +0,0 @@ | |||
import { copyFileSync, readFileSync, writeFileSync } from 'fs'; | |||
import { resolve } from 'path'; | |||
const doCopy = (src: string, dest: string) => { | |||
const trueSrc = resolve(src); | |||
const trueDest = resolve(dest); | |||
console.log('Copying...'); | |||
console.log(`${trueSrc} -> ${trueDest}`); | |||
copyFileSync(trueSrc, trueDest); | |||
const packageJsonContents = readFileSync('./package.json', 'utf-8'); | |||
const packageJson = JSON.parse(packageJsonContents); | |||
packageJson.exports[dest] = dest; | |||
const newPackageJsonContents = JSON.stringify(packageJson, null, 2); | |||
console.log('Updating package.json...'); | |||
writeFileSync('./package.json', newPackageJsonContents); | |||
console.log('Done'); | |||
} | |||
doCopy('./src/components/ColorPicker/ColorPicker.css', './dist/ColorPicker.css'); |
@@ -1,7 +0,0 @@ | |||
.color-picker::-webkit-color-swatch-wrapper { | |||
padding: 0; | |||
} | |||
.color-picker::-webkit-color-swatch { | |||
border: 2px solid black; | |||
} |
@@ -1,5 +1,6 @@ | |||
import * as React from 'react'; | |||
import clsx from 'clsx'; | |||
import plugin from 'tailwindcss/plugin'; | |||
export type ColorPickerDerivedElement = HTMLInputElement; | |||
@@ -8,6 +9,19 @@ export interface ColorPickerProps extends Omit<React.HTMLProps<ColorPickerDerive | |||
size?: 'small' | 'medium' | 'large'; | |||
} | |||
export const colorPickerPlugin = plugin(({ addComponents }) => { | |||
addComponents({ | |||
'.color-picker': { | |||
'&::-webkit-color-swatch-wrapper': { | |||
'padding': '0', | |||
}, | |||
'&::-webkit-color-swatch': { | |||
'border': '2px solid black', | |||
}, | |||
}, | |||
}); | |||
}); | |||
export const ColorPicker = React.forwardRef< | |||
ColorPickerDerivedElement, | |||
ColorPickerProps | |||
@@ -93,6 +93,34 @@ export const EmailInput = React.forwardRef<EmailInputDerivedElement, EmailInputP | |||
)} | |||
style={style} | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
size={length} | |||
@@ -133,31 +161,6 @@ export const EmailInput = React.forwardRef<EmailInputDerivedElement, EmailInputP | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -104,6 +104,34 @@ export const PatternTextInput = React.forwardRef< | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
htmlFor={id} | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
size={length} | |||
@@ -144,31 +172,6 @@ export const PatternTextInput = React.forwardRef< | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
htmlFor={id} | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -147,6 +147,34 @@ export const PhoneNumberInput = React.forwardRef< | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
size={length} | |||
@@ -171,31 +199,6 @@ export const PhoneNumberInput = React.forwardRef< | |||
className={commonInputStyles} | |||
/> | |||
)} | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -82,6 +82,34 @@ export const UrlInput = React.forwardRef<UrlInputDerivedElement, UrlInputProps>( | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
htmlFor={id} | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
size={length} | |||
@@ -121,31 +149,6 @@ export const UrlInput = React.forwardRef<UrlInputDerivedElement, UrlInputProps>( | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
htmlFor={id} | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -85,6 +85,34 @@ export const MaskedTextInput = React.forwardRef< | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
size={length} | |||
@@ -124,31 +152,6 @@ export const MaskedTextInput = React.forwardRef< | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -82,6 +82,34 @@ export const MultilineTextInput = React.forwardRef< | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<textarea | |||
{...etcProps} | |||
ref={forwardedRef} | |||
@@ -133,31 +161,6 @@ export const MultilineTextInput = React.forwardRef< | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -101,6 +101,34 @@ export const TextInput = React.forwardRef<TextInputDerivedElement, TextInputProp | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
htmlFor={id} | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
size={length} | |||
@@ -141,31 +169,6 @@ export const TextInput = React.forwardRef<TextInputDerivedElement, TextInputProp | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
htmlFor={id} | |||
id={labelId} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -28,7 +28,6 @@ | |||
"react-dom": "^18.2.0", | |||
"react-test-renderer": "^18.2.0", | |||
"tslib": "^2.5.0", | |||
"tsx": "^3.12.7", | |||
"typescript": "^4.9.5", | |||
"vitest": "^0.33.0" | |||
}, | |||
@@ -38,7 +37,7 @@ | |||
}, | |||
"scripts": { | |||
"prepublishOnly": "pridepack clean && pridepack build", | |||
"build": "pridepack build && tsx scripts/build.ts", | |||
"build": "pridepack build", | |||
"type-check": "pridepack check", | |||
"lint": "pridepack lint", | |||
"clean": "pridepack clean", | |||
@@ -65,7 +64,8 @@ | |||
"@modal-sh/react-utils": "workspace:*", | |||
"@tesseract-design/web-base": "workspace:*", | |||
"clsx": "^1.2.1", | |||
"react-tag-input-component": "^2.0.2" | |||
"react-tag-input-component": "^2.0.2", | |||
"tailwindcss": "3.3.2" | |||
}, | |||
"types": "./dist/types/index.d.ts", | |||
"main": "./dist/cjs/production/index.js", | |||
@@ -79,14 +79,9 @@ | |||
"require": "./dist/cjs/production/index.js", | |||
"import": "./dist/esm/production/index.js", | |||
"types": "./dist/types/index.d.ts" | |||
}, | |||
"./dist/MenuMultiSelect.css": "./dist/MenuMultiSelect.css", | |||
"./dist/TagInput.css": "./dist/TagInput.css", | |||
"./dist/ToggleButton.css": "./dist/ToggleButton.css", | |||
"./dist/ToggleSwitch.css": "./dist/ToggleSwitch.css", | |||
"./dist/ToggleTickBox.css": "./dist/ToggleTickBox.css" | |||
} | |||
}, | |||
"typesVersions": { | |||
"*": {} | |||
} | |||
} | |||
} |
@@ -1,23 +0,0 @@ | |||
import { copyFileSync, readFileSync, writeFileSync } from 'fs'; | |||
import { resolve } from 'path'; | |||
const doCopy = (src: string, dest: string) => { | |||
const trueSrc = resolve(src); | |||
const trueDest = resolve(dest); | |||
console.log('Copying...'); | |||
console.log(`${trueSrc} -> ${trueDest}`); | |||
copyFileSync(trueSrc, trueDest); | |||
const packageJsonContents = readFileSync('./package.json', 'utf-8'); | |||
const packageJson = JSON.parse(packageJsonContents); | |||
packageJson.exports[dest] = dest; | |||
const newPackageJsonContents = JSON.stringify(packageJson, null, 2); | |||
console.log('Updating package.json...'); | |||
writeFileSync('./package.json', newPackageJsonContents); | |||
console.log('Done'); | |||
} | |||
doCopy('./src/components/MenuMultiSelect/MenuMultiSelect.css', './dist/MenuMultiSelect.css'); | |||
doCopy('./src/components/TagInput/TagInput.css', './dist/TagInput.css'); | |||
doCopy('./src/components/ToggleButton/ToggleButton.css', './dist/ToggleButton.css'); | |||
doCopy('./src/components/ToggleSwitch/ToggleSwitch.css', './dist/ToggleSwitch.css'); | |||
doCopy('./src/components/ToggleTickBox/ToggleTickBox.css', './dist/ToggleTickBox.css'); |
@@ -1,17 +0,0 @@ | |||
.tesseract-design-menu-multi-select optgroup { | |||
color: rgb(var(--color-positive) / 50%); | |||
text-transform: uppercase; | |||
font-size: 0.75em; | |||
margin-top: 0.5rem; | |||
user-select: none; | |||
} | |||
.tesseract-design-menu-multi-select optgroup > option { | |||
color: rgb(var(--color-positive)); | |||
text-transform: none; | |||
font-size: 1.333333em; | |||
} | |||
.tesseract-design-menu-multi-select option { | |||
user-select: none; | |||
} |
@@ -1,6 +1,7 @@ | |||
import * as React from 'react'; | |||
import { TextControl } from '@tesseract-design/web-base'; | |||
import clsx from 'clsx'; | |||
import plugin from 'tailwindcss/plugin'; | |||
export type MenuMultiSelectDerivedElement = HTMLSelectElement; | |||
@@ -43,6 +44,28 @@ export interface MenuMultiSelectProps extends Omit<React.HTMLProps<MenuMultiSele | |||
startingHeight?: number | string, | |||
} | |||
export const menuMultiSelectPlugin = plugin(({ addComponents, }) => { | |||
addComponents({ | |||
'.menu-multi-select': { | |||
'& optgroup': { | |||
'color': 'rgb(var(--color-positive) / 50%)', | |||
'text-transform': 'uppercase', | |||
'font-size': '0.75em', | |||
'margin-top': '0.5rem', | |||
'user-select': 'none', | |||
}, | |||
'& optgroup > option': { | |||
'color': 'rgb(var(--color-positive))', | |||
'text-transform': 'none', | |||
'font-size': '1.333333em', | |||
}, | |||
'& option': { | |||
'user-select': 'none', | |||
}, | |||
}, | |||
}); | |||
}); | |||
/** | |||
* Component for inputting textual values. | |||
* | |||
@@ -75,7 +98,7 @@ export const MenuMultiSelect = React.forwardRef< | |||
return ( | |||
<div | |||
className={clsx( | |||
'tesseract-design-menu-multi-select relative rounded ring-secondary/50', | |||
'menu-multi-select relative rounded ring-secondary/50', | |||
'focus-within:ring-4', | |||
{ | |||
'block': block, | |||
@@ -85,6 +108,34 @@ export const MenuMultiSelect = React.forwardRef< | |||
)} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<select | |||
{...etcProps} | |||
ref={forwardedRef} | |||
@@ -138,31 +189,6 @@ export const MenuMultiSelect = React.forwardRef< | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -1,109 +0,0 @@ | |||
.tesseract-design-tag-input textarea + div > input { | |||
flex: auto; | |||
} | |||
.tesseract-design-tag-input.tag-input-small textarea + div > input { | |||
font-size: 0.625rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-medium textarea + div > input { | |||
font-size: 0.75rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-default textarea + div { | |||
padding-left: 1rem; | |||
padding-right: 1rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-alternate textarea + div { | |||
padding-left: 0.375rem; | |||
padding-right: 0.375rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-small.tag-input-default textarea + div { | |||
padding-top: 0.625rem; | |||
padding-bottom: 0.875rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-medium.tag-input-default textarea + div { | |||
padding-top: 0.75rem; | |||
padding-bottom: 1rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-large.tag-input-default textarea + div { | |||
padding-top: 1rem; | |||
padding-bottom: 1.25rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-small.tag-input-alternate textarea + div { | |||
padding-top: 1.375rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-medium.tag-input-alternate textarea + div { | |||
padding-top: 1.5rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-large.tag-input-alternate textarea + div { | |||
padding-top: 1.75rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-small textarea + div { | |||
gap: 0.25rem; | |||
min-height: 2.5rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-small.tag-input-indicator textarea + div { | |||
padding-right: 2.5rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-medium textarea + div { | |||
gap: 0.375rem; | |||
min-height: 3rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-medium.tag-input-indicator textarea + div { | |||
padding-right: 3rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-large textarea + div { | |||
gap: 0.375rem; | |||
min-height: 4rem; | |||
} | |||
.tesseract-design-tag-input.tag-input-large.tag-input-indicator textarea + div { | |||
padding-right: 4rem; | |||
} | |||
.tesseract-design-tag-input textarea + div > span { | |||
padding: 0.125rem; | |||
border-radius: 0.25rem; | |||
line-height: 1; | |||
background-color: rgb(var(--color-positive) / 25%); | |||
} | |||
.tesseract-design-tag-input textarea + div > span:focus-within { | |||
background-color: rgb(var(--color-secondary) / 25%); | |||
} | |||
.tesseract-design-tag-input textarea + div > span span { | |||
pointer-events: none; | |||
} | |||
.tesseract-design-tag-input textarea + div > span button { | |||
color: rgb(var(--color-primary)); | |||
padding: 0; | |||
width: 1rem; | |||
margin-left: 0.25rem; | |||
} | |||
.tesseract-design-tag-input textarea + div > span button:focus { | |||
outline: none; | |||
color: rgb(var(--color-secondary)); | |||
} | |||
.tesseract-design-tag-input textarea + div > span button:focus:-moz-focusring { | |||
display: none; | |||
} | |||
.tesseract-design-tag-input textarea + div > span button:hover { | |||
color: rgb(var(--color-primary)); | |||
} |
@@ -3,6 +3,7 @@ import { TagsInput } from 'react-tag-input-component'; | |||
import clsx from 'clsx'; | |||
import { useClientSide, delegateTriggerEvent } from '@modal-sh/react-utils'; | |||
import { TextControl } from '@tesseract-design/web-base'; | |||
import plugin from 'tailwindcss/plugin'; | |||
const TAG_INPUT_SEPARATOR_MAP = { | |||
'comma': ',', | |||
@@ -61,6 +62,120 @@ export interface TagInputProps extends Omit<React.HTMLProps<TagInputDerivedEleme | |||
editOnRemove?: boolean, | |||
} | |||
export const tagInputPlugin = plugin(({ addComponents }) => { | |||
addComponents({ | |||
'.tag-input': { | |||
'& textarea + div > input': { | |||
'flex': 'auto', | |||
}, | |||
'&[data-size="small"] textarea + div > input': { | |||
'font-size': '0.625rem', | |||
}, | |||
'&[data-size="medium"] textarea + div > input': { | |||
'font-size': '0.75rem', | |||
}, | |||
'&[data-variant="default"] textarea + div': { | |||
'padding-left': '1rem', | |||
'padding-right': '1rem', | |||
}, | |||
'&[data-variant="alternate"] textarea + div': { | |||
'padding-left': '0.375rem', | |||
'padding-right': '0.375rem', | |||
}, | |||
'&[data-size="small"][data-variant="default"] textarea + div': { | |||
'padding-top': '0.625rem', | |||
'padding-bottom': '0.875rem', | |||
}, | |||
'&[data-size="medium"][data-variant="default"] textarea + div': { | |||
'padding-top': '0.75rem', | |||
'padding-bottom': '1rem', | |||
}, | |||
'&[data-size="large"][data-variant="default"] textarea + div': { | |||
'padding-top': '1rem', | |||
'padding-bottom': '1.25rem', | |||
}, | |||
'&[data-size="small"][data-variant="alternate"] textarea + div': { | |||
'padding-top': '1.375rem', | |||
}, | |||
'&[data-size="medium"][data-variant="alternate"] textarea + div': { | |||
'padding-top': '1.5rem', | |||
}, | |||
'&[data-size="large"][data-variant="alternate"] textarea + div': { | |||
'padding-top': '1.75rem', | |||
}, | |||
'&[data-size="small"] textarea + div': { | |||
'gap': '0.25rem', | |||
'min-height': '2.5rem', | |||
}, | |||
'&[data-size="small"].tag-input-indicator textarea + div': { | |||
'padding-right': '2.5rem', | |||
}, | |||
'&[data-size="medium"] textarea + div': { | |||
'gap': '0.375rem', | |||
'min-height': '3rem', | |||
}, | |||
'&[data-size="medium"].tag-input-indicator textarea + div': { | |||
'padding-right': '3rem', | |||
}, | |||
'&[data-size="large"] textarea + div': { | |||
'gap': '0.375rem', | |||
'min-height': '4rem', | |||
}, | |||
'&[data-size="large"].tag-input-indicator textarea + div': { | |||
'padding-right': '4rem', | |||
}, | |||
'& textarea + div > span': { | |||
'padding': '0.125rem', | |||
'border-radius': '0.25rem', | |||
'line-height': '1', | |||
'background-color': 'rgb(var(--color-positive) / 25%)', | |||
}, | |||
'& textarea + div > span:focus-within': { | |||
'background-color': 'rgb(var(--color-secondary) / 25%)', | |||
}, | |||
'& textarea + div > span span': { | |||
'pointer-events': 'none', | |||
}, | |||
'& textarea + div > span button': { | |||
'color': 'rgb(var(--color-primary))', | |||
'padding': '0', | |||
'width': '1rem', | |||
'margin-left': '0.25rem', | |||
}, | |||
'& textarea + div > span button:focus': { | |||
'outline': 'none', | |||
'color': 'rgb(var(--color-secondary))', | |||
}, | |||
'& textarea + div > span button:focus:-moz-focusring': { | |||
'display': 'none', | |||
}, | |||
'& textarea + div > span button:hover': { | |||
'color': 'rgb(var(--color-primary))', | |||
}, | |||
}, | |||
}); | |||
}); | |||
/** | |||
* Component for inputting textual values. | |||
* | |||
@@ -203,6 +318,8 @@ export const TagInput = React.forwardRef<TagInputDerivedElement, TagInputProps>( | |||
return ( | |||
<div | |||
data-size={size} | |||
data-variant={variant} | |||
className={clsx( | |||
'relative rounded ring-secondary/50 group', | |||
'focus-within:ring-4', | |||
@@ -215,18 +332,41 @@ export const TagInput = React.forwardRef<TagInputDerivedElement, TagInputProps>( | |||
'min-h-12': size === 'medium', | |||
'min-h-16': size === 'large', | |||
}, | |||
'tesseract-design-tag-input', | |||
size === 'small' && 'tag-input-small', | |||
size === 'medium' && 'tag-input-medium', | |||
size === 'large' && 'tag-input-large', | |||
'tag-input', | |||
indicator && 'tag-input-indicator', | |||
variant === 'default' && 'tag-input-default', | |||
variant === 'alternate' && 'tag-input-alternate', | |||
className, | |||
)} | |||
data-testid="base" | |||
onFocusCapture={handleFocusCapture} | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 group-focus-within:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<textarea | |||
{...etcProps} | |||
placeholder={placeholder} | |||
@@ -303,31 +443,6 @@ export const TagInput = React.forwardRef<TagInputDerivedElement, TagInputProps>( | |||
separators={separator.map((s) => TAG_INPUT_SEPARATOR_MAP[s])} | |||
/> | |||
)} | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 group-focus-within:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -1,15 +0,0 @@ | |||
.tesseract-design-toggle-button + label > :first-child > :first-child { | |||
display: none; | |||
} | |||
.tesseract-design-toggle-button:checked + label > :first-child > :first-child { | |||
display: block; | |||
} | |||
.tesseract-design-toggle-button + label > :first-child > :first-child + * { | |||
display: none; | |||
} | |||
.tesseract-design-toggle-button:indeterminate + label > :first-child > :first-child + * { | |||
display: block; | |||
} |
@@ -1,6 +1,7 @@ | |||
import * as React from 'react'; | |||
import clsx from 'clsx'; | |||
import { Button } from '@tesseract-design/web-base'; | |||
import plugin from 'tailwindcss/plugin'; | |||
export type ToggleButtonDerivedElement = HTMLInputElement; | |||
@@ -14,6 +15,25 @@ export interface ToggleButtonProps extends Omit<React.InputHTMLAttributes<Toggle | |||
indeterminate?: boolean; | |||
} | |||
export const toggleButtonPlugin = plugin(({ addComponents, }) => { | |||
addComponents({ | |||
'.toggle-button': { | |||
'& + label > :first-child > :first-child': { | |||
'display': 'none', | |||
}, | |||
'&:checked + label > :first-child > :first-child': { | |||
'display': 'block', | |||
}, | |||
'& + label > :first-child > :first-child + *': { | |||
'display': 'none', | |||
}, | |||
'&:indeterminate + label > :first-child > :first-child + *': { | |||
'display': 'block', | |||
}, | |||
}, | |||
}); | |||
}); | |||
export const ToggleButton = React.forwardRef<ToggleButtonDerivedElement, ToggleButtonProps>(( | |||
{ | |||
children, | |||
@@ -53,7 +73,7 @@ export const ToggleButton = React.forwardRef<ToggleButtonDerivedElement, ToggleB | |||
ref={typeof ref === 'function' ? defaultRef : ref} | |||
type="checkbox" | |||
id={id} | |||
className="sr-only peer tesseract-design-toggle-button" | |||
className="sr-only peer toggle-button" | |||
/> | |||
<label | |||
data-testid="button" | |||
@@ -1,118 +0,0 @@ | |||
.tesseract-design-toggle-switch + label + label + label > :first-child { | |||
appearance: none; | |||
cursor: pointer; | |||
position: relative; | |||
overflow: hidden; | |||
height: 1.5em; | |||
width: 3em; | |||
display: block; | |||
box-sizing: border-box; | |||
border-radius: 9999px; | |||
color: rgb(var(--color-primary)); | |||
} | |||
.tesseract-design-toggle-switch:checked + label + label + label > :first-child { | |||
color: rgb(var(--color-tertiary)); | |||
} | |||
.tesseract-design-toggle-switch:focus + label + label + label > :first-child { | |||
color: rgb(var(--color-secondary)); | |||
} | |||
.tesseract-design-toggle-switch + label:active + label + label > :first-child { | |||
color: rgb(var(--color-tertiary)); | |||
} | |||
.tesseract-design-toggle-switch + label + label:active + label > :first-child { | |||
color: rgb(var(--color-tertiary)); | |||
} | |||
.tesseract-design-toggle-switch + label + label + label:active > :first-child { | |||
color: rgb(var(--color-tertiary)); | |||
} | |||
.tesseract-design-toggle-switch + label + label + label > :first-child > :first-child { | |||
width: 100%; | |||
height: 100%; | |||
background-color: rgb(var(--color-primary) / 50%); | |||
border-radius: 9999px; | |||
display: block; | |||
box-sizing: border-box; | |||
background-clip: content-box; | |||
padding: 0.25em; | |||
appearance: none; | |||
} | |||
.tesseract-design-toggle-switch:checked + label + label + label > :first-child > :first-child { | |||
background-color: rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch:focus + label + label + label > :first-child > :first-child { | |||
background-color: rgb(var(--color-secondary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch + label:active + label + label > :first-child > :first-child { | |||
background-color: rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch + label + label:active + label > :first-child > :first-child { | |||
background-color: rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch + label + label + label:active > :first-child > :first-child { | |||
background-color: rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch + label + label + label > :first-child > :first-child > :first-child { | |||
appearance: none; | |||
border-radius: 9999px; | |||
display: block; | |||
width: 100%; | |||
height: 100%; | |||
margin: -0.25em; | |||
box-sizing: border-box; | |||
background-clip: content-box; | |||
} | |||
.tesseract-design-toggle-switch + label + label + label > :first-child > :first-child > :first-child > :first-child { | |||
width: 1.5em; | |||
height: 1.5em; | |||
margin: -0.25em 0 0 0; | |||
display: block; | |||
border-radius: 9999px; | |||
background-color: currentColor; | |||
appearance: none; | |||
aspect-ratio: 1 / 1; | |||
z-index: 1; | |||
position: relative; | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-primary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch:checked + label + label + label > :first-child > :first-child > :first-child > :first-child { | |||
margin-left: calc(100% - 1em); | |||
} | |||
.tesseract-design-toggle-switch:indeterminate + label + label + label > :first-child > :first-child > :first-child > :first-child { | |||
margin-left: calc(50% - 0.5em); | |||
} | |||
.tesseract-design-toggle-switch:checked + label + label + label > :first-child > :first-child > :first-child > :first-child { | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch:focus + label + label + label > :first-child > :first-child > :first-child > :first-child { | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-secondary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch + label:active + label + label > :first-child > :first-child > :first-child > :first-child { | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch + label + label:active + label > :first-child > :first-child > :first-child > :first-child { | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-toggle-switch + label + label + label:active > :first-child > :first-child > :first-child > :first-child { | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%); | |||
} | |||
@@ -1,5 +1,6 @@ | |||
import * as React from 'react'; | |||
import clsx from 'clsx'; | |||
import plugin from 'tailwindcss/plugin'; | |||
export type ToggleSwitchDerivedElement = HTMLInputElement; | |||
@@ -11,6 +12,127 @@ export interface ToggleSwitchProps extends Omit<React.InputHTMLAttributes<Toggle | |||
uncheckedLabel?: React.ReactNode; | |||
} | |||
export const toggleSwitchPlugin = plugin(({ addComponents }) => { | |||
addComponents({ | |||
'.toggle-switch': { | |||
'& + label + label + label > :first-child': { | |||
appearance: 'none', | |||
cursor: 'pointer', | |||
position: 'relative', | |||
overflow: 'hidden', | |||
height: '1.5em', | |||
width: '3em', | |||
display: 'block', | |||
'box-sizing': 'border-box', | |||
'border-radius': '9999px', | |||
color: 'rgb(var(--color-primary))', | |||
}, | |||
'&:checked + label + label + label > :first-child': { | |||
color: 'rgb(var(--color-tertiary))', | |||
}, | |||
'&:focus + label + label + label > :first-child': { | |||
color: 'rgb(var(--color-secondary))', | |||
}, | |||
'& + label:active + label + label > :first-child': { | |||
color: 'rgb(var(--color-tertiary))', | |||
}, | |||
'& + label + label:active + label > :first-child': { | |||
color: 'rgb(var(--color-tertiary))', | |||
}, | |||
'& + label + label + label:active > :first-child': { | |||
color: 'rgb(var(--color-tertiary))', | |||
}, | |||
'& + label + label + label > :first-child > :first-child': { | |||
width: '100%', | |||
height: '100%', | |||
'background-color': 'rgb(var(--color-primary) / 50%)', | |||
'border-radius': '9999px', | |||
display: 'block', | |||
'box-sizing': 'border-box', | |||
'background-clip': 'content-box', | |||
padding: '0.25em', | |||
appearance: 'none', | |||
}, | |||
'&:checked + label + label + label > :first-child > :first-child': { | |||
'background-color': 'rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'&:focus + label + label + label > :first-child > :first-child': { | |||
'background-color': 'rgb(var(--color-secondary) / 50%)', | |||
}, | |||
'& + label:active + label + label > :first-child > :first-child': { | |||
'background-color': 'rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'& + label + label:active + label > :first-child > :first-child': { | |||
'background-color': 'rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'& + label + label + label:active > :first-child > :first-child': { | |||
'background-color': 'rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'& + label + label + label > :first-child > :first-child > :first-child': { | |||
appearance: 'none', | |||
'border-radius': '9999px', | |||
display: 'block', | |||
width: '100%', | |||
height: '100%', | |||
margin: '-0.25em', | |||
'box-sizing': 'border-box', | |||
'background-clip': 'content-box', | |||
}, | |||
'& + label + label + label > :first-child > :first-child > :first-child > :first-child': { | |||
width: '1.5em', | |||
height: '1.5em', | |||
margin: '-0.25em 0 0 0', | |||
display: 'block', | |||
'border-radius': '9999px', | |||
'background-color': 'currentColor', | |||
appearance: 'none', | |||
'aspect-ratio': '1 / 1', | |||
'z-index': '1', | |||
position: 'relative', | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-primary) / 50%)', | |||
}, | |||
'&:checked + label + label + label > :first-child > :first-child > :first-child > :first-child': { | |||
'margin-left': 'calc(100% - 1em)', | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'&:indeterminate + label + label + label > :first-child > :first-child > :first-child > :first-child': { | |||
'margin-left': 'calc(50% - 0.5em)', | |||
}, | |||
'&:focus + label + label + label > :first-child > :first-child > :first-child > :first-child': { | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-secondary) / 50%)', | |||
}, | |||
'& + label:active + label + label > :first-child > :first-child > :first-child > :first-child': { | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'& + label + label:active + label > :first-child > :first-child > :first-child > :first-child': { | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'& + label + label + label:active > :first-child > :first-child > :first-child > :first-child': { | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
}, | |||
}); | |||
}); | |||
export const ToggleSwitch = React.forwardRef<ToggleSwitchDerivedElement, ToggleSwitchProps>(( | |||
{ | |||
uncheckedLabel, | |||
@@ -57,7 +179,7 @@ export const ToggleSwitch = React.forwardRef<ToggleSwitchDerivedElement, ToggleS | |||
ref={typeof ref === 'function' ? defaultRef : ref} | |||
type="checkbox" | |||
id={id} | |||
className="sr-only peer/radio tesseract-design-toggle-switch" | |||
className="sr-only peer/radio toggle-switch" | |||
/> | |||
<label | |||
htmlFor={id} | |||
@@ -1,15 +0,0 @@ | |||
.tesseract-design-toggle-tick-box + label + label > :first-child > :first-child { | |||
display: none; | |||
} | |||
.tesseract-design-toggle-tick-box:checked + label + label > :first-child > :first-child { | |||
display: block; | |||
} | |||
.tesseract-design-toggle-tick-box + label + label > :first-child > :first-child + * { | |||
display: none; | |||
} | |||
.tesseract-design-toggle-tick-box:indeterminate + label + label > :first-child > :first-child + * { | |||
display: block; | |||
} |
@@ -1,5 +1,6 @@ | |||
import * as React from 'react'; | |||
import clsx from 'clsx'; | |||
import plugin from 'tailwindcss/plugin'; | |||
export type ToggleTickBoxDerivedElement = HTMLInputElement; | |||
@@ -9,6 +10,25 @@ export interface ToggleTickBoxProps extends Omit<React.InputHTMLAttributes<Toggl | |||
indeterminate?: boolean; | |||
} | |||
export const toggleTickBoxPlugin = plugin(({ addComponents, }) => { | |||
addComponents({ | |||
'.toggle-tick-box': { | |||
'& + label + label > :first-child > :first-child': { | |||
'display': 'none', | |||
}, | |||
'&:checked + label + label > :first-child > :first-child': { | |||
'display': 'block', | |||
}, | |||
'& + label + label > :first-child > :first-child + *': { | |||
'display': 'none', | |||
}, | |||
'&:indeterminate + label + label > :first-child > :first-child + *': { | |||
'display': 'block', | |||
}, | |||
}, | |||
}); | |||
}); | |||
export const ToggleTickBox = React.forwardRef<ToggleTickBoxDerivedElement, ToggleTickBoxProps>(( | |||
{ | |||
children, | |||
@@ -54,7 +74,7 @@ export const ToggleTickBox = React.forwardRef<ToggleTickBoxDerivedElement, Toggl | |||
ref={typeof ref === 'function' ? defaultRef : ref} | |||
type="checkbox" | |||
id={id} | |||
className="sr-only peer/radio tesseract-design-toggle-tick-box" | |||
className="sr-only peer/radio toggle-tick-box" | |||
/> | |||
<label | |||
htmlFor={id} | |||
@@ -28,7 +28,6 @@ | |||
"react-dom": "^18.2.0", | |||
"react-test-renderer": "^18.2.0", | |||
"tslib": "^2.5.0", | |||
"tsx": "^3.12.7", | |||
"typescript": "^4.9.5", | |||
"vitest": "^0.33.0" | |||
}, | |||
@@ -38,7 +37,7 @@ | |||
}, | |||
"scripts": { | |||
"prepublishOnly": "pridepack clean && pridepack build", | |||
"build": "pridepack build && tsx scripts/build.ts", | |||
"build": "pridepack build", | |||
"type-check": "pridepack check", | |||
"lint": "pridepack lint", | |||
"clean": "pridepack clean", | |||
@@ -63,7 +62,8 @@ | |||
}, | |||
"dependencies": { | |||
"@tesseract-design/web-base": "workspace:*", | |||
"clsx": "^1.2.1" | |||
"clsx": "^1.2.1", | |||
"tailwindcss": "3.3.2" | |||
}, | |||
"types": "./dist/types/index.d.ts", | |||
"main": "./dist/cjs/production/index.js", | |||
@@ -77,11 +77,9 @@ | |||
"require": "./dist/cjs/production/index.js", | |||
"import": "./dist/esm/production/index.js", | |||
"types": "./dist/types/index.d.ts" | |||
}, | |||
"./dist/Slider.css": "./dist/Slider.css", | |||
"./dist/NumberSpinner.css": "./dist/NumberSpinner.css" | |||
} | |||
}, | |||
"typesVersions": { | |||
"*": {} | |||
} | |||
} | |||
} |
@@ -1,20 +0,0 @@ | |||
import { copyFileSync, readFileSync, writeFileSync } from 'fs'; | |||
import { resolve } from 'path'; | |||
const doCopy = (src: string, dest: string) => { | |||
const trueSrc = resolve(src); | |||
const trueDest = resolve(dest); | |||
console.log('Copying...'); | |||
console.log(`${trueSrc} -> ${trueDest}`); | |||
copyFileSync(trueSrc, trueDest); | |||
const packageJsonContents = readFileSync('./package.json', 'utf-8'); | |||
const packageJson = JSON.parse(packageJsonContents); | |||
packageJson.exports[dest] = dest; | |||
const newPackageJsonContents = JSON.stringify(packageJson, null, 2); | |||
console.log('Updating package.json...'); | |||
writeFileSync('./package.json', newPackageJsonContents); | |||
console.log('Done'); | |||
} | |||
doCopy('./src/components/Slider/Slider.css', './dist/Slider.css'); | |||
doCopy('./src/components/NumberSpinner/NumberSpinner.css', './dist/NumberSpinner.css'); |
@@ -1,12 +0,0 @@ | |||
.tesseract-design-number-spinner { | |||
position: relative; | |||
} | |||
.tesseract-design-number-spinner::-webkit-inner-spin-button { | |||
position: absolute; | |||
top: 0; | |||
right: 0; | |||
height: 100%; | |||
width: 1.5rem; | |||
z-index: 2; | |||
} |
@@ -1,6 +1,7 @@ | |||
import * as React from 'react'; | |||
import { TextControl } from '@tesseract-design/web-base'; | |||
import clsx from 'clsx'; | |||
import plugin from 'tailwindcss/plugin'; | |||
export type NumberSpinnerDerivedElement = HTMLInputElement; | |||
@@ -43,6 +44,21 @@ export interface NumberSpinnerProps extends Omit<React.HTMLProps<NumberSpinnerDe | |||
length?: number, | |||
} | |||
export const numberSpinnerPlugin = plugin(({ addComponents, }) => { | |||
addComponents({ | |||
'.number-spinner': { | |||
'&::-webkit-inner-spin-button': { | |||
'position': 'absolute', | |||
'top': '0', | |||
'right': '0', | |||
'height': '100%', | |||
'width': '1.5rem', | |||
'z-index': '2', | |||
}, | |||
}, | |||
}); | |||
}); | |||
/** | |||
* Component for inputting numeric values. | |||
*/ | |||
@@ -82,6 +98,34 @@ export const NumberSpinner = React.forwardRef<NumberSpinnerDerivedElement, Numbe | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
size={length} | |||
@@ -91,10 +135,10 @@ export const NumberSpinner = React.forwardRef<NumberSpinnerDerivedElement, Numbe | |||
type="number" | |||
data-testid="input" | |||
className={clsx( | |||
'bg-negative rounded-inherit w-full peer block tabular-nums font-inherit', | |||
'bg-negative rounded-inherit w-full peer block tabular-nums font-inherit relative', | |||
'focus:outline-0', | |||
'disabled:opacity-50 disabled:cursor-not-allowed', | |||
'tesseract-design-number-spinner', | |||
'number-spinner', | |||
{ | |||
'text-xxs': size === 'small', | |||
'text-xs': size === 'medium', | |||
@@ -122,31 +166,6 @@ export const NumberSpinner = React.forwardRef<NumberSpinnerDerivedElement, Numbe | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -1,157 +0,0 @@ | |||
.tesseract-design-slider-wrapper > input { | |||
appearance: none; | |||
cursor: pointer; | |||
position: relative; | |||
overflow: hidden; | |||
height: 1em; | |||
box-sizing: border-box; | |||
color: rgb(var(--color-primary)); | |||
} | |||
.tesseract-design-slider-wrapper > input::-webkit-slider-container { | |||
width: 100%; | |||
height: 100%; | |||
min-block-size: 0; | |||
background-color: rgb(var(--color-primary) / 50%); | |||
border-radius: 9999px; | |||
display: block; | |||
box-sizing: border-box; | |||
background-clip: content-box; | |||
padding: 0.25em; | |||
appearance: none; | |||
} | |||
.tesseract-design-slider-wrapper > input::-webkit-slider-runnable-track { | |||
appearance: none; | |||
border-radius: 9999px; | |||
display: block; | |||
width: 100%; | |||
height: 100%; | |||
margin: -0.25em; | |||
box-sizing: border-box; | |||
background-clip: content-box; | |||
} | |||
.tesseract-design-slider-wrapper > input::-webkit-slider-thumb { | |||
width: 1em; | |||
height: 1em; | |||
margin: -0.25em 0 0 0; | |||
border-radius: 9999px; | |||
background-color: currentColor; | |||
appearance: none; | |||
aspect-ratio: 1 / 1; | |||
z-index: 1; | |||
position: relative; | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-primary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper > input:focus::-webkit-slider-container { | |||
background-color: rgb(var(--color-secondary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper > input:active::-webkit-slider-container { | |||
background-color: rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper > input:focus::-webkit-slider-thumb { | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-secondary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper > input:active::-webkit-slider-thumb { | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper[data-orient='horizontal'] { | |||
flex-direction: column; | |||
} | |||
.tesseract-design-slider-wrapper[data-firefox] { | |||
flex-direction: column; | |||
} | |||
.tesseract-design-slider-wrapper[data-firefox='vertical'] { | |||
flex-direction: row; | |||
} | |||
.tesseract-design-slider-wrapper[data-orient='vertical'] { | |||
flex-direction: column; | |||
rotate: -90deg; | |||
translate: calc(-100% + 0.5em * 2); | |||
transform-origin: calc(100% - 0.5em) 0.5em; | |||
} | |||
.tesseract-design-slider-wrapper > input::-moz-range-track { | |||
appearance: none; | |||
border-radius: 9999px; | |||
content: ''; | |||
display: block; | |||
position: absolute; | |||
background-color: currentColor; | |||
opacity: 0.5; | |||
width: calc(100% - 0.5em); | |||
height: 50%; | |||
top: 25%; | |||
margin: -0.25em; | |||
} | |||
.tesseract-design-slider-wrapper > input::-moz-range-thumb { | |||
height: 100%; | |||
outline: 0; | |||
border: 0; | |||
border-radius: 9999px; | |||
background-color: currentColor; | |||
appearance: none; | |||
aspect-ratio: 1 / 1; | |||
z-index: 1; | |||
position: relative; | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-primary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper > input:focus::-moz-range-thumb { | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-secondary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper > input:active::-moz-range-thumb { | |||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper > input[orient='vertical'] { | |||
width: 1em; | |||
height: 16em; | |||
} | |||
.tesseract-design-slider-wrapper > input[orient='vertical']::-moz-range-track { | |||
width: 50%; | |||
height: calc(100% - 0.5em); | |||
} | |||
.tesseract-design-slider-wrapper > input[orient='vertical']::-moz-range-thumb { | |||
width: 100%; | |||
height: 1em; | |||
box-shadow: 0 100000.5em 0 100000em rgb(var(--color-primary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper > input[orient='vertical']:focus::-moz-range-thumb { | |||
box-shadow: 0 100000.5em 0 100000em rgb(var(--color-secondary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper > input[orient='vertical']:active::-moz-range-thumb { | |||
box-shadow: 0 100000.5em 0 100000em rgb(var(--color-tertiary) / 50%); | |||
} | |||
.tesseract-design-slider-wrapper[data-chrome] > input + * { | |||
padding: 0 0.5em; | |||
height: 1.5em; | |||
} | |||
.tesseract-design-slider-wrapper[data-firefox='horizontal'] > input + * { | |||
padding: 0 0.5em; | |||
height: 1.5em; | |||
} | |||
.tesseract-design-slider-wrapper[data-firefox='vertical'] > input + * { | |||
padding: 0.5em 0; | |||
width: 1.5em; | |||
} |
@@ -1,5 +1,6 @@ | |||
import * as React from 'react'; | |||
import clsx from 'clsx'; | |||
import plugin from 'tailwindcss/plugin'; | |||
const filterOptions = (children: React.ReactNode): React.ReactNode => { | |||
const childrenArray = Array.isArray(children) ? children : [children]; | |||
@@ -44,6 +45,168 @@ export interface SliderProps extends Omit<React.HTMLProps<HTMLInputElement>, 'ty | |||
length?: React.CSSProperties['width']; | |||
} | |||
export const sliderPlugin = plugin(({ addComponents }) => { | |||
addComponents({ | |||
'.slider': { | |||
'& > input': { | |||
appearance: 'none', | |||
cursor: 'pointer', | |||
position: 'relative', | |||
overflow: 'hidden', | |||
height: '1em', | |||
'box-sizing': 'border-box', | |||
color: 'rgb(var(--color-primary))', | |||
}, | |||
'& > input::-webkit-slider-container': { | |||
width: '100%', | |||
height: '100%', | |||
'min-block-size': '0', | |||
'background-color': 'rgb(var(--color-primary) / 50%)', | |||
'border-radius': '9999px', | |||
display: 'block', | |||
'box-sizing': 'border-box', | |||
'background-clip': 'content-box', | |||
padding: '0.25em', | |||
appearance: 'none', | |||
}, | |||
'& > input::-webkit-slider-runnable-track': { | |||
appearance: 'none', | |||
'border-radius': '9999px', | |||
display: 'block', | |||
width: '100%', | |||
height: '100%', | |||
margin: '-0.25em', | |||
'box-sizing': 'border-box', | |||
'background-clip': 'content-box', | |||
}, | |||
'& > input::-webkit-slider-thumb': { | |||
width: '1em', | |||
height: '1em', | |||
margin: '-0.25em 0 0 0', | |||
'border-radius': '9999px', | |||
'background-color': 'currentColor', | |||
appearance: 'none', | |||
'aspect-ratio': '1 / 1', | |||
'z-index': '1', | |||
position: 'relative', | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-primary) / 50%)', | |||
}, | |||
'& > input:focus::-webkit-slider-container': { | |||
'background-color': 'rgb(var(--color-secondary) / 50%)', | |||
}, | |||
'& > input:active::-webkit-slider-container': { | |||
'background-color': 'rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'& > input:focus::-webkit-slider-thumb': { | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-secondary) / 50%)', | |||
}, | |||
'& > input:active::-webkit-slider-thumb': { | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'&[data-orient="horizontal"]': { | |||
'flex-direction': 'column', | |||
}, | |||
'&[data-firefox]': { | |||
'flex-direction': 'column', | |||
}, | |||
'&[data-firefox="vertical"]': { | |||
'flex-direction': 'row', | |||
}, | |||
'&[data-orient="vertical"]': { | |||
'flex-direction': 'column', | |||
'rotate': '-90deg', | |||
'translate': 'calc(-100% + 0.5em * 2)', | |||
'transform-origin': 'calc(100% - 0.5em) 0.5em', | |||
}, | |||
'& > input::-moz-range-track': { | |||
appearance: 'none', | |||
'border-radius': '9999px', | |||
'content': '""', | |||
display: 'block', | |||
position: 'absolute', | |||
'background-color': 'currentColor', | |||
'opacity': '0.5', | |||
width: 'calc(100% - 0.5em)', | |||
height: '50%', | |||
top: '25%', | |||
margin: '-0.25em', | |||
}, | |||
'& > input::-moz-range-thumb': { | |||
height: '100%', | |||
outline: '0', | |||
border: '0', | |||
'border-radius': '9999px', | |||
'background-color': 'currentColor', | |||
appearance: 'none', | |||
'aspect-ratio': '1 / 1', | |||
'z-index': '1', | |||
position: 'relative', | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-primary) / 50%)', | |||
}, | |||
'& > input:focus::-moz-range-thumb': { | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-secondary) / 50%)', | |||
}, | |||
'& > input:active::-moz-range-thumb': { | |||
'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'& > input[orient="vertical"]': { | |||
width: '1em', | |||
height: '16em', | |||
}, | |||
'& > input[orient="vertical"]::-moz-range-track': { | |||
width: '50%', | |||
height: 'calc(100% - 0.5em)', | |||
}, | |||
'& > input[orient="vertical"]::-moz-range-thumb': { | |||
width: '100%', | |||
height: '1em', | |||
'box-shadow': '0 100000.5em 0 100000em rgb(var(--color-primary) / 50%)', | |||
}, | |||
'& > input[orient="vertical"]:focus::-moz-range-thumb': { | |||
'box-shadow': '0 100000.5em 0 100000em rgb(var(--color-secondary) / 50%)', | |||
}, | |||
'& > input[orient="vertical"]:active::-moz-range-thumb': { | |||
'box-shadow': '0 100000.5em 0 100000em rgb(var(--color-tertiary) / 50%)', | |||
}, | |||
'&[data-chrome] > input + *': { | |||
'padding': '0 0.5em', | |||
'height': '1.5em', | |||
}, | |||
'&[data-firefox="horizontal"] > input + *': { | |||
'padding': '0 0.5em', | |||
'height': '1.5em', | |||
}, | |||
'&[data-firefox="vertical"] > input + *': { | |||
'padding': '0.5em 0', | |||
'width': '1.5em', | |||
}, | |||
}, | |||
}); | |||
}); | |||
export const Slider = React.forwardRef<SliderDerivedElement, SliderProps>(( | |||
{ | |||
className, | |||
@@ -274,7 +437,7 @@ export const Slider = React.forwardRef<SliderDerivedElement, SliderProps>(( | |||
}} | |||
> | |||
<div | |||
className="flex tesseract-design-slider-wrapper" | |||
className="flex slider" | |||
data-orient={orient} | |||
> | |||
<input | |||
@@ -85,6 +85,34 @@ export const DateDropdown = React.forwardRef< | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
size={length} | |||
@@ -125,31 +153,6 @@ export const DateDropdown = React.forwardRef< | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -151,6 +151,9 @@ importers: | |||
clsx: | |||
specifier: ^1.2.1 | |||
version: 1.2.1 | |||
tailwindcss: | |||
specifier: 3.3.2 | |||
version: 3.3.2 | |||
devDependencies: | |||
'@testing-library/jest-dom': | |||
specifier: ^5.16.5 | |||
@@ -197,9 +200,6 @@ importers: | |||
tslib: | |||
specifier: ^2.5.0 | |||
version: 2.6.0 | |||
tsx: | |||
specifier: ^3.12.7 | |||
version: 3.12.7 | |||
typescript: | |||
specifier: ^4.9.5 | |||
version: 4.9.5 | |||
@@ -218,6 +218,9 @@ importers: | |||
color-convert: | |||
specifier: ^2.0.1 | |||
version: 2.0.1 | |||
tailwindcss: | |||
specifier: 3.3.2 | |||
version: 3.3.2 | |||
devDependencies: | |||
'@testing-library/jest-dom': | |||
specifier: ^5.16.5 | |||
@@ -261,9 +264,6 @@ importers: | |||
tslib: | |||
specifier: ^2.5.0 | |||
version: 2.6.0 | |||
tsx: | |||
specifier: ^3.12.7 | |||
version: 3.12.7 | |||
typescript: | |||
specifier: ^4.9.5 | |||
version: 4.9.5 | |||
@@ -462,6 +462,9 @@ importers: | |||
react-tag-input-component: | |||
specifier: ^2.0.2 | |||
version: 2.0.2(react-dom@18.2.0)(react@18.2.0) | |||
tailwindcss: | |||
specifier: 3.3.2 | |||
version: 3.3.2 | |||
devDependencies: | |||
'@testing-library/jest-dom': | |||
specifier: ^5.16.5 | |||
@@ -508,9 +511,6 @@ importers: | |||
tslib: | |||
specifier: ^2.5.0 | |||
version: 2.6.0 | |||
tsx: | |||
specifier: ^3.12.7 | |||
version: 3.12.7 | |||
typescript: | |||
specifier: ^4.9.5 | |||
version: 4.9.5 | |||
@@ -587,6 +587,9 @@ importers: | |||
clsx: | |||
specifier: ^1.2.1 | |||
version: 1.2.1 | |||
tailwindcss: | |||
specifier: 3.3.2 | |||
version: 3.3.2 | |||
devDependencies: | |||
'@testing-library/jest-dom': | |||
specifier: ^5.16.5 | |||
@@ -633,9 +636,6 @@ importers: | |||
tslib: | |||
specifier: ^2.5.0 | |||
version: 2.6.0 | |||
tsx: | |||
specifier: ^3.12.7 | |||
version: 3.12.7 | |||
typescript: | |||
specifier: ^4.9.5 | |||
version: 4.9.5 | |||
@@ -103,6 +103,34 @@ export const TimeSpinner = React.forwardRef< | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
ref={forwardedRef} | |||
@@ -143,31 +171,6 @@ export const TimeSpinner = React.forwardRef< | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -82,6 +82,34 @@ export const WeekInput = React.forwardRef< | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
ref={forwardedRef} | |||
@@ -121,31 +149,6 @@ export const WeekInput = React.forwardRef< | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -82,6 +82,34 @@ export const YearMonthInput = React.forwardRef< | |||
style={style} | |||
data-testid="base" | |||
> | |||
{label && ( | |||
<> | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
{' '} | |||
</> | |||
)} | |||
<input | |||
{...etcProps} | |||
ref={forwardedRef} | |||
@@ -121,31 +149,6 @@ export const YearMonthInput = React.forwardRef< | |||
}, | |||
)} | |||
/> | |||
{label && ( | |||
<label | |||
data-testid="label" | |||
id={labelId} | |||
htmlFor={id} | |||
className={clsx( | |||
'absolute z-[1] w-full top-0.5 left-0 pointer-events-none pl-1 text-xxs font-bold peer-disabled:opacity-50 peer-focus:text-secondary text-primary leading-none bg-negative select-none', | |||
{ | |||
'sr-only': hiddenLabel, | |||
}, | |||
{ | |||
'pr-1': !indicator, | |||
}, | |||
{ | |||
'pr-10': indicator && size === 'small', | |||
'pr-12': indicator && size === 'medium', | |||
'pr-16': indicator && size === 'large', | |||
}, | |||
)} | |||
> | |||
<span className="block w-full whitespace-nowrap h-[1.1em] overflow-hidden text-ellipsis"> | |||
{label} | |||
</span> | |||
</label> | |||
)} | |||
{hint && ( | |||
<div | |||
data-testid="hint" | |||
@@ -1,22 +1,6 @@ | |||
import '@/styles/globals.css' | |||
import '@/styles/kitchen-sink.css' | |||
import '@tesseract-design/web-choice-react/dist/DropdownSelect.css' | |||
import '@tesseract-design/web-choice-react/dist/MenuSelect.css' | |||
import '@tesseract-design/web-choice-react/dist/RadioButton.css' | |||
import '@tesseract-design/web-choice-react/dist/RadioTickBox.css' | |||
import '@tesseract-design/web-color-react/dist/ColorPicker.css' | |||
import '@tesseract-design/web-multichoice-react/dist/MenuMultiSelect.css' | |||
import '@tesseract-design/web-multichoice-react/dist/TagInput.css' | |||
import '@tesseract-design/web-multichoice-react/dist/ToggleButton.css' | |||
import '@tesseract-design/web-multichoice-react/dist/ToggleSwitch.css' | |||
import '@tesseract-design/web-multichoice-react/dist/ToggleTickBox.css' | |||
import '@tesseract-design/web-number-react/dist/NumberSpinner.css' | |||
import '@tesseract-design/web-number-react/dist/Slider.css' | |||
import '@modal-sh/react-refractor/dist/Refractor.css' | |||
import type { AppProps } from 'next/app' | |||
@@ -38,6 +38,23 @@ const ColorPage: NextPage = () => { | |||
defaultValue="#0000ff" | |||
/> | |||
</Subsection> | |||
<Subsection title="Disabled"> | |||
<Color.ColorPicker | |||
size="small" | |||
defaultValue="#ff0000" | |||
disabled | |||
/> | |||
<Color.ColorPicker | |||
size="medium" | |||
defaultValue="#00ff00" | |||
disabled | |||
/> | |||
<Color.ColorPicker | |||
size="large" | |||
defaultValue="#0000ff" | |||
disabled | |||
/> | |||
</Subsection> | |||
</Section> | |||
</DefaultLayout> | |||
) | |||
@@ -29,7 +29,7 @@ const OptionPage: NextPage<Props> = ({ | |||
<DefaultLayout | |||
title="Option" | |||
> | |||
<main className="mt-8 mb-16 md:mt-16 md:mb-32"> | |||
<div className="mt-8 mb-16 md:mt-16 md:mb-32"> | |||
<section> | |||
<div className="container mx-auto px-4"> | |||
<h1> | |||
@@ -1655,7 +1655,7 @@ const OptionPage: NextPage<Props> = ({ | |||
</div> | |||
</div> | |||
</section> | |||
</main> | |||
</div> | |||
</DefaultLayout> | |||
); | |||
}; | |||
@@ -1,4 +1,5 @@ | |||
@tailwind base; | |||
@tailwind components; | |||
@tailwind utilities; | |||
@layer base { | |||
@@ -1,4 +1,24 @@ | |||
const defaultTheme = require('tailwindcss/defaultTheme') | |||
const { | |||
dropdownSelectPlugin, | |||
menuSelectPlugin, | |||
radioButtonPlugin, | |||
radioTickBoxPlugin, | |||
} = require('@tesseract-design/web-choice-react'); | |||
const { | |||
colorPickerPlugin, | |||
} = require('@tesseract-design/web-color-react'); | |||
const { | |||
menuMultiSelectPlugin, | |||
tagInputPlugin, | |||
toggleButtonPlugin, | |||
toggleSwitchPlugin, | |||
toggleTickBoxPlugin, | |||
} = require('@tesseract-design/web-multichoice-react'); | |||
const { | |||
numberSpinnerPlugin, | |||
sliderPlugin, | |||
} = require('@tesseract-design/web-number-react'); | |||
/** @type {import('tailwindcss').Config} */ | |||
module.exports = { | |||
@@ -6,7 +26,7 @@ module.exports = { | |||
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}', | |||
'./src/components/**/*.{js,ts,jsx,tsx,mdx}', | |||
'./src/categories/**/*.{js,ts,jsx,tsx,mdx}', | |||
'./node_modules/@tesseract-design/web-*-react/dist/**/*.js', | |||
'./node_modules/@tesseract-design/web-*-react/dist/**/*.js', // catch-all, can use individual packages | |||
], | |||
theme: { | |||
fontFamily: { | |||
@@ -72,5 +92,18 @@ module.exports = { | |||
}, | |||
}, | |||
}, | |||
plugins: [], | |||
plugins: [ | |||
colorPickerPlugin, | |||
dropdownSelectPlugin, | |||
menuMultiSelectPlugin, | |||
menuSelectPlugin, | |||
numberSpinnerPlugin, | |||
radioButtonPlugin, | |||
radioTickBoxPlugin, | |||
sliderPlugin, | |||
tagInputPlugin, | |||
toggleButtonPlugin, | |||
toggleSwitchPlugin, | |||
toggleTickBoxPlugin, | |||
], | |||
} |