Style sliders and add active indicators for interactable componentspull/1/head
@@ -6,11 +6,13 @@ import { | |||||
formatSecondsDurationConcise, | formatSecondsDurationConcise, | ||||
formatSecondsDurationPrecise, | formatSecondsDurationPrecise, | ||||
} from '@/utils/numeral'; | } from '@/utils/numeral'; | ||||
import theme from '@/styles/theme'; | |||||
import {useMediaControls} from '../../hooks/interactive'; | import {useMediaControls} from '../../hooks/interactive'; | ||||
import {useAugmentedFile} from '@/categories/blob/react'; | import {useAugmentedFile} from '@/categories/blob/react'; | ||||
import clsx from 'clsx'; | import clsx from 'clsx'; | ||||
import {WaveSurferCanvas} from '@/packages/react-wavesurfer'; | import {WaveSurferCanvas} from '@/packages/react-wavesurfer'; | ||||
import {Slider} from '@/categories/number/react'; | |||||
type AudioFilePreviewDerivedComponent = HTMLAudioElement; | type AudioFilePreviewDerivedComponent = HTMLAudioElement; | ||||
@@ -99,53 +101,59 @@ export const AudioFilePreview = React.forwardRef<AudioFilePreviewDerivedComponen | |||||
</audio> | </audio> | ||||
{visualizationMode === 'waveform' && ( | {visualizationMode === 'waveform' && ( | ||||
<WaveSurferCanvas | <WaveSurferCanvas | ||||
className="sm:absolute w-full sm:h-full top-0 left-0 block object-center object-contain flex-auto aspect-video sm:aspect-auto bg-[#000000]" | |||||
className="sm:absolute w-full sm:h-full top-0 left-0 block object-center object-contain flex-auto aspect-video sm:aspect-auto bg-primary/10" | |||||
ref={mediaControllerRef} | ref={mediaControllerRef} | ||||
data-testid="preview" | data-testid="preview" | ||||
barWidth={1} | barWidth={1} | ||||
barGap={1} | barGap={1} | ||||
waveColor="rgb(199 138 179)" | |||||
progressColor="rgb(255 153 0)" | |||||
waveColor={`rgb(${theme.primary.split(' ').map((c) => Math.floor(Number(c) / 2)).join(' ')})`} | |||||
progressColor={`rgb(${theme.primary})`} | |||||
interact | interact | ||||
/> | /> | ||||
)} | )} | ||||
<div className="flex gap-4 absolute top-0 right-0 z-[2] px-4"> | <div className="flex gap-4 absolute top-0 right-0 z-[2] px-4"> | ||||
<label | <label | ||||
className={clsx( | className={clsx( | ||||
'h-12 flex text-primary disabled:text-primary focus:text-secondary active:text-tertiary items-center justify-center leading-none gap-4 select-none', | |||||
'focus:outline-0', | |||||
'disabled:opacity-50 disabled:cursor-not-allowed', | |||||
'h-12 flex items-center justify-center leading-none gap-4 select-none', | |||||
)} | )} | ||||
> | > | ||||
<input | <input | ||||
type="radio" | type="radio" | ||||
name="visualizationMode" | name="visualizationMode" | ||||
value="waveform" | value="waveform" | ||||
className="sr-only" | |||||
className="sr-only peer/waveform" | |||||
onChange={handleVisualizationModeChange} | onChange={handleVisualizationModeChange} | ||||
/> | /> | ||||
<span | <span | ||||
className="block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded" | |||||
className={clsx( | |||||
'block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded text-primary', | |||||
'peer-focus/waveform:text-secondary', | |||||
'peer-active/waveform:text-tertiary', | |||||
'peer-disabled/waveform:text-primary peer-disabled/waveform:cursor-not-allowed peer-disabled/waveform:opacity-50', | |||||
)} | |||||
> | > | ||||
Waveform | Waveform | ||||
</span> | </span> | ||||
</label> | </label> | ||||
<label | <label | ||||
className={clsx( | className={clsx( | ||||
'h-12 flex text-primary disabled:text-primary focus:text-secondary active:text-tertiary items-center justify-center leading-none gap-4 select-none', | |||||
'focus:outline-0', | |||||
'disabled:opacity-50 disabled:cursor-not-allowed', | |||||
'h-12 flex items-center justify-center leading-none gap-4 select-none', | |||||
)} | )} | ||||
> | > | ||||
<input | <input | ||||
type="radio" | type="radio" | ||||
name="visualizationMode" | name="visualizationMode" | ||||
value="spectrum" | value="spectrum" | ||||
className="sr-only" | |||||
className="sr-only peer/waveform" | |||||
onChange={handleVisualizationModeChange} | onChange={handleVisualizationModeChange} | ||||
/> | /> | ||||
<span | <span | ||||
className="block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded" | |||||
className={clsx( | |||||
'block uppercase font-bold h-[1.1em] w-full whitespace-nowrap overflow-hidden text-ellipsis font-semi-expanded text-primary', | |||||
'peer-focus/waveform:text-secondary', | |||||
'peer-active/waveform:text-tertiary', | |||||
'peer-disabled/waveform:text-primary peer-disabled/waveform:cursor-not-allowed peer-disabled/waveform:opacity-50', | |||||
)} | |||||
> | > | ||||
Spectrum | Spectrum | ||||
</span> | </span> | ||||
@@ -153,19 +161,59 @@ export const AudioFilePreview = React.forwardRef<AudioFilePreviewDerivedComponen | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{enhanced && ( | {enhanced && ( | ||||
<div className="w-full flex-shrink-0 h-10 flex gap-4 relative"> | |||||
<div className="w-full flex-shrink-0 h-10 flex gap-4 items-center"> | |||||
<button | <button | ||||
className="w-10 h-full flex-shrink-0 text-primary" | |||||
className={clsx( | |||||
'w-10 h-full flex-shrink-0 text-primary flex items-center justify-center', | |||||
'focus:text-secondary focus:outline-0', | |||||
'active:text-tertiary', | |||||
'disabled:text-primary disabled:cursor-not-allowed disabled:opacity-50', | |||||
)} | |||||
type="submit" | type="submit" | ||||
name="action" | name="action" | ||||
value="togglePlayback" | value="togglePlayback" | ||||
form={formId} | form={formId} | ||||
> | > | ||||
{isPlaying ? '⏸' : '▶'} | |||||
{ | |||||
isPlaying | |||||
? ( | |||||
<svg | |||||
aria-label="Pause" | |||||
viewBox="0 0 24 24" | |||||
className="w-6 h-6 fill-none stroke-current stroke-2" | |||||
strokeLinecap="round" | |||||
strokeLinejoin="round" | |||||
> | |||||
<rect | |||||
x="6" | |||||
y="4" | |||||
width="4" | |||||
height="16" | |||||
/> | |||||
<rect | |||||
x="14" | |||||
y="4" | |||||
width="4" | |||||
height="16" | |||||
/> | |||||
</svg> | |||||
) | |||||
: ( | |||||
<svg | |||||
aria-label="Play" | |||||
viewBox="0 0 24 24" | |||||
className="w-6 h-6 fill-none stroke-current stroke-2" | |||||
strokeLinecap="round" | |||||
strokeLinejoin="round" | |||||
> | |||||
<polygon points="5 3 19 12 5 21 5 3" /> | |||||
</svg> | |||||
) | |||||
} | |||||
</button> | </button> | ||||
<div className="flex-auto w-full flex items-center gap-2 text-sm relative"> | <div className="flex-auto w-full flex items-center gap-2 text-sm relative"> | ||||
<button | <button | ||||
className="absolute overflow-hidden w-12 opacity-0 h-10" | |||||
className="absolute overflow-hidden w-12 opacity-0 h-10 peer/seek" | |||||
title="Toggle Seek Time Count Mode" | title="Toggle Seek Time Count Mode" | ||||
type="submit" | type="submit" | ||||
name="action" | name="action" | ||||
@@ -174,8 +222,13 @@ export const AudioFilePreview = React.forwardRef<AudioFilePreviewDerivedComponen | |||||
> | > | ||||
Toggle Seek Time Count Mode | Toggle Seek Time Count Mode | ||||
</button> | </button> | ||||
<span | |||||
className="before:block before:content-[attr(title)] contents tabular-nums" | |||||
<div | |||||
className={clsx( | |||||
'before:block before:content-[attr(title)] contents tabular-nums flex-auto text-primary font-bold', | |||||
'peer-focus/seek:text-secondary peer-focus/seek:outline-0', | |||||
'peer-active/seek:text-tertiary', | |||||
'peer-disabled/seek:text-primary \'peer-disabled/seek:cursor-not-allowed \'peer-disabled/seek:opacity-50' | |||||
)} | |||||
title={ | title={ | ||||
`${ | `${ | ||||
isSeekTimeCountingDown ? '−' : '+' | isSeekTimeCountingDown ? '−' : '+' | ||||
@@ -186,9 +239,8 @@ export const AudioFilePreview = React.forwardRef<AudioFilePreviewDerivedComponen | |||||
}` | }` | ||||
} | } | ||||
> | > | ||||
<input | |||||
type="range" | |||||
className="flex-auto w-full tabular-nums" | |||||
<Slider | |||||
className="w-full bg-negative text-base" | |||||
ref={seekRef} | ref={seekRef} | ||||
onMouseDown={startSeek} | onMouseDown={startSeek} | ||||
onMouseUp={endSeek} | onMouseUp={endSeek} | ||||
@@ -196,13 +248,12 @@ export const AudioFilePreview = React.forwardRef<AudioFilePreviewDerivedComponen | |||||
defaultValue="0" | defaultValue="0" | ||||
step="any" | step="any" | ||||
/> | /> | ||||
</span> | |||||
<span> | |||||
</div> | |||||
<span className="tabular-nums font-bold"> | |||||
{formatSecondsDurationConcise(durationDisplay)} | {formatSecondsDurationConcise(durationDisplay)} | ||||
</span> | </span> | ||||
</div> | </div> | ||||
<input | |||||
type="range" | |||||
<Slider | |||||
ref={volumeRef} | ref={volumeRef} | ||||
max={1} | max={1} | ||||
min={0} | min={0} | ||||
@@ -3,6 +3,7 @@ import {augmentVideoFile, getMimeTypeDescription} from '@/utils/blob'; | |||||
import {formatFileSize, formatNumeral, formatSecondsDurationConcise} from '@/utils/numeral'; | import {formatFileSize, formatNumeral, formatSecondsDurationConcise} from '@/utils/numeral'; | ||||
import {useAugmentedFile, useMediaControls} from '@tesseract-design/web-blob-react'; | import {useAugmentedFile, useMediaControls} from '@tesseract-design/web-blob-react'; | ||||
import clsx from 'clsx'; | import clsx from 'clsx'; | ||||
import {Slider} from '@tesseract-design/web-number-react'; | |||||
type VideoFilePreviewDerivedComponent = HTMLVideoElement; | type VideoFilePreviewDerivedComponent = HTMLVideoElement; | ||||
@@ -72,37 +73,91 @@ export const VideoFilePreview = React.forwardRef<VideoFilePreviewDerivedComponen | |||||
data-testid="preview" | data-testid="preview" | ||||
> | > | ||||
<div className="w-full flex-auto relative"> | <div className="w-full flex-auto relative"> | ||||
<video | |||||
{...etcProps} | |||||
className="sm:absolute w-full sm:h-full top-0 left-0 block object-center object-contain flex-auto aspect-video sm:aspect-auto bg-[#000000]" | |||||
ref={mediaControllerRef} | |||||
onLoadedMetadata={refreshControls} | |||||
onDurationChange={refreshControls} | |||||
onEnded={reset} | |||||
onTimeUpdate={updateSeekFromPlayback} | |||||
data-testid="preview" | |||||
controls={!enhanced} | |||||
> | |||||
<source | |||||
src={augmentedFile.metadata.previewUrl} | |||||
type={augmentedFile.type} | |||||
/> | |||||
</video> | |||||
<video | |||||
{...etcProps} | |||||
className="sm:absolute w-full sm:h-full top-0 left-0 block object-center object-contain flex-auto aspect-video sm:aspect-auto bg-primary/10" | |||||
ref={mediaControllerRef} | |||||
onLoadedMetadata={refreshControls} | |||||
onDurationChange={refreshControls} | |||||
onEnded={reset} | |||||
onTimeUpdate={updateSeekFromPlayback} | |||||
data-testid="preview" | |||||
controls={!enhanced} | |||||
> | |||||
<source | |||||
src={augmentedFile.metadata.previewUrl} | |||||
type={augmentedFile.type} | |||||
/> | |||||
</video> | |||||
<button | |||||
className="absolute w-full h-full top-0 left-0" | |||||
type="submit" | |||||
name="action" | |||||
value="togglePlayback" | |||||
form={formId} | |||||
tabIndex={-1} | |||||
> | |||||
<span className="sr-only"> | |||||
{isPlaying ? 'Pause' : 'Play'} | |||||
</span> | |||||
</button> | |||||
</div> | </div> | ||||
{enhanced && ( | {enhanced && ( | ||||
<div className="w-full flex-shrink-0 h-10 flex gap-4"> | |||||
<div className="w-full flex-shrink-0 h-10 flex gap-4 items-center"> | |||||
<button | <button | ||||
className="w-10 h-full flex-shrink-0 text-primary" | |||||
className={ | |||||
clsx( | |||||
'w-10 h-full flex-shrink-0 text-primary flex items-center justify-center', | |||||
'focus:text-secondary focus:outline-0', | |||||
'active:text-tertiary', | |||||
'disabled:text-primary disabled:cursor-not-allowed disabled:opacity-50' | |||||
) | |||||
} | |||||
type="submit" | type="submit" | ||||
name="action" | name="action" | ||||
value="togglePlayback" | value="togglePlayback" | ||||
form={formId} | form={formId} | ||||
> | > | ||||
{isPlaying ? '⏸' : '▶'} | |||||
{ | |||||
isPlaying | |||||
? ( | |||||
<svg | |||||
aria-label="Pause" | |||||
viewBox="0 0 24 24" | |||||
className="w-6 h-6 fill-none stroke-current stroke-2" | |||||
strokeLinecap="round" | |||||
strokeLinejoin="round" | |||||
> | |||||
<rect | |||||
x="6" | |||||
y="4" | |||||
width="4" | |||||
height="16" | |||||
/> | |||||
<rect | |||||
x="14" | |||||
y="4" | |||||
width="4" | |||||
height="16" | |||||
/> | |||||
</svg> | |||||
) | |||||
: ( | |||||
<svg | |||||
aria-label="Play" | |||||
viewBox="0 0 24 24" | |||||
className="w-6 h-6 fill-none stroke-current stroke-2" | |||||
strokeLinecap="round" | |||||
strokeLinejoin="round" | |||||
> | |||||
<polygon points="5 3 19 12 5 21 5 3" /> | |||||
</svg> | |||||
) | |||||
} | |||||
</button> | </button> | ||||
<div className="flex-auto w-full flex items-center gap-2 text-sm relative"> | <div className="flex-auto w-full flex items-center gap-2 text-sm relative"> | ||||
<button | <button | ||||
className="absolute overflow-hidden w-12 opacity-0 h-10" | |||||
className="absolute overflow-hidden w-12 opacity-0 h-10 peer/seek" | |||||
title="Toggle Seek Time Count Mode" | title="Toggle Seek Time Count Mode" | ||||
type="submit" | type="submit" | ||||
name="action" | name="action" | ||||
@@ -111,8 +166,13 @@ export const VideoFilePreview = React.forwardRef<VideoFilePreviewDerivedComponen | |||||
> | > | ||||
Toggle Seek Time Count Mode | Toggle Seek Time Count Mode | ||||
</button> | </button> | ||||
<span | |||||
className="before:block before:content-[attr(title)] contents tabular-nums" | |||||
<div | |||||
className={clsx( | |||||
'before:block before:content-[attr(title)] contents tabular-nums flex-auto text-primary font-bold', | |||||
'peer-focus/seek:text-secondary peer-focus/seek:outline-0', | |||||
'peer-active/seek:text-tertiary', | |||||
'peer-disabled/seek:text-primary \'peer-disabled/seek:cursor-not-allowed \'peer-disabled/seek:opacity-50' | |||||
)} | |||||
title={ | title={ | ||||
`${ | `${ | ||||
isSeekTimeCountingDown ? '−' : '+' | isSeekTimeCountingDown ? '−' : '+' | ||||
@@ -123,9 +183,8 @@ export const VideoFilePreview = React.forwardRef<VideoFilePreviewDerivedComponen | |||||
}` | }` | ||||
} | } | ||||
> | > | ||||
<input | |||||
type="range" | |||||
className="flex-auto w-full tabular-nums" | |||||
<Slider | |||||
className="w-full bg-negative text-base" | |||||
ref={seekRef} | ref={seekRef} | ||||
onMouseDown={startSeek} | onMouseDown={startSeek} | ||||
onMouseUp={endSeek} | onMouseUp={endSeek} | ||||
@@ -133,13 +192,12 @@ export const VideoFilePreview = React.forwardRef<VideoFilePreviewDerivedComponen | |||||
defaultValue="0" | defaultValue="0" | ||||
step="any" | step="any" | ||||
/> | /> | ||||
</div> | |||||
<span className="tabular-nums font-bold"> | |||||
{formatSecondsDurationConcise(durationDisplay)} | |||||
</span> | </span> | ||||
<span> | |||||
{formatSecondsDurationConcise(durationDisplay)} | |||||
</span> | |||||
</div> | </div> | ||||
<input | |||||
type="range" | |||||
<Slider | |||||
ref={volumeRef} | ref={volumeRef} | ||||
max={1} | max={1} | ||||
min={0} | min={0} | ||||
@@ -0,0 +1,36 @@ | |||||
import * as React from 'react'; | |||||
import clsx from 'clsx'; | |||||
type SliderDerivedComponent = HTMLInputElement; | |||||
export interface SliderProps extends Omit<React.HTMLProps<HTMLInputElement>, 'type'> { | |||||
} | |||||
export const Slider = React.forwardRef<SliderDerivedComponent, SliderProps>(({ | |||||
className, | |||||
style, | |||||
...etcProps | |||||
}, forwardedRef) => { | |||||
return ( | |||||
<div | |||||
className={clsx( | |||||
className, | |||||
)} | |||||
style={style} | |||||
> | |||||
<input | |||||
{...etcProps} | |||||
ref={forwardedRef} | |||||
type="range" | |||||
className={clsx( | |||||
'w-full h-full bg-inherit slider block text-primary ring-secondary/50', | |||||
'focus:text-secondary focus:outline-0 focus:ring-4', | |||||
'active:text-tertiary active:ring-tertiary/50', | |||||
)} | |||||
/> | |||||
</div> | |||||
) | |||||
}); | |||||
Slider.displayName = 'Slider'; |
@@ -0,0 +1 @@ | |||||
export * from './components/Slider'; |
@@ -1,9 +1,14 @@ | |||||
import { Html, Head, Main, NextScript } from 'next/document' | import { Html, Head, Main, NextScript } from 'next/document' | ||||
import theme from '@/styles/theme' | |||||
export default function Document() { | export default function Document() { | ||||
return ( | return ( | ||||
<Html lang="en" className="bg-negative text-positive"> | <Html lang="en" className="bg-negative text-positive"> | ||||
<Head /> | |||||
<Head> | |||||
<style> | |||||
{`:root{${Object.entries(theme).map(([key, value]) => `--color-${key}: ${value};`).join('')}}`} | |||||
</style> | |||||
</Head> | |||||
<body> | <body> | ||||
<Main /> | <Main /> | ||||
<NextScript /> | <NextScript /> | ||||
@@ -1,41 +1,72 @@ | |||||
@tailwind base; | @tailwind base; | ||||
@tailwind utilities; | @tailwind utilities; | ||||
@layer base { | |||||
:root { | |||||
--color-shade: 0 0 0; | |||||
--color-negative: 34 34 34; | |||||
--color-positive: 238 238 238; | |||||
--color-primary: 199 138 179; | |||||
--color-secondary: 255 153 0; | |||||
--color-tertiary: 215 95 75; | |||||
--color-code-number: 116 249 94; | |||||
--color-code-keyword: 255 67 137; | |||||
--color-code-type: 80 151 210; | |||||
--color-code-instance-attribute: 118 167 210; | |||||
--color-code-function: 103 194 82; | |||||
--color-code-parameter: 145 94 194; | |||||
--color-code-property: 255 161 201; | |||||
--color-code-string: 238 211 113; | |||||
--color-code-variable: 139 194 117; | |||||
--color-code-regexp: 116 167 43; | |||||
--color-code-url: 0 153 204; | |||||
--color-code-global: 194 128 80; | |||||
@layer utilities { | |||||
.font-condensed { | |||||
font-stretch: condensed; | |||||
} | } | ||||
.font-semi-condensed { | |||||
font-stretch: semi-condensed; | |||||
} | |||||
.font-expanded { | |||||
font-stretch: expanded; | |||||
} | |||||
.font-semi-expanded { | |||||
font-stretch: semi-expanded; | |||||
} | |||||
} | |||||
.slider { | |||||
@apply rounded-full; | |||||
appearance: none; | |||||
cursor: pointer; | |||||
position: relative; | |||||
overflow: hidden; | |||||
height: 1em; | |||||
color: rgb(var(--color-primary)); | |||||
} | |||||
.slider::before { | |||||
@apply rounded-full; | |||||
content: ''; | |||||
display: block; | |||||
position: absolute; | |||||
background-color: currentColor; | |||||
opacity: 0.5; | |||||
width: 100%; | |||||
height: 50%; | |||||
top: 25%; | |||||
} | |||||
.slider::-webkit-slider-container { | |||||
height: 100%; | |||||
overflow: hidden; | |||||
box-sizing: border-box; | |||||
} | } | ||||
.font-condensed { | |||||
font-stretch: condensed; | |||||
.slider::-webkit-slider-runnable-track { | |||||
appearance: none; | |||||
height: 100%; | |||||
} | } | ||||
.font-semi-condensed { | |||||
font-stretch: semi-condensed; | |||||
.slider::-webkit-slider-thumb { | |||||
@apply rounded-full; | |||||
background-color: currentColor; | |||||
appearance: none; | |||||
height: 100%; | |||||
aspect-ratio: 1 / 1; | |||||
z-index: 1; | |||||
position: relative; | |||||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-primary) / 50%); | |||||
} | } | ||||
.font-expanded { | |||||
font-stretch: expanded; | |||||
.slider:focus::-webkit-slider-thumb { | |||||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-secondary) / 50%); | |||||
} | } | ||||
.font-semi-expanded { | |||||
font-stretch: semi-expanded; | |||||
.slider:active::-webkit-slider-thumb { | |||||
box-shadow: -100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%); | |||||
} | } |
@@ -0,0 +1,22 @@ | |||||
const theme = { | |||||
"shade": "0 0 0", | |||||
"negative": "34 34 34", | |||||
"positive": "238 238 238", | |||||
"primary": "199 138 179", | |||||
"secondary": "255 153 0", | |||||
"tertiary": "215 95 75", | |||||
"code-number": "116 249 94", | |||||
"code-keyword": "255 67 137", | |||||
"code-type": "80 151 210", | |||||
"code-instance-attribute": "118 167 210", | |||||
"code-function": "103 194 82", | |||||
"code-parameter": "145 94 194", | |||||
"code-property": "255 161 201", | |||||
"code-string": "238 211 113", | |||||
"code-variable": "139 194 117", | |||||
"code-regexp": "116 167 43", | |||||
"code-url": "0 153 204", | |||||
"code-global": "194 128 80" | |||||
} as const; | |||||
export default theme; |
@@ -1,3 +1,5 @@ | |||||
const defaultTheme = require('tailwindcss/defaultTheme') | |||||
/** @type {import('tailwindcss').Config} */ | /** @type {import('tailwindcss').Config} */ | ||||
module.exports = { | module.exports = { | ||||
content: [ | content: [ | ||||
@@ -7,7 +9,8 @@ module.exports = { | |||||
], | ], | ||||
theme: { | theme: { | ||||
fontFamily: { | fontFamily: { | ||||
sans: ['Encode Sans Semi Expanded', 'Encode Sans', 'sans-serif'], | |||||
sans: ['Encode Sans', ...defaultTheme.fontFamily.sans], | |||||
mono: ['MonoLisa', 'mononoki', ...defaultTheme.fontFamily.mono], | |||||
}, | }, | ||||
colors: { | colors: { | ||||
'shade': 'rgb(var(--color-shade))', | 'shade': 'rgb(var(--color-shade))', | ||||
@@ -16,6 +16,7 @@ | |||||
"incremental": true, | "incremental": true, | ||||
"paths": { | "paths": { | ||||
"@/*": ["./src/*"], | "@/*": ["./src/*"], | ||||
"tailwind.config": ["./tailwind.config.js"], | |||||
"@tesseract-design/web-base-button": ["./src/base/button"], | "@tesseract-design/web-base-button": ["./src/base/button"], | ||||
"@tesseract-design/web-base-selectcontrol": ["./src/base/selectcontrol"], | "@tesseract-design/web-base-selectcontrol": ["./src/base/selectcontrol"], | ||||
"@tesseract-design/web-base-textcontrol": ["./src/base/textcontrol"], | "@tesseract-design/web-base-textcontrol": ["./src/base/textcontrol"], | ||||
@@ -24,6 +25,7 @@ | |||||
"@tesseract-design/web-freeform-react": ["./src/categories/freeform/react"], | "@tesseract-design/web-freeform-react": ["./src/categories/freeform/react"], | ||||
"@tesseract-design/web-information-react": ["./src/categories/information/react"], | "@tesseract-design/web-information-react": ["./src/categories/information/react"], | ||||
"@tesseract-design/web-option-react": ["./src/categories/option/react"], | "@tesseract-design/web-option-react": ["./src/categories/option/react"], | ||||
"@tesseract-design/web-number-react": ["./src/categories/number/react"], | |||||
"@tesseract-design/web-navigation-react": ["./src/categories/navigation/react"], | "@tesseract-design/web-navigation-react": ["./src/categories/navigation/react"], | ||||
} | } | ||||
}, | }, | ||||