@@ -0,0 +1,9 @@ | |||||
# tesseract | |||||
Simple, accessible, and robust Web components for data-driven documents and apps. | |||||
Tesseract supports the following frameworks: | |||||
- [React](/web/react) | |||||
- [Vue](/web/vue) (TODO) | |||||
- [Solid](/web/solid) (TODO) |
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -2,6 +2,10 @@ import * as React from 'react'; | |||||
import { useClientSide, useFallbackId, useProxyInput } from '@modal-sh/react-utils'; | import { useClientSide, useFallbackId, useProxyInput } from '@modal-sh/react-utils'; | ||||
import clsx from 'clsx'; | import clsx from 'clsx'; | ||||
/** | |||||
* Common props for the {@link FileSelectBoxProps.previewComponent|previewComponent prop} of the | |||||
* {@link FileSelectBox} component. | |||||
*/ | |||||
export interface CommonPreviewComponentProps<F extends Partial<File> = Partial<File>> { | export interface CommonPreviewComponentProps<F extends Partial<File> = Partial<File>> { | ||||
/** | /** | ||||
* The file to preview. | * The file to preview. | ||||
@@ -21,8 +25,14 @@ export interface CommonPreviewComponentProps<F extends Partial<File> = Partial<F | |||||
mini?: boolean; | mini?: boolean; | ||||
} | } | ||||
/** | |||||
* Derived HTML element of the {@link FileSelectBox} component. | |||||
*/ | |||||
export type FileSelectBoxDerivedElement = HTMLInputElement; | export type FileSelectBoxDerivedElement = HTMLInputElement; | ||||
/** | |||||
* Props of the {@link FileSelectBox} component. | |||||
*/ | |||||
export interface FileSelectBoxProps< | export interface FileSelectBoxProps< | ||||
F extends Partial<File> = Partial<File>, | F extends Partial<File> = Partial<File>, | ||||
P extends CommonPreviewComponentProps<F> = CommonPreviewComponentProps<F> | P extends CommonPreviewComponentProps<F> = CommonPreviewComponentProps<F> | ||||
@@ -57,6 +67,10 @@ export interface FileSelectBoxProps< | |||||
previewComponent?: React.ElementType<P>, | previewComponent?: React.ElementType<P>, | ||||
} | } | ||||
/** | |||||
* Default component for the {@link FileSelectBoxProps.previewComponent|previewComponent prop} | |||||
* of the {@link FileSelectBox} component. | |||||
*/ | |||||
export const FileSelectBoxDefaultPreviewComponent = React.forwardRef< | export const FileSelectBoxDefaultPreviewComponent = React.forwardRef< | ||||
HTMLDivElement, | HTMLDivElement, | ||||
CommonPreviewComponentProps | CommonPreviewComponentProps | ||||
@@ -113,6 +127,9 @@ export const FileSelectBoxDefaultPreviewComponent = React.forwardRef< | |||||
</div> | </div> | ||||
)); | )); | ||||
/** | |||||
* Component for selecting files. | |||||
*/ | |||||
export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileSelectBoxProps>(( | export const FileSelectBox = React.forwardRef<FileSelectBoxDerivedElement, FileSelectBoxProps>(( | ||||
{ | { | ||||
label = '', | label = '', | ||||
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -2,8 +2,14 @@ import * as React from 'react'; | |||||
import clsx from 'clsx'; | import clsx from 'clsx'; | ||||
import plugin from 'tailwindcss/plugin'; | import plugin from 'tailwindcss/plugin'; | ||||
/** | |||||
* Derived HTML element of the {@link ColorPicker} component. | |||||
*/ | |||||
export type ColorPickerDerivedElement = HTMLInputElement; | export type ColorPickerDerivedElement = HTMLInputElement; | ||||
/** | |||||
* Props of the {@link ColorPicker} component. | |||||
*/ | |||||
export interface ColorPickerProps extends Omit<React.HTMLProps<ColorPickerDerivedElement>, 'size' | 'type' | 'label'> { | export interface ColorPickerProps extends Omit<React.HTMLProps<ColorPickerDerivedElement>, 'size' | 'type' | 'label'> { | ||||
square?: boolean; | square?: boolean; | ||||
size?: 'small' | 'medium' | 'large'; | size?: 'small' | 'medium' | 'large'; | ||||
@@ -25,6 +31,9 @@ export const colorPickerPlugin = plugin(({ addComponents }) => { | |||||
}); | }); | ||||
}); | }); | ||||
/** | |||||
* Component for picking a color. | |||||
*/ | |||||
export const ColorPicker = React.forwardRef< | export const ColorPicker = React.forwardRef< | ||||
ColorPickerDerivedElement, | ColorPickerDerivedElement, | ||||
ColorPickerProps | ColorPickerProps | ||||
@@ -3,12 +3,18 @@ import clsx from 'clsx'; | |||||
import Color from 'color'; | import Color from 'color'; | ||||
import * as convert from 'color-convert'; | import * as convert from 'color-convert'; | ||||
/** | |||||
* Derived HTML element of the {@link Swatch} component. | |||||
*/ | |||||
export type SwatchDerivedElement = HTMLInputElement; | export type SwatchDerivedElement = HTMLInputElement; | ||||
type ColorValue = ConstructorParameters<typeof Color>[0]; | type ColorValue = ConstructorParameters<typeof Color>[0]; | ||||
type ColorMode = keyof typeof convert; | type ColorMode = keyof typeof convert; | ||||
/** | |||||
* Props of the {@link Swatch} component. | |||||
*/ | |||||
export interface SwatchProps extends Omit<React.HTMLProps<SwatchDerivedElement>, 'color'> { | export interface SwatchProps extends Omit<React.HTMLProps<SwatchDerivedElement>, 'color'> { | ||||
color: NonNullable<ColorValue>; | color: NonNullable<ColorValue>; | ||||
mode?: ColorMode; | mode?: ColorMode; | ||||
@@ -26,6 +32,9 @@ export const useSwatchControls = () => { | |||||
}), [id, copyColor]); | }), [id, copyColor]); | ||||
}; | }; | ||||
/** | |||||
* Component for displaying a color. | |||||
*/ | |||||
export const Swatch = React.forwardRef<SwatchDerivedElement, SwatchProps>(({ | export const Swatch = React.forwardRef<SwatchDerivedElement, SwatchProps>(({ | ||||
// todo unify color and mode into one "value" attribute | // todo unify color and mode into one "value" attribute | ||||
color, | color, | ||||
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -5,23 +5,23 @@ import { useClientSide, useFallbackId, useProxyInput } from '@modal-sh/react-uti | |||||
import { TextControl } from '@tesseract-design/web-base'; | import { TextControl } from '@tesseract-design/web-base'; | ||||
import plugin from 'tailwindcss/plugin'; | import plugin from 'tailwindcss/plugin'; | ||||
const TAG_INPUT_SEPARATOR_MAP = { | |||||
/** | |||||
* Separator for splitting the input value into multiple tags. | |||||
*/ | |||||
export type TagInputSeparator = 'comma' | 'newline' | 'semicolon'; | |||||
const TAG_INPUT_SEPARATOR_MAP: Record<TagInputSeparator, string> = { | |||||
'comma': ',', | 'comma': ',', | ||||
'newline': 'Enter', | 'newline': 'Enter', | ||||
'semicolon': ';', | 'semicolon': ';', | ||||
} as const; | } as const; | ||||
const TAG_INPUT_VALUE_SEPARATOR_MAP = { | |||||
const TAG_INPUT_VALUE_SEPARATOR_MAP: Record<TagInputSeparator, string> = { | |||||
'comma': ',', | 'comma': ',', | ||||
'newline': '\n', | 'newline': '\n', | ||||
'semicolon': ';', | 'semicolon': ';', | ||||
} as const; | } as const; | ||||
/** | |||||
* Separator for splitting the input value into multiple tags. | |||||
*/ | |||||
export type TagInputSeparator = keyof typeof TAG_INPUT_SEPARATOR_MAP | |||||
/** | /** | ||||
* Derived HTML element of the {@link TagInput} component. | * Derived HTML element of the {@link TagInput} component. | ||||
*/ | */ | ||||
@@ -263,12 +263,9 @@ export const TagInput = React.forwardRef<TagInputDerivedElement, TagInputProps>( | |||||
valueSetterFn: (v) => { | valueSetterFn: (v) => { | ||||
setTags(v); | setTags(v); | ||||
}, | }, | ||||
transformChangeHandlerArgs: (newTags) => { | |||||
const thisNewTags = newTags as string[]; | |||||
return ( | |||||
thisNewTags.map((t) => t.trim()).join(TAG_INPUT_VALUE_SEPARATOR_MAP[valueSeparator]) | |||||
); | |||||
}, | |||||
transformChangeHandlerArgs: (newTags) => ( | |||||
newTags.map((t) => t.trim()).join(TAG_INPUT_VALUE_SEPARATOR_MAP[valueSeparator]) | |||||
), | |||||
}); | }); | ||||
const ref = forwardedRef ?? defaultRef; | const ref = forwardedRef ?? defaultRef; | ||||
const labelId = React.useId(); | const labelId = React.useId(); | ||||
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -49,6 +49,9 @@ export interface LinkButtonProps<T = any> extends Omit<React.HTMLProps<LinkButto | |||||
disabled?: boolean; | disabled?: boolean; | ||||
} | } | ||||
/** | |||||
* Component for performing a navigation action. | |||||
*/ | |||||
export const LinkButton = React.forwardRef<LinkButtonDerivedElement, LinkButtonProps>(( | export const LinkButton = React.forwardRef<LinkButtonDerivedElement, LinkButtonProps>(( | ||||
{ | { | ||||
variant = 'bare' as const, | variant = 'bare' as const, | ||||
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -15,7 +15,11 @@ type Segment = `${Digit}${Digit}`; | |||||
type StepHhMm = `${Segment}:${Segment}`; | type StepHhMm = `${Segment}:${Segment}`; | ||||
type StepHhMmSs = `${StepHhMm}:${Segment}`; | |||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | |||||
// @ts-ignore | |||||
// type StepHhMmSs = `${StepHhMm}:${Segment}`; | |||||
type StepHhMmSs = string; | |||||
type Step = StepHhMm | StepHhMmSs; | type Step = StepHhMm | StepHhMmSs; | ||||
@@ -58,7 +62,7 @@ export interface TimeSpinnerProps extends Omit<React.HTMLProps<TimeSpinnerDerive | |||||
/** | /** | ||||
* Step size for the component. | * Step size for the component. | ||||
*/ | */ | ||||
step?: Step, | |||||
step?: Step | string, | |||||
} | } | ||||
export const timeSpinnerPlugin = plugin(({ addComponents }) => { | export const timeSpinnerPlugin = plugin(({ addComponents }) => { | ||||
@@ -114,7 +118,7 @@ export const TimeSpinner = React.forwardRef< | |||||
const labelId = React.useId(); | const labelId = React.useId(); | ||||
const id = useFallbackId(idProp); | const id = useFallbackId(idProp); | ||||
const [hh, mm, ss = 0] = step.split(':').map((s: string) => parseInt(s, 10)) as number[]; | |||||
const [hh, mm, ss = 0] = step.split(':').map((s: string) => parseInt(s, 10)); | |||||
const stepValue = ss + (mm * 60) + (hh * 3600); | const stepValue = ss + (mm * 60) + (hh * 3600); | ||||
return ( | return ( | ||||
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"extends": ["../../../typedoc.base.json"], | |||||
"exclude": ["**/*.test.(ts|tsx)", "**/node_modules/**"], | |||||
"entryPoints": ["src/index.ts"], | |||||
"excludeNotDocumented": true, | |||||
"includeVersion": true, | |||||
"tsconfig": "../../../tsconfig.json" | |||||
} |
@@ -1,4 +1,4 @@ | |||||
# Tesseract | |||||
# Philosophy | |||||
## Design | ## Design | ||||
- Tesseract components follow a strict and simple design philosophy. | - Tesseract components follow a strict and simple design philosophy. | ||||
@@ -1238,6 +1238,9 @@ importers: | |||||
tailwindcss: | tailwindcss: | ||||
specifier: 0.0.0-insiders.7f31ac1 | specifier: 0.0.0-insiders.7f31ac1 | ||||
version: 0.0.0-insiders.7f31ac1 | version: 0.0.0-insiders.7f31ac1 | ||||
typedoc: | |||||
specifier: ^0.24.8 | |||||
version: 0.24.8(typescript@5.1.3) | |||||
packages: | packages: | ||||
@@ -2634,6 +2637,10 @@ packages: | |||||
engines: {node: '>=12'} | engines: {node: '>=12'} | ||||
dev: true | dev: true | ||||
/ansi-sequence-parser@1.1.1: | |||||
resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} | |||||
dev: true | |||||
/ansi-styles@3.2.1: | /ansi-styles@3.2.1: | ||||
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} | ||||
engines: {node: '>=4'} | engines: {node: '>=4'} | ||||
@@ -2843,6 +2850,12 @@ packages: | |||||
balanced-match: 1.0.2 | balanced-match: 1.0.2 | ||||
concat-map: 0.0.1 | concat-map: 0.0.1 | ||||
/brace-expansion@2.0.1: | |||||
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} | |||||
dependencies: | |||||
balanced-match: 1.0.2 | |||||
dev: true | |||||
/braces@3.0.2: | /braces@3.0.2: | ||||
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} | ||||
engines: {node: '>=8'} | engines: {node: '>=8'} | ||||
@@ -5446,6 +5459,10 @@ packages: | |||||
dependencies: | dependencies: | ||||
yallist: 4.0.0 | yallist: 4.0.0 | ||||
/lunr@2.3.9: | |||||
resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} | |||||
dev: true | |||||
/lz-string@1.5.0: | /lz-string@1.5.0: | ||||
resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} | resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} | ||||
hasBin: true | hasBin: true | ||||
@@ -5465,6 +5482,12 @@ packages: | |||||
semver: 6.3.0 | semver: 6.3.0 | ||||
dev: true | dev: true | ||||
/marked@4.3.0: | |||||
resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} | |||||
engines: {node: '>= 12'} | |||||
hasBin: true | |||||
dev: true | |||||
/mdast-util-definitions@5.1.2: | /mdast-util-definitions@5.1.2: | ||||
resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} | resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} | ||||
dependencies: | dependencies: | ||||
@@ -5728,6 +5751,13 @@ packages: | |||||
dependencies: | dependencies: | ||||
brace-expansion: 1.1.11 | brace-expansion: 1.1.11 | ||||
/minimatch@9.0.3: | |||||
resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} | |||||
engines: {node: '>=16 || 14 >=14.17'} | |||||
dependencies: | |||||
brace-expansion: 2.0.1 | |||||
dev: true | |||||
/minimist@1.2.8: | /minimist@1.2.8: | ||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} | ||||
@@ -6763,6 +6793,15 @@ packages: | |||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} | ||||
engines: {node: '>=8'} | engines: {node: '>=8'} | ||||
/shiki@0.14.3: | |||||
resolution: {integrity: sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==} | |||||
dependencies: | |||||
ansi-sequence-parser: 1.1.1 | |||||
jsonc-parser: 3.2.0 | |||||
vscode-oniguruma: 1.7.0 | |||||
vscode-textmate: 8.0.0 | |||||
dev: true | |||||
/side-channel@1.0.4: | /side-channel@1.0.4: | ||||
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} | resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} | ||||
dependencies: | dependencies: | ||||
@@ -7330,6 +7369,20 @@ packages: | |||||
is-typedarray: 1.0.0 | is-typedarray: 1.0.0 | ||||
dev: true | dev: true | ||||
/typedoc@0.24.8(typescript@5.1.3): | |||||
resolution: {integrity: sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==} | |||||
engines: {node: '>= 14.14'} | |||||
hasBin: true | |||||
peerDependencies: | |||||
typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x | |||||
dependencies: | |||||
lunr: 2.3.9 | |||||
marked: 4.3.0 | |||||
minimatch: 9.0.3 | |||||
shiki: 0.14.3 | |||||
typescript: 5.1.3 | |||||
dev: true | |||||
/typescript@4.9.5: | /typescript@4.9.5: | ||||
resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} | resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} | ||||
engines: {node: '>=4.2.0'} | engines: {node: '>=4.2.0'} | ||||
@@ -7713,6 +7766,14 @@ packages: | |||||
- terser | - terser | ||||
dev: true | dev: true | ||||
/vscode-oniguruma@1.7.0: | |||||
resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} | |||||
dev: true | |||||
/vscode-textmate@8.0.0: | |||||
resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} | |||||
dev: true | |||||
/vue-eslint-parser@9.3.1(eslint@8.43.0): | /vue-eslint-parser@9.3.1(eslint@8.43.0): | ||||
resolution: {integrity: sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==} | resolution: {integrity: sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==} | ||||
engines: {node: ^14.17.0 || >=16.0.0} | engines: {node: ^14.17.0 || >=16.0.0} | ||||
@@ -33,3 +33,5 @@ yarn-error.log* | |||||
# typescript | # typescript | ||||
*.tsbuildinfo | *.tsbuildinfo | ||||
next-env.d.ts | next-env.d.ts | ||||
typedoc.data.json |
@@ -3,6 +3,7 @@ | |||||
"version": "0.1.0", | "version": "0.1.0", | ||||
"private": true, | "private": true, | ||||
"scripts": { | "scripts": { | ||||
"typedoc": "", | |||||
"dev": "next dev", | "dev": "next dev", | ||||
"build": "next build", | "build": "next build", | ||||
"start": "next start", | "start": "next start", | ||||
@@ -47,6 +48,7 @@ | |||||
"typescript": "5.1.3" | "typescript": "5.1.3" | ||||
}, | }, | ||||
"devDependencies": { | "devDependencies": { | ||||
"tailwindcss": "0.0.0-insiders.7f31ac1" | |||||
"tailwindcss": "0.0.0-insiders.7f31ac1", | |||||
"typedoc": "^0.24.8" | |||||
} | } | ||||
} | } |
@@ -7,7 +7,7 @@ export const Brand = () => { | |||||
Tesseract | Tesseract | ||||
</span> | </span> | ||||
{' '} | {' '} | ||||
<span className="absolute left-2 top-4 font-semibold"> | |||||
<span className="absolute left-4 top-4 font-semibold"> | |||||
Web | Web | ||||
</span> | </span> | ||||
{' '} | {' '} | ||||
@@ -17,7 +17,7 @@ export const Brand = () => { | |||||
<span className="sr-only">)</span> | <span className="sr-only">)</span> | ||||
</span> | </span> | ||||
{' '} | {' '} | ||||
<span className="absolute right-1 top-4 font-black text-xs"> | |||||
<span className="absolute right-0 top-4 font-black text-xs"> | |||||
v.0.1.0 | v.0.1.0 | ||||
</span> | </span> | ||||
</span> | </span> | ||||
@@ -0,0 +1,203 @@ | |||||
import * as React from 'react'; | |||||
import {Layouts, Widgets} from '@tesseract-design/viewfinder-react'; | |||||
import Link from 'next/link'; | |||||
import {Brand} from '@/components/Brand'; | |||||
import {DropdownSelect} from '@tesseract-design/web-choice-react'; | |||||
export interface Page { | |||||
id: string; | |||||
href: string; | |||||
label: string; | |||||
} | |||||
export interface DocsLayoutProps { | |||||
componentPages?: { name: string; components: Page[] }[]; | |||||
docsPages?: Page[]; | |||||
examplePages?: Page[]; | |||||
sidebarOpen?: boolean; | |||||
children?: React.ReactNode; | |||||
} | |||||
const createSidebarPageLink = (p: Page) => ( | |||||
<div | |||||
key={p.id} | |||||
> | |||||
<Link | |||||
href={p.href} | |||||
className="no-underline font-semibold m-0 p-0 leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
{p.label} | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
</Link> | |||||
</div> | |||||
); | |||||
export const DocsLayout: React.FC<DocsLayoutProps> = ({ | |||||
sidebarOpen = false, | |||||
componentPages = [], | |||||
docsPages = [], | |||||
examplePages = [], | |||||
children, | |||||
}) => { | |||||
return ( | |||||
<Layouts.LeftSidebar.Root | |||||
topBarWidget={ | |||||
<Widgets.TopBar | |||||
span="wide" | |||||
brand={ | |||||
<Link | |||||
href="/" | |||||
className="no-underline block" | |||||
> | |||||
<Brand /> | |||||
</Link> | |||||
} | |||||
menuLink={ | |||||
<Link | |||||
href={{ | |||||
query: { | |||||
open: 'sidebar', | |||||
}, | |||||
}} | |||||
className="no-underline p-0 m-0" | |||||
> | |||||
<svg | |||||
className="w-6 h-6 fill-none stroke-current stroke-2 linejoin-round linecap-round" | |||||
viewBox="0 0 24 24" | |||||
role="presentation" | |||||
> | |||||
<line x1="3" y1="12" x2="21" y2="12"/> | |||||
<line x1="3" y1="6" x2="21" y2="6"/> | |||||
<line x1="3" y1="18" x2="21" y2="18"/> | |||||
</svg> | |||||
</Link> | |||||
} | |||||
/> | |||||
} | |||||
sidebarBaseWidget={ | |||||
<Widgets.LeftSidebarBase | |||||
open={sidebarOpen} | |||||
> | |||||
<div className="min-h-full py-4 box-border flex flex-col gap-8"> | |||||
<div> | |||||
<nav> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
<h1> | |||||
Docs | |||||
</h1> | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
<div className="flex flex-col gap-2 my-8"> | |||||
{docsPages?.map(createSidebarPageLink)} | |||||
</div> | |||||
</nav> | |||||
<nav> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
<h1> | |||||
Platforms | |||||
</h1> | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
<div className="flex flex-col gap-2 my-8"> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
<div className="flex gap-8"> | |||||
<Link | |||||
href={{ | |||||
pathname: '[...url]', | |||||
query: { | |||||
url: ['web', 'react'], | |||||
}, | |||||
}} | |||||
className="no-underline font-semibold leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
React | |||||
</Link> | |||||
<Link | |||||
href={{ | |||||
pathname: '[...url]', | |||||
query: { | |||||
url: ['web', 'vue'], | |||||
}, | |||||
}} | |||||
className="no-underline font-semibold leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
Vue | |||||
</Link> | |||||
<Link | |||||
href={{ | |||||
pathname: '[...url]', | |||||
query: { | |||||
url: ['web', 'solid'], | |||||
}, | |||||
}} | |||||
className="no-underline font-semibold leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
Solid | |||||
</Link> | |||||
</div> | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
</div> | |||||
</nav> | |||||
{/*<div>*/} | |||||
{/* <Layouts.LeftSidebar.SidebarContentContainer>*/} | |||||
{/* <h1>*/} | |||||
{/* Categories*/} | |||||
{/* </h1>*/} | |||||
{/* </Layouts.LeftSidebar.SidebarContentContainer>*/} | |||||
{/* {componentPages.map(({name, components}) => (*/} | |||||
{/* <nav key={name}>*/} | |||||
{/* <h2>*/} | |||||
{/* <Layouts.LeftSidebar.SidebarContentContainer>*/} | |||||
{/* {name}*/} | |||||
{/* </Layouts.LeftSidebar.SidebarContentContainer>*/} | |||||
{/* </h2>*/} | |||||
{/* <div className="flex flex-col gap-2 my-8">*/} | |||||
{/* {components?.map(createSidebarPageLink)}*/} | |||||
{/* </div>*/} | |||||
{/* </nav>*/} | |||||
{/* ))}*/} | |||||
{/*</div>*/} | |||||
{/*<nav>*/} | |||||
{/* <Layouts.LeftSidebar.SidebarContentContainer>*/} | |||||
{/* <h1>*/} | |||||
{/* Examples*/} | |||||
{/* </h1>*/} | |||||
{/* </Layouts.LeftSidebar.SidebarContentContainer>*/} | |||||
{/* <div className="flex flex-col gap-4 my-4">*/} | |||||
{/* {examplePages?.map(createSidebarPageLink)}*/} | |||||
{/* </div>*/} | |||||
{/*</nav>*/} | |||||
</div> | |||||
<div className="mb-8"> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
<div className="flex gap-8"> | |||||
<Link | |||||
href="https://code.modal.sh/tesseract-design/tesseract" | |||||
className="no-underline font-semibold leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
Repo | |||||
</Link> | |||||
<Link | |||||
href="https://code.modal.sh/tesseract-design/tesseract" | |||||
className="no-underline font-semibold leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
Website | |||||
</Link> | |||||
<Link | |||||
href="https://code.modal.sh/tesseract-design/tesseract/issues" | |||||
className="no-underline font-semibold leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
Issues | |||||
</Link> | |||||
</div> | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
</div> | |||||
</div> | |||||
</Widgets.LeftSidebarBase> | |||||
} | |||||
> | |||||
<Layouts.LeftSidebar.MainContentContainer> | |||||
{children} | |||||
</Layouts.LeftSidebar.MainContentContainer> | |||||
</Layouts.LeftSidebar.Root> | |||||
) | |||||
}; |
@@ -0,0 +1,249 @@ | |||||
import type {GetStaticPaths, GetStaticProps, NextPage} from 'next'; | |||||
import * as fs from 'fs/promises'; | |||||
import * as path from 'path'; | |||||
import * as React from 'react' | |||||
import {useRouter} from 'next/router'; | |||||
import ReactMarkdown from 'react-markdown'; | |||||
import {DocsLayout, Page} from '@/components/DocsLayout'; | |||||
export interface Props { | |||||
componentPages: { name: string; components: Page[] }[], | |||||
docsPages: Page[], | |||||
examplePages: Page[], | |||||
markdown: string, | |||||
} | |||||
const InnerPage: NextPage<Props> = ({ | |||||
componentPages, | |||||
examplePages, | |||||
docsPages, | |||||
markdown, | |||||
}) => { | |||||
const router = useRouter(); | |||||
const sidebarOpen = router.query.open === 'sidebar'; | |||||
return ( | |||||
<DocsLayout | |||||
componentPages={componentPages} | |||||
examplePages={examplePages} | |||||
docsPages={docsPages} | |||||
sidebarOpen={sidebarOpen} | |||||
> | |||||
{markdown && ( | |||||
<ReactMarkdown | |||||
className="my-12 leading-loose" | |||||
components={{ | |||||
ul: ({node, ordered: _ordered, ...props}) => ( | |||||
<ul | |||||
{...props} | |||||
className="list-disc pl-4" | |||||
/> | |||||
), | |||||
li: ({node, ...props}) => ( | |||||
<li | |||||
{...props} | |||||
className="list-item pl-4" | |||||
/> | |||||
), | |||||
}} | |||||
> | |||||
{markdown} | |||||
</ReactMarkdown> | |||||
)} | |||||
<pre> | |||||
<code> | |||||
{JSON.stringify(componentPages, null, 2)} | |||||
</code> | |||||
</pre> | |||||
</DocsLayout> | |||||
) | |||||
} | |||||
export const getStaticProps: GetStaticProps = async (ctx) => { | |||||
const { params } = ctx; | |||||
const { url } = params as { url: string[] }; | |||||
const [platform, framework, ...etcUrl] = url; | |||||
const props = {} as Record<string, unknown>; | |||||
const docsPath = path.resolve('../../docs'); | |||||
const docs = await fs.readdir(docsPath); | |||||
props.docsPages = docs.map((d) => ({ | |||||
id: d, | |||||
href: `/docs/${d}`, | |||||
label: d | |||||
.split('-') | |||||
.slice(1) | |||||
.map((dd) => dd.slice(0, 1).toUpperCase() + dd.slice(1)) | |||||
.join(' ') | |||||
.replace(/\.md/i, '') | |||||
})); | |||||
// const categoriesPath = path.resolve('../../categories'); | |||||
// const categories = await fs.readdir(categoriesPath); | |||||
// props.componentPages = categories.map((c) => ({ | |||||
// id: c, | |||||
// href: `/categories/${c}`, | |||||
// label: c.split('-').map((cc) => cc.slice(0, 1).toUpperCase() + cc.slice(1)).join(' '), | |||||
// })); | |||||
// const pagesPath = path.resolve('src/pages'); | |||||
// const examplesPath = path.resolve(pagesPath, 'examples'); | |||||
// const examplesRaw = await fs.readdir(examplesPath); | |||||
// const examplesIndexPage = await Promise.all( | |||||
// examplesRaw.map(async (c) => { | |||||
// const indexPath = await path.resolve(examplesPath, c, 'index.tsx'); | |||||
// try { | |||||
// const statResult = await fs.stat(indexPath); | |||||
// return [c, statResult.isFile()]; | |||||
// } catch { | |||||
// // noop | |||||
// } | |||||
// | |||||
// return [c, false]; | |||||
// }) | |||||
// ) as [string, boolean][]; | |||||
// const examples = examplesIndexPage | |||||
// .filter(([, hasIndexPage]) => hasIndexPage) | |||||
// .map(([key]) => key); | |||||
// props.examplePages = examples.map((e) => ({ | |||||
// id: e, | |||||
// href: `/examples/${e}`, | |||||
// label: e.split('-').map((ee) => ee.slice(0, 1).toUpperCase() + ee.slice(1)).join(' '), | |||||
// })); | |||||
const isHome = !Array.isArray(params.url); | |||||
if (isHome) { | |||||
const readmePath = path.resolve('../../README.md'); | |||||
props.markdown = await fs.readFile(readmePath, 'utf-8'); | |||||
} | |||||
const theParamsUrl = params.url as string[]; | |||||
const isDocs = Array.isArray(theParamsUrl) && theParamsUrl[0] === 'docs'; | |||||
if (isDocs) { | |||||
const docsPath = path.resolve('../../docs', theParamsUrl[1] as string); | |||||
props.markdown = await fs.readFile(docsPath, 'utf-8'); | |||||
} | |||||
const typedocData = await fs.readFile('typedoc.data.json', 'utf-8'); | |||||
const project = JSON.parse(typedocData) as any; | |||||
props.componentPages = project.children.reduce( | |||||
(theComponents, pkg) => { | |||||
const packageNameFragments = pkg.name.split('-'); | |||||
const packageFramework = packageNameFragments.pop(); | |||||
const categoryBaseName = packageNameFragments.pop(); | |||||
console.log(packageFramework, categoryBaseName); | |||||
if (theComponents.some((c) => c.name === categoryBaseName)) { | |||||
return theComponents.map((cc) => { | |||||
if (cc.name !== categoryBaseName) { | |||||
return cc; | |||||
} | |||||
let components = []; | |||||
if (packageFramework === 'react') { | |||||
components = pkg.children | |||||
.filter((exported) => { | |||||
return exported.kind === 64; // Function, these are react components | |||||
}) | |||||
.map((component) => { | |||||
return { | |||||
...component, | |||||
id: component.name, | |||||
href: `/categories/${categoryBaseName}/${component.name}`, | |||||
label: component.name, | |||||
descriptionMarkdown: component.signatures[0].comment.summary.reduce( | |||||
(theText, t) => { | |||||
if (t.kind === 'text') { | |||||
return `${theText}${t.text}`; | |||||
} | |||||
if (t.kind === 'inline-tag' && t.tag === '@link') { | |||||
return `${theText}[${t.text}](#)` // TODO set URL | |||||
} | |||||
return theText; | |||||
}, | |||||
'' | |||||
), | |||||
}; | |||||
}); | |||||
} | |||||
return { | |||||
...cc, | |||||
name: categoryBaseName, | |||||
packages: { | |||||
...(cc.packages ?? {}), | |||||
[packageFramework]: { | |||||
components, | |||||
}, | |||||
}, | |||||
}; | |||||
}) | |||||
} | |||||
let components = []; | |||||
if (packageFramework === 'react') { | |||||
components = pkg.children | |||||
.filter((exported) => { | |||||
return exported.kind === 64; // Function, these are react components | |||||
}) | |||||
.map((component) => { | |||||
return { | |||||
...component, | |||||
id: component.name, | |||||
href: `/categories/${categoryBaseName}/${component.name}`, | |||||
label: component.name, | |||||
descriptionMarkdown: component.signatures[0].comment.summary.reduce( | |||||
(theText, t) => { | |||||
if (t.kind === 'text') { | |||||
return `${theText}${t.text}`; | |||||
} | |||||
if (t.kind === 'inline-tag' && t.tag === '@link') { | |||||
return `${theText}[${t.text}](#)` // TODO set URL | |||||
} | |||||
return theText; | |||||
}, | |||||
'' | |||||
), | |||||
}; | |||||
}); | |||||
} | |||||
return [ | |||||
...theComponents, | |||||
{ | |||||
name: categoryBaseName, | |||||
packages: { | |||||
[packageFramework]: { | |||||
components, | |||||
} | |||||
} | |||||
} | |||||
] | |||||
}, | |||||
[], | |||||
); | |||||
return { | |||||
props, | |||||
}; | |||||
}; | |||||
export default InnerPage; | |||||
export const getStaticPaths: GetStaticPaths = async () => { | |||||
const docsPath = path.resolve('../../docs'); | |||||
const docs = await fs.readdir(docsPath); | |||||
const categoriesPath = path.resolve('../../categories'); | |||||
const categories = await fs.readdir(categoriesPath); | |||||
return { | |||||
paths: [ | |||||
...docs.map((d) => `/docs/${d}`), | |||||
], | |||||
fallback: true, | |||||
}; | |||||
}; |
@@ -1,13 +0,0 @@ | |||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction | |||||
import type { NextApiRequest, NextApiResponse } from 'next' | |||||
type Data = { | |||||
name: string | |||||
} | |||||
export default function handler( | |||||
req: NextApiRequest, | |||||
res: NextApiResponse<Data> | |||||
) { | |||||
res.status(200).json({ name: 'John Doe' }) | |||||
} |
@@ -1,242 +0,0 @@ | |||||
import { NextPage } from 'next'; | |||||
import * as Action from '@tesseract-design/web-action-react'; | |||||
import { DefaultLayout } from '@/components/DefaultLayout'; | |||||
const ActionPage: NextPage = () => { | |||||
return ( | |||||
<DefaultLayout | |||||
title="Action" | |||||
> | |||||
<section> | |||||
<div className="container mx-auto px-4"> | |||||
<h1> | |||||
ActionButton | |||||
</h1> | |||||
<div> | |||||
<section> | |||||
<h2>Variants</h2> | |||||
<div> | |||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 my-4"> | |||||
<div> | |||||
<Action.ActionButton | |||||
variant="bare" | |||||
block | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
variant="filled" | |||||
block | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
variant="outline" | |||||
block | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
variant="filled" | |||||
block | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
variant="bare" | |||||
block | |||||
disabled | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
variant="filled" | |||||
block | |||||
disabled | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
variant="outline" | |||||
block | |||||
disabled | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
variant="filled" | |||||
block | |||||
disabled | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<section> | |||||
<h2>Sizes</h2> | |||||
<div> | |||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 my-4"> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
variant="outline" | |||||
size="small" | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
variant="filled" | |||||
size="small" | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
variant="outline" | |||||
size="medium" | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
variant="filled" | |||||
size="medium" | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
variant="outline" | |||||
size="large" | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
variant="filled" | |||||
size="large" | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<section> | |||||
<h2>Compact</h2> | |||||
<div> | |||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 my-4"> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
compact | |||||
variant="outline" | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
compact | |||||
variant="filled" | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
compact | |||||
variant="outline" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
compact | |||||
variant="filled" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
compact | |||||
variant="outline" | |||||
size="small" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
> | |||||
Button | |||||
</Action.ActionButton> | |||||
</div> | |||||
<div> | |||||
<Action.ActionButton | |||||
block | |||||
compact | |||||
variant="filled" | |||||
size="small" | |||||
subtext={ | |||||
<> | |||||
Very Long Line of Subtext That Spans More Than The Component Width For Testing Overflow | |||||
</> | |||||
} | |||||
> | |||||
Very Long Line of Text That Spans More Than The Component Width For Testing Overflow | |||||
</Action.ActionButton> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
</DefaultLayout> | |||||
) | |||||
} | |||||
export default ActionPage |
@@ -1,61 +0,0 @@ | |||||
import {NextPage} from 'next'; | |||||
import {DefaultLayout} from '@/components/DefaultLayout'; | |||||
import {Section, Subsection} from '@/components/Section'; | |||||
import * as TesseractBlob from '@tesseract-design/web-blob-react'; | |||||
const BlobPage: NextPage = () => { | |||||
return ( | |||||
<DefaultLayout title="Blob"> | |||||
<Section title="FileSelectBox"> | |||||
<Subsection title="Default"> | |||||
<TesseractBlob.FileSelectBox | |||||
label="File" | |||||
name="file" | |||||
border | |||||
placeholder="Select a file" | |||||
onChange={(e) => { console.log('change', e.currentTarget.name, e.currentTarget, e.currentTarget.files)}} | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="Default Multiple"> | |||||
<TesseractBlob.FileSelectBox | |||||
label="File" | |||||
name="file" | |||||
border | |||||
multiple | |||||
placeholder="Select a file" | |||||
onChange={(e) => { console.log('change', e.currentTarget.name, e.currentTarget, e.currentTarget.files)}} | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="Enhanced"> | |||||
<TesseractBlob.FileSelectBox | |||||
label="File" | |||||
name="file" | |||||
border | |||||
enhanced | |||||
placeholder="Select a file" | |||||
style={{ | |||||
height: 256, | |||||
}} | |||||
onChange={(e) => { console.log('change', e.currentTarget.name, e.currentTarget, e.currentTarget.files)}} | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="Enhanced Multiple"> | |||||
<TesseractBlob.FileSelectBox | |||||
label="File" | |||||
name="file" | |||||
border | |||||
enhanced | |||||
placeholder="Select a file" | |||||
multiple | |||||
style={{ | |||||
height: 256, | |||||
}} | |||||
onChange={(e) => { console.log('change', e.currentTarget.name, e.currentTarget, e.currentTarget.files)}} | |||||
/> | |||||
</Subsection> | |||||
</Section> | |||||
</DefaultLayout> | |||||
) | |||||
} | |||||
export default BlobPage; |
@@ -1,90 +0,0 @@ | |||||
import {NextPage} from 'next'; | |||||
import {DefaultLayout} from '@/components/DefaultLayout'; | |||||
import {Section, Subsection} from '@/components/Section'; | |||||
import * as Color from '@tesseract-design/web-color-react'; | |||||
import { TextInput } from '@tesseract-design/web-freeform-react'; | |||||
const ColorPage: NextPage = () => { | |||||
return ( | |||||
<DefaultLayout title="Color"> | |||||
<Section title="ColorPicker"> | |||||
<Subsection title="Default"> | |||||
<Color.ColorPicker | |||||
size="small" | |||||
defaultValue="#ff0000" | |||||
/> | |||||
<Color.ColorPicker | |||||
size="medium" | |||||
defaultValue="#00ff00" | |||||
/> | |||||
<Color.ColorPicker | |||||
size="large" | |||||
defaultValue="#0000ff" | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="Square"> | |||||
<Color.ColorPicker | |||||
size="small" | |||||
square | |||||
defaultValue="#ff0000" | |||||
/> | |||||
<Color.ColorPicker | |||||
size="medium" | |||||
square | |||||
defaultValue="#00ff00" | |||||
/> | |||||
<Color.ColorPicker | |||||
size="large" | |||||
square | |||||
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> | |||||
<Subsection title="Copy on select"> | |||||
<Color.ColorPicker | |||||
size="small" | |||||
defaultValue="#ff0000" | |||||
copyOnSelect | |||||
readOnly | |||||
/> | |||||
<Color.ColorPicker | |||||
size="medium" | |||||
defaultValue="#00ff00" | |||||
copyOnSelect | |||||
readOnly | |||||
/> | |||||
<Color.ColorPicker | |||||
size="large" | |||||
defaultValue="#0000ff" | |||||
copyOnSelect | |||||
readOnly | |||||
/> | |||||
<div> | |||||
<TextInput | |||||
label="Color" | |||||
border | |||||
/> | |||||
</div> | |||||
</Subsection> | |||||
</Section> | |||||
</DefaultLayout> | |||||
) | |||||
} | |||||
export default ColorPage; |
@@ -1,128 +0,0 @@ | |||||
import {NextPage} from 'next'; | |||||
import {DefaultLayout} from '@/components/DefaultLayout'; | |||||
import {Section, Subsection} from '@/components/Section'; | |||||
import * as Formatted from '@tesseract-design/web-formatted-react'; | |||||
import {useRef} from 'react'; | |||||
import {ActionButton} from '@tesseract-design/web-action-react'; | |||||
const TemporalPage: NextPage = () => { | |||||
const phoneNumberRef = useRef<HTMLInputElement>(null); | |||||
return ( | |||||
<DefaultLayout title="Formatted"> | |||||
<Section title="PhoneNumberInput"> | |||||
<Subsection title="Default"> | |||||
<Formatted.PhoneNumberInput | |||||
country="PH" | |||||
label="Phone" | |||||
name="phone" | |||||
enhanced | |||||
border | |||||
onFocus={(e) => { console.log('focus', e.currentTarget)}} | |||||
onBlur={(e) => { console.log('blur', e.currentTarget)}} | |||||
onChange={(e) => { console.log('change', e.currentTarget.name, e.currentTarget, e.currentTarget.value)}} | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="Non-enhanced"> | |||||
<Formatted.PhoneNumberInput | |||||
country="PH" | |||||
label="Phone" | |||||
name="phone" | |||||
border | |||||
onFocus={(e) => { console.log('focus', e.currentTarget)}} | |||||
onBlur={(e) => { console.log('blur', e.currentTarget)}} | |||||
onChange={(e) => { console.log('change', e.currentTarget.name, e.currentTarget, e.currentTarget.value)}} | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="With Default Value"> | |||||
<Formatted.PhoneNumberInput | |||||
country="PH" | |||||
label="Phone" | |||||
name="phone2" | |||||
enhanced | |||||
border | |||||
defaultValue="+639876543210" | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="With Ref"> | |||||
<div className="flex gap-4 flex-wrap"> | |||||
<div> | |||||
<Formatted.PhoneNumberInput | |||||
country="PH" | |||||
label="Phone" | |||||
name="phone3" | |||||
enhanced | |||||
border | |||||
ref={phoneNumberRef} | |||||
onChange={(e) => { console.log('change', e.currentTarget.name, e.currentTarget, e.currentTarget.value)}} | |||||
/> | |||||
</div> | |||||
<div> | |||||
<ActionButton | |||||
onClick={() => { | |||||
if (phoneNumberRef.current) { | |||||
phoneNumberRef.current.value = '+639123456789'; | |||||
} | |||||
}} | |||||
> | |||||
Set Value | |||||
</ActionButton> | |||||
</div> | |||||
<div> | |||||
<ActionButton | |||||
onClick={() => { | |||||
if (phoneNumberRef.current) { | |||||
phoneNumberRef.current.value = '+63465123456'; | |||||
} | |||||
}} | |||||
> | |||||
Set Other Value | |||||
</ActionButton> | |||||
</div> | |||||
<div> | |||||
<ActionButton | |||||
onClick={() => { | |||||
if (phoneNumberRef.current) { | |||||
phoneNumberRef.current.value = '+63288888888'; | |||||
} | |||||
}} | |||||
> | |||||
Set Yet Other Value | |||||
</ActionButton> | |||||
</div> | |||||
</div> | |||||
</Subsection> | |||||
</Section> | |||||
<Section title="EmailInput"> | |||||
<Subsection title="Default"> | |||||
<Formatted.EmailInput | |||||
label="Email" | |||||
name="email" | |||||
border | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="With domains"> | |||||
<Formatted.EmailInput | |||||
label="Email" | |||||
name="email" | |||||
border | |||||
variant="alternate" | |||||
domains={['gmail.com', 'yahoo.com']} | |||||
hint="Only GMail or Yahoo Mail allowed" | |||||
length={50} | |||||
/> | |||||
</Subsection> | |||||
</Section> | |||||
<Section title="UrlInput"> | |||||
<Subsection title="Default"> | |||||
<Formatted.UrlInput | |||||
label="Website" | |||||
name="website" | |||||
border | |||||
/> | |||||
</Subsection> | |||||
</Section> | |||||
</DefaultLayout> | |||||
) | |||||
} | |||||
export default TemporalPage; |
@@ -1,601 +0,0 @@ | |||||
import { NextPage } from 'next'; | |||||
import * as Freeform from '@tesseract-design/web-freeform-react'; | |||||
import { DefaultLayout } from '@/components/DefaultLayout'; | |||||
import { Section, Subsection } from '@/components/Section'; | |||||
const FreeformPage: NextPage = () => { | |||||
return ( | |||||
<DefaultLayout title="Freeform"> | |||||
<Section title="TextInput"> | |||||
<Subsection title="Default"> | |||||
<div className="grid md:grid-cols-2 gap-4 my-4"> | |||||
<div> | |||||
<Freeform.TextInput | |||||
size="small" | |||||
label="TextInput ffgg" | |||||
hint="Type anything here… ffgg" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
border | |||||
size="small" | |||||
label="TextInput ffgg" | |||||
hint="Type anything here… ffgg" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
label="TextInput ffgg" | |||||
hint="Type anything here… ffgg" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
border | |||||
label="TextInput ffgg" | |||||
hint="Type anything here… ffgg" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
size="large" | |||||
label="TextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
border | |||||
size="large" | |||||
label="TextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
label="TextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
border | |||||
label="TextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
</div> | |||||
<form> | |||||
<fieldset className="contents"> | |||||
<legend className="sr-only">Fieldset Test</legend> | |||||
<div className="grid grid-cols-6 gap-4 my-4"> | |||||
<div className="col-span-2"> | |||||
<Freeform.TextInput | |||||
label="First Name" | |||||
block | |||||
border | |||||
/> | |||||
</div> | |||||
<div className="col-span-2"> | |||||
<Freeform.TextInput | |||||
label="Middle Name" | |||||
block | |||||
border | |||||
/> | |||||
</div> | |||||
<div className="col-span-2"> | |||||
<Freeform.TextInput | |||||
label="Last Name" | |||||
block | |||||
border | |||||
/> | |||||
</div> | |||||
<div className="col-span-3"> | |||||
<Freeform.TextInput | |||||
label="Username" | |||||
block | |||||
border | |||||
/> | |||||
</div> | |||||
<div className="col-span-3"> | |||||
<Freeform.TextInput | |||||
label="Title" | |||||
block | |||||
border | |||||
disabled | |||||
/> | |||||
</div> | |||||
</div> | |||||
</fieldset> | |||||
</form> | |||||
<form> | |||||
<fieldset | |||||
disabled | |||||
className="contents" | |||||
> | |||||
<legend className="sr-only">Disabled Test</legend> | |||||
<div className="grid grid-cols-6 gap-4 my-4"> | |||||
<div className="col-span-2"> | |||||
<Freeform.TextInput | |||||
label="First Name" | |||||
block | |||||
border | |||||
/> | |||||
</div> | |||||
<div className="col-span-2"> | |||||
<Freeform.TextInput | |||||
label="Middle Name" | |||||
block | |||||
border | |||||
/> | |||||
</div> | |||||
<div className="col-span-2"> | |||||
<Freeform.TextInput | |||||
label="Last Name" | |||||
block | |||||
border | |||||
/> | |||||
</div> | |||||
<div className="col-span-3"> | |||||
<Freeform.TextInput | |||||
label="Username" | |||||
block | |||||
border | |||||
/> | |||||
</div> | |||||
<div className="col-span-3"> | |||||
<Freeform.TextInput | |||||
label="Title" | |||||
block | |||||
border | |||||
/> | |||||
</div> | |||||
</div> | |||||
</fieldset> | |||||
</form> | |||||
<form> | |||||
<div> | |||||
Hi, my name is | |||||
{' '} | |||||
<Freeform.TextInput | |||||
border | |||||
label="Name" | |||||
size="small" | |||||
/> | |||||
{' '} | |||||
but you can call me | |||||
{' '} | |||||
<Freeform.TextInput | |||||
border | |||||
label="Nickname" | |||||
size="small" | |||||
/> | |||||
. | |||||
</div> | |||||
</form> | |||||
</Subsection> | |||||
<Subsection title="Alternate"> | |||||
<div className="grid md:grid-cols-2 gap-4"> | |||||
<div> | |||||
<Freeform.TextInput | |||||
variant="alternate" | |||||
size="small" | |||||
label="TextInput ffgg" | |||||
hint="Type anything here… ffgg" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
border | |||||
variant="alternate" | |||||
size="small" | |||||
label="TextInput ffgg" | |||||
hint="Type anything here… ffgg" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
variant="alternate" | |||||
label="TextInput ffgg" | |||||
hint="Type anything here… ffgg" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
border | |||||
variant="alternate" | |||||
label="TextInput ffgg" | |||||
hint="Type anything here… ffgg" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
variant="alternate" | |||||
size="large" | |||||
label="TextInput ffgg" | |||||
hint="Type anything here… ffgg" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
border | |||||
block | |||||
variant="alternate" | |||||
size="large" | |||||
label="TextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
variant="alternate" | |||||
label="TextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.TextInput | |||||
variant="alternate" | |||||
border | |||||
label="TextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
</div> | |||||
</Subsection> | |||||
</Section> | |||||
<Section title="MaskedTextInput"> | |||||
<Subsection title="Default"> | |||||
<div className="grid md:grid-cols-2 gap-4"> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
size="small" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
border | |||||
size="small" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
border | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
size="large" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
border | |||||
size="large" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
border | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
</div> | |||||
</Subsection> | |||||
<Subsection title="Alternate"> | |||||
<div className="grid md:grid-cols-2 gap-4"> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
variant="alternate" | |||||
size="small" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
border | |||||
variant="alternate" | |||||
size="small" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
variant="alternate" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
border | |||||
variant="alternate" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
variant="alternate" | |||||
size="large" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
border | |||||
block | |||||
variant="alternate" | |||||
size="large" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
variant="alternate" | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MaskedTextInput | |||||
variant="alternate" | |||||
border | |||||
label="MaskedTextInput" | |||||
hint="Type anything here…" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
</div> | |||||
</Subsection> | |||||
</Section> | |||||
<Section title="MultilineTextInput"> | |||||
<Subsection title="Default"> | |||||
<div className="grid md:grid-cols-2 gap-4"> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
size="small" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
border | |||||
size="small" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
border | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
size="large" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
border | |||||
size="large" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
border | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
</div> | |||||
</Subsection> | |||||
<Subsection title="Alternate"> | |||||
<div className="grid md:grid-cols-2 gap-4"> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
variant="alternate" | |||||
size="small" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
border | |||||
variant="alternate" | |||||
size="small" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
variant="alternate" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
border | |||||
variant="alternate" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
variant="alternate" | |||||
size="large" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
border | |||||
block | |||||
variant="alternate" | |||||
size="large" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
variant="alternate" | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
<div> | |||||
<Freeform.MultilineTextInput | |||||
variant="alternate" | |||||
border | |||||
label="MultilineTextInput" | |||||
hint="Type anything here…" | |||||
indicator="A" | |||||
block | |||||
disabled | |||||
/> | |||||
</div> | |||||
</div> | |||||
</Subsection> | |||||
</Section> | |||||
</DefaultLayout> | |||||
); | |||||
}; | |||||
export default FreeformPage; |
@@ -1,469 +0,0 @@ | |||||
import { NextPage } from 'next'; | |||||
import * as Navigation from '@tesseract-design/web-navigation-react'; | |||||
import * as Info from '@tesseract-design/web-information-react'; | |||||
const ActionPage: NextPage = () => { | |||||
return ( | |||||
<main className="my-16 md:my-32"> | |||||
<section> | |||||
<div className="container mx-auto px-4"> | |||||
<h1> | |||||
Navigation | |||||
</h1> | |||||
<div> | |||||
<section> | |||||
<h2> | |||||
LinkButton | |||||
</h2> | |||||
<div> | |||||
<section> | |||||
<h3>Variants</h3> | |||||
<div> | |||||
<div className="grid md:grid-cols-2 gap-4 my-4"> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
variant="bare" | |||||
href="#" | |||||
block | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
variant="filled" | |||||
block | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
variant="outline" | |||||
block | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
variant="filled" | |||||
block | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
disabled | |||||
href="#" | |||||
variant="bare" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
variant="filled" | |||||
block | |||||
disabled | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
variant="outline" | |||||
block | |||||
disabled | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
variant="filled" | |||||
block | |||||
disabled | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<section> | |||||
<h3>Sizes</h3> | |||||
<div> | |||||
<div className="grid md:grid-cols-2 gap-4 my-4"> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="outline" | |||||
size="small" | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="filled" | |||||
size="small" | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="outline" | |||||
size="medium" | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="filled" | |||||
size="medium" | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="outline" | |||||
size="large" | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="filled" | |||||
size="large" | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<section> | |||||
<h3>Compact</h3> | |||||
<div> | |||||
<div className="grid md:grid-cols-2 gap-4 my-4"> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
compact | |||||
variant="outline" | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
compact | |||||
variant="filled" | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="outline" | |||||
compact | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
compact | |||||
variant="filled" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="outline" | |||||
compact | |||||
size="small" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
compact | |||||
variant="filled" | |||||
size="small" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="outline" | |||||
compact | |||||
size="large" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
compact | |||||
variant="filled" | |||||
size="large" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="outline" | |||||
compact | |||||
menuItem | |||||
size="small" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
compact | |||||
size="small" | |||||
variant="filled" | |||||
menuItem | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="outline" | |||||
compact | |||||
menuItem | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
compact | |||||
variant="filled" | |||||
menuItem | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
variant="outline" | |||||
compact | |||||
menuItem | |||||
size="large" | |||||
subtext={ | |||||
<> | |||||
Subtext | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Button | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
<div> | |||||
<Navigation.LinkButton | |||||
block | |||||
compact | |||||
size="large" | |||||
variant="filled" | |||||
menuItem | |||||
subtext={ | |||||
<> | |||||
Very Long Line of Subtext That Spans More Than The Component Width For Testing Overflow | |||||
</> | |||||
} | |||||
badge={ | |||||
<Info.Badge | |||||
rounded | |||||
> | |||||
69 | |||||
</Info.Badge> | |||||
} | |||||
href="#" | |||||
> | |||||
Very Long Line of Text That Spans More Than The Component Width For Testing Overflow | |||||
</Navigation.LinkButton> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
</div> | |||||
</section> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
</main> | |||||
) | |||||
} | |||||
export default ActionPage |
@@ -1,128 +0,0 @@ | |||||
import * as React from 'react'; | |||||
import { NextPage } from 'next'; | |||||
import * as TesseractNumber from '@tesseract-design/web-number-react'; | |||||
import {Section, Subsection} from '@/components/Section'; | |||||
const NumberPage: NextPage = () => { | |||||
return ( | |||||
<main className="my-16 md:my-32"> | |||||
<Section title="NumberSpinner"> | |||||
<Subsection title="Default"> | |||||
<TesseractNumber.NumberSpinner | |||||
min={-100} | |||||
max={100} | |||||
step="any" | |||||
label="Step" | |||||
border | |||||
enhanced | |||||
size="small" | |||||
/> | |||||
<TesseractNumber.NumberSpinner | |||||
min={-100} | |||||
max={100} | |||||
step="any" | |||||
label="Step" | |||||
border | |||||
enhanced | |||||
/> | |||||
<TesseractNumber.NumberSpinner | |||||
min={-100} | |||||
max={100} | |||||
step="any" | |||||
label="Step" | |||||
border | |||||
enhanced | |||||
size="large" | |||||
/> | |||||
</Subsection> | |||||
</Section> | |||||
<Section title="Slider"> | |||||
<Subsection title="Default"> | |||||
<TesseractNumber.Slider | |||||
min={-100} | |||||
max={100} | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="Default (with tick marks)"> | |||||
<TesseractNumber.Slider | |||||
min={-100} | |||||
max={100} | |||||
> | |||||
<optgroup label="Test Values"> | |||||
<option value={-100}> | |||||
Lowest | |||||
</option> | |||||
<option value={25}> | |||||
日本語 | |||||
</option> | |||||
<option value={50} /> | |||||
<option value={100}> | |||||
Highest | |||||
</option> | |||||
<option value={200}> | |||||
Out of bounds | |||||
</option> | |||||
</optgroup> | |||||
</TesseractNumber.Slider> | |||||
</Subsection> | |||||
<Subsection title="Vertical"> | |||||
<TesseractNumber.Slider | |||||
min={-100} | |||||
max={100} | |||||
orient="vertical" | |||||
> | |||||
<optgroup label="Test Values"> | |||||
<option value={-100}> | |||||
Lowest | |||||
</option> | |||||
<option value={25}> | |||||
日本語 | |||||
</option> | |||||
<option value={50} /> | |||||
<option value={100}> | |||||
Highest | |||||
</option> | |||||
<option value={200}> | |||||
Out of bounds | |||||
</option> | |||||
</optgroup> | |||||
</TesseractNumber.Slider> | |||||
<TesseractNumber.Slider | |||||
min={-100} | |||||
max={100} | |||||
orient="vertical" | |||||
> | |||||
<optgroup label="Test Values"> | |||||
<option value={-100}> | |||||
Lowest | |||||
</option> | |||||
<option value={25}> | |||||
日本語 | |||||
</option> | |||||
<option value={50} /> | |||||
<option value={100}> | |||||
Highest | |||||
</option> | |||||
<option value={200}> | |||||
Out of bounds | |||||
</option> | |||||
</optgroup> | |||||
</TesseractNumber.Slider> | |||||
A | |||||
</Subsection> | |||||
</Section> | |||||
<Section title="Matrix"> | |||||
<h2> | |||||
Matrix | |||||
</h2> | |||||
<div> | |||||
TODO | |||||
<input type="range" /> | |||||
<input type="range" /> | |||||
</div> | |||||
</Section> | |||||
</main> | |||||
) | |||||
} | |||||
export default NumberPage; |
@@ -1,35 +0,0 @@ | |||||
import { NextPage } from 'next'; | |||||
import { DefaultLayout } from '@/components/DefaultLayout'; | |||||
const PresentationPage: NextPage = () => { | |||||
return ( | |||||
<DefaultLayout | |||||
title="Code" | |||||
> | |||||
<main className="mt-8 mb-16 md:mt-16 md:mb-32"> | |||||
<section> | |||||
<div className="container mx-auto px-4"> | |||||
<h2> | |||||
Tabs | |||||
</h2> | |||||
<div> | |||||
TODO | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<section> | |||||
<div className="container mx-auto px-4"> | |||||
<h2> | |||||
Accordion | |||||
</h2> | |||||
<div> | |||||
TODO | |||||
</div> | |||||
</div> | |||||
</section> | |||||
</main> | |||||
</DefaultLayout> | |||||
) | |||||
} | |||||
export default PresentationPage; |
@@ -1,66 +0,0 @@ | |||||
import {NextPage} from 'next'; | |||||
import {DefaultLayout} from '@/components/DefaultLayout'; | |||||
import {Section, Subsection} from '@/components/Section'; | |||||
import * as Temporal from '@tesseract-design/web-temporal-react'; | |||||
import * as TemporalWip from '@/components/temporal'; | |||||
const TemporalPage: NextPage = () => { | |||||
return ( | |||||
<DefaultLayout title="Temporal"> | |||||
<Section title="DateDropdown"> | |||||
<Subsection title="Default"> | |||||
<Temporal.DateDropdown | |||||
label="Birthday" | |||||
border | |||||
/> | |||||
</Subsection> | |||||
</Section> | |||||
<Section title="TimeSpinner"> | |||||
<Subsection title="Default"> | |||||
<Temporal.TimeSpinner | |||||
label="Time" | |||||
variant="default" | |||||
border | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="Step"> | |||||
<Temporal.TimeSpinner | |||||
label="Time" | |||||
variant="default" | |||||
border | |||||
step="00:15:00" | |||||
/> | |||||
</Subsection> | |||||
<Subsection title="Step + Display Seconds"> | |||||
<Temporal.TimeSpinner | |||||
label="Time" | |||||
variant="default" | |||||
border | |||||
step="00:00:05" | |||||
displaySeconds | |||||
/> | |||||
</Subsection> | |||||
</Section> | |||||
<Section title="YearMonthInput"> | |||||
<Subsection title="Default"> | |||||
<TemporalWip.YearMonthInput | |||||
label="Month" | |||||
variant="default" | |||||
border | |||||
/> | |||||
</Subsection> | |||||
</Section> | |||||
<Section title="WeekInput"> | |||||
<Subsection title="Default"> | |||||
<TemporalWip.WeekInput | |||||
label="Vacation" | |||||
variant="default" | |||||
border | |||||
/> | |||||
</Subsection> | |||||
</Section> | |||||
</DefaultLayout> | |||||
) | |||||
} | |||||
export default TemporalPage; |
@@ -1,136 +1,24 @@ | |||||
import type {GetStaticProps, NextPage} from 'next'; | import type {GetStaticProps, NextPage} from 'next'; | ||||
import Link from 'next/link'; | |||||
import * as fs from 'fs/promises'; | import * as fs from 'fs/promises'; | ||||
import * as path from 'path'; | import * as path from 'path'; | ||||
import { Layouts, Widgets } from '@tesseract-design/viewfinder-react'; | |||||
import * as React from 'react' | import * as React from 'react' | ||||
import {useRouter} from 'next/router'; | import {useRouter} from 'next/router'; | ||||
import {Brand} from '@/components/Brand'; | |||||
import ReactMarkdown from 'react-markdown'; | import ReactMarkdown from 'react-markdown'; | ||||
import {Layouts} from '@tesseract-design/viewfinder-react'; | |||||
type Page = { | |||||
id: string, | |||||
href: string, | |||||
label: string, | |||||
export interface Props { | |||||
markdown: string, | |||||
} | } | ||||
type Props = { | |||||
componentPages: Page[], | |||||
examplePages: Page[], | |||||
} | |||||
const createSidebarPageLink = (p: Page) => ( | |||||
<div | |||||
key={p.id} | |||||
> | |||||
<Link | |||||
href={p.href} | |||||
className="no-underline font-semibold m-0 p-0 leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
{p.label} | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
</Link> | |||||
</div> | |||||
); | |||||
const IndexPage: NextPage<Props> = ({ | const IndexPage: NextPage<Props> = ({ | ||||
componentPages, | |||||
examplePages, | |||||
markdown, | |||||
}) => { | }) => { | ||||
const router = useRouter(); | const router = useRouter(); | ||||
const sidebarOpen = router.query.open === 'sidebar'; | |||||
return ( | return ( | ||||
<Layouts.LeftSidebar.Root | |||||
topBarWidget={ | |||||
<Widgets.TopBar | |||||
span="wide" | |||||
brand={ | |||||
<Link | |||||
href="/" | |||||
className="no-underline block" | |||||
> | |||||
<Brand /> | |||||
</Link> | |||||
} | |||||
menuLink={ | |||||
<Link | |||||
href={{ | |||||
query: { | |||||
open: 'sidebar', | |||||
}, | |||||
}} | |||||
className="no-underline p-0 m-0" | |||||
> | |||||
<svg | |||||
className="w-6 h-6 fill-none stroke-current stroke-2 linejoin-round linecap-round" | |||||
viewBox="0 0 24 24" | |||||
role="presentation" | |||||
> | |||||
<line x1="3" y1="12" x2="21" y2="12"/> | |||||
<line x1="3" y1="6" x2="21" y2="6"/> | |||||
<line x1="3" y1="18" x2="21" y2="18"/> | |||||
</svg> | |||||
</Link> | |||||
} | |||||
/> | |||||
} | |||||
sidebarBaseWidget={ | |||||
<Widgets.LeftSidebarBase | |||||
open={router.query.open === 'sidebar'} | |||||
> | |||||
<div className="min-h-full py-4 flex flex-col gap-8"> | |||||
<div> | |||||
<nav> | |||||
<h1> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
Categories | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
</h1> | |||||
<div className="flex flex-col gap-2 my-8"> | |||||
{componentPages.map(createSidebarPageLink)} | |||||
</div> | |||||
</nav> | |||||
<nav> | |||||
<h1> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
Examples | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
</h1> | |||||
<div className="flex flex-col gap-4 my-4"> | |||||
{examplePages.map(createSidebarPageLink)} | |||||
</div> | |||||
</nav> | |||||
</div> | |||||
<div className="mb-8"> | |||||
<Layouts.LeftSidebar.SidebarContentContainer> | |||||
<div className="flex gap-8"> | |||||
<Link | |||||
href="https://code.modal.sh/tesseract-design/tesseract" | |||||
className="no-underline font-semibold leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
Repo | |||||
</Link> | |||||
<Link | |||||
href="https://code.modal.sh/tesseract-design/tesseract" | |||||
className="no-underline font-semibold leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
Website | |||||
</Link> | |||||
<Link | |||||
href="https://code.modal.sh/tesseract-design/tesseract/issues" | |||||
className="no-underline font-semibold leading-none h-8 flex items-center cursor-pointer uppercase text-sm" | |||||
> | |||||
Issues | |||||
</Link> | |||||
</div> | |||||
</Layouts.LeftSidebar.SidebarContentContainer> | |||||
</div> | |||||
</div> | |||||
</Widgets.LeftSidebarBase> | |||||
} | |||||
> | |||||
<Layouts.LeftSidebar.MainContentContainer> | |||||
<Layouts.Basic.Root> | |||||
<Layouts.Basic.ContentContainer> | |||||
<ReactMarkdown | <ReactMarkdown | ||||
className="my-12 leading-loose" | className="my-12 leading-loose" | ||||
components={{ | components={{ | ||||
@@ -148,104 +36,21 @@ const IndexPage: NextPage<Props> = ({ | |||||
), | ), | ||||
}} | }} | ||||
> | > | ||||
{`# Tesseract | |||||
## Design | |||||
- Tesseract components follow a strict and simple design philosophy. | |||||
- The aesthetics of the elements are rigid--any element which users can | |||||
interact with should be easily recognizable--they are determined by the | |||||
usage of the chosen accent color. | |||||
- The look and feel of the elements are designed to be less opinionated | |||||
as possible. | |||||
## Engineering | |||||
- Every component is a derivative of an existing HTML element, | |||||
thus any Tesseract component can substitute for any HTML element | |||||
with added capabilities like improved user experience and consistency. | |||||
- In case of overloaded HTML elements such as \`<input>\`, Tesseract | |||||
dissects the element into multiple components each having a single | |||||
defined behavior. | |||||
- Tesseract components gracefully degrade to their native counterparts, | |||||
allowing user agents without client-side JavaScript to still use the | |||||
components with minimal loss of functionality. | |||||
- Tesseract components render Web-compliant HTML and CSS, thus | |||||
making it resilient to future changes in the HTML/CSS specifications. | |||||
- Tesseract components are designed to be used with popular JavaScript | |||||
frameworks like React. Consumption of the components using the framework | |||||
of choice should be seamless, even with the use of form-handling libraries. | |||||
- Terminal-based browsers such as Lynx are used to test the components | |||||
for accessibility and graceful degradation. | |||||
## Accessibility | |||||
- Components are made to be accessible according to Web standards (WAI-ARIA). | |||||
- Focus handling is managed sensibly to facilitate functional | |||||
keyboard navigation. | |||||
- In cases where there are improvements in user experience, some | |||||
elements may have different markup and appearance. Tesseract | |||||
ensures components are still usable on most assistive technologies given | |||||
both versions of the user interface. | |||||
- All components are named in order to depict the purpose, the nature of data | |||||
being operated, and UX expectations. | |||||
`} | |||||
{markdown} | |||||
</ReactMarkdown> | </ReactMarkdown> | ||||
</Layouts.LeftSidebar.MainContentContainer> | |||||
</Layouts.LeftSidebar.Root> | |||||
) | |||||
</Layouts.Basic.ContentContainer> | |||||
</Layouts.Basic.Root> | |||||
); | |||||
} | } | ||||
export const getStaticProps: GetStaticProps = async () => { | |||||
const pagesPath = path.resolve('src/pages'); | |||||
const categoriesPath = path.resolve(pagesPath, 'categories'); | |||||
const categoriesRaw = await fs.readdir(categoriesPath); | |||||
const categoriesIndexPage = await Promise.all( | |||||
categoriesRaw.map(async (c) => { | |||||
const indexPath = await path.resolve(categoriesPath, c, 'index.tsx'); | |||||
try { | |||||
const statResult = await fs.stat(indexPath); | |||||
return [c, statResult.isFile()]; | |||||
} catch { | |||||
// noop | |||||
} | |||||
return [c, false]; | |||||
}) | |||||
) as [string, boolean][]; | |||||
const categories = categoriesIndexPage | |||||
.filter(([, hasIndexPage]) => hasIndexPage) | |||||
.map(([key]) => key); | |||||
const examplesPath = path.resolve(pagesPath, 'examples'); | |||||
const examplesRaw = await fs.readdir(examplesPath); | |||||
const examplesIndexPage = await Promise.all( | |||||
examplesRaw.map(async (c) => { | |||||
const indexPath = await path.resolve(examplesPath, c, 'index.tsx'); | |||||
try { | |||||
const statResult = await fs.stat(indexPath); | |||||
return [c, statResult.isFile()]; | |||||
} catch { | |||||
// noop | |||||
} | |||||
export const getStaticProps: GetStaticProps = async (ctx) => { | |||||
const props = {} as Record<string, unknown>; | |||||
return [c, false]; | |||||
}) | |||||
) as [string, boolean][]; | |||||
const examples = examplesIndexPage | |||||
.filter(([, hasIndexPage]) => hasIndexPage) | |||||
.map(([key]) => key); | |||||
const readmePath = path.resolve('../../README.md'); | |||||
props.markdown = await fs.readFile(readmePath, 'utf-8'); | |||||
return { | return { | ||||
props: { | |||||
componentPages: categories.map((c) => ({ | |||||
id: c, | |||||
href: `/categories/${c}`, | |||||
label: c.split('-').map((cc) => cc.slice(0, 1).toUpperCase() + cc.slice(1)).join(' '), | |||||
})), | |||||
examplePages: examples.map((e) => ({ | |||||
id: e, | |||||
href: `/examples/${e}`, | |||||
label: e.split('-').map((ee) => ee.slice(0, 1).toUpperCase() + ee.slice(1)).join(' '), | |||||
})), | |||||
}, | |||||
props, | |||||
}; | }; | ||||
}; | }; | ||||
@@ -0,0 +1,8 @@ | |||||
{ | |||||
"entryPoints": ["../../categories/**"], | |||||
"entryPointStrategy": "packages", | |||||
"name": "@tesseract-design/tesseract-web-react", | |||||
"json": "typedoc.data.json", | |||||
"pretty": true, | |||||
"tsconfig": "../../tsconfig.json" | |||||
} |
@@ -1,5 +1,9 @@ | |||||
{ | { | ||||
"exclude": ["node_modules"], | |||||
"include": ["categories/**/src/*"], | |||||
"exclude": [ | |||||
"node_modules", | |||||
"**/*.test.{ts,js,tsx,jsx}" | |||||
], | |||||
"compilerOptions": { | "compilerOptions": { | ||||
"module": "ESNext", | "module": "ESNext", | ||||
"lib": ["ESNext", "DOM"], | "lib": ["ESNext", "DOM"], | ||||
@@ -0,0 +1,4 @@ | |||||
{ | |||||
"$schema": "https://typedoc.org/schema.json", | |||||
"includeVersion": true | |||||
} |