npm package: @getbluma/tiktok-text
Description: TikTok-style text component with outline effects
Author: Bluma
Latest version: 1.0.6

# @getbluma/tiktok-text

TikTok-style text components with outline effects using SVG rendering.

## Installation

```bash
npm install @getbluma/tiktok-text
# or
pnpm add @getbluma/tiktok-text
```

## Font Setup

This package includes the TikTok Sans variable font. Use the built-in helper to load it:

```tsx
import { useEffect } from 'react';
import { loadTikTokFont } from '@getbluma/tiktok-text';

export const App: React.FC = () => {
  useEffect(() => {
    loadTikTokFont('/fonts/TikTokSans-Variable.ttf');
  }, []);

  return <TikTokText>Hello World</TikTokText>;
};
```

Copy the font from `node_modules/@getbluma/tiktok-text/fonts/` to your public folder.

## Components

### TikTokText

Simple text without outline.

```tsx
import { TikTokText } from '@getbluma/tiktok-text';

<TikTokText>Hello World</TikTokText>
<TikTokText size="xl" weight={550}>Big Text</TikTokText>
<TikTokText theme="cyan">Cyan themed text</TikTokText>
```

### TikTokTextOutline

Text with SVG stroke outline (TikTok caption style).

```tsx
import { TikTokTextOutline } from '@getbluma/tiktok-text';

// Using theme (recommended)
<TikTokTextOutline theme="cyan">Cyan Theme</TikTokTextOutline>
<TikTokTextOutline theme="paleYellow">Pale Yellow Theme</TikTokTextOutline>
<TikTokTextOutline theme="peach">Peach Theme</TikTokTextOutline>

// Custom colors
<TikTokTextOutline color="#FFFF00" outlineColor="#FF0000">
  Yellow with Red Outline
</TikTokTextOutline>

// With gradient fill
<TikTokTextOutline
  gradient={{
    type: 'linear',
    angle: 90,
    stops: [
      { offset: '0%', color: '#FF0000' },
      { offset: '100%', color: '#FFFF00' }
    ]
  }}
>
  Gradient Text
</TikTokTextOutline>
```

### TikTokTextBlock

Text with gooey/rounded background effect (perfect for multi-line captions).

```tsx
import { TikTokTextBlock } from '@getbluma/tiktok-text';

// Using theme (recommended)
<TikTokTextBlock theme="purple">Hello World</TikTokTextBlock>
<TikTokTextBlock theme="paleYellow" size="m" weight={450}>
  {"- from someone who got into stanford,\n yale, & other t20's! ('29)"}
</TikTokTextBlock>
<TikTokTextBlock theme="peach" weight={550}>
  {"you are killing\nme inside"}
</TikTokTextBlock>

// Step indicator style (white bg, black text)
<TikTokTextBlock theme="white">
  1. first step title
</TikTokTextBlock>

// Multi-line text with gooey wrap effect
<TikTokTextBlock theme="lavender" size="l" weight={550}>
  {"lavender theme\nwith two lines"}
</TikTokTextBlock>

// Using custom hex colors (overrides theme)
<TikTokTextBlock backgroundColor="#FF69B4" color="#FFFFFF">
  Custom Pink
</TikTokTextBlock>

// With maxWidth for auto word-wrapping
<TikTokTextBlock theme="purple" maxWidth={500}>
  This text will automatically wrap when it exceeds 500px width
</TikTokTextBlock>

// With custom font
<TikTokTextBlock theme="cyan" fontFamily="Arial, sans-serif">
  Custom Font Text
</TikTokTextBlock>
```

## Props

### Common Props (all components)

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `ReactNode` | required | Text content |
| `size` | `TextSize \| number` | `'m'` (48px) | Size preset or custom pixels |
| `weight` | `FontWeight \| number` | `'semibold'` (550) | Weight preset or custom 100-900 |
| `theme` | `ColorPreset` | - | Color theme preset |
| `color` | `string` | from theme | Text color (overrides theme) |
| `style` | `CSSProperties` | `{}` | Additional CSS styles |
| `className` | `string` | `''` | CSS class name |

### Size Presets

| Preset | Pixels |
|--------|--------|
| `xs` | 24px |
| `s` | 32px |
| `m` | 48px |
| `l` | 64px |
| `xl` | 84px |
| `xxl` | 96px |
| `xxxl` | 128px |

### Weight Presets

| Preset | Value |
|--------|-------|
| `light` | 250 |
| `regular` | 350 |
| `medium` | 450 |
| `semibold` | 550 |
| `bold` | 650 |
| `extrabold` | 750 |
| `black` | 850 |

### Color Themes

Themes provide coordinated color pairs (primary for fill/background, secondary for outline/text):

| Theme | Primary | Secondary | Best For |
|-------|---------|-----------|----------|
| `white` | #FFFFFF | #000000 | Light backgrounds |
| `black` | #000000 | #FFFFFF | Dark text |
| `cyan` | #00A8CD | #FFFFFF | Bright accents |
| `paleYellow` | #FFF7A7 | #B0642A | Warm highlights |
| `peach` | #F8E2D7 | #DF3932 | Soft warm tones |
| `pink` | #FAC2FF | #922BAA | Feminine accents |
| `lavender` | #B4AFFF | #402FB0 | Soft purple |
| `skyBlue` | #8ADDEB | #105B68 | Cool tones |
| `periwinkle` | #95ABFF | #21337A | Blue-purple |
| `purple` | #9A66F1 | #FFFFFF | Bold purple |
| `indigo` | #5756D5 | #FFFFFF | Deep purple-blue |
| `blue` | #3496EF | #FFFFFF | Standard blue |
| `darkBlue` | #2444B3 | #FFFFFF | Deep blue |
| `green` | #77C25D | #FFFFFF | Natural green |
| `teal` | #00B09B | #FFFFFF | Blue-green |
| `yellow` | #F2CE46 | #FFFFFF | Bright yellow |
| `orange` | #FF923D | #FFFFFF | Warm orange |
| `red` | #EA4040 | #FFFFFF | Alert red |
| `magenta` | #CA2FFE | #FFFFFF | Vivid pink |
| `dustyRose` | #D26793 | #FFFFFF | Muted pink |
| `brown` | #412E28 | #FFFFFF | Earth tone |
| `rust` | #B2533D | #FFFFFF | Warm brown |
| `olive` | #A4895A | #FFFFFF | Muted green |
| `darkGreen` | #32523B | #FFFFFF | Forest green |
| `darkTeal` | #2E698E | #FFFFFF | Deep teal |
| `navy` | #223655 | #FFFFFF | Dark blue |
| `gray` | #92979D | #FFFFFF | Neutral |
| `darkGray` | #333333 | #FFFFFF | Dark neutral |

### TikTokTextOutline Additional Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `outlineColor` | `string` | from theme | Stroke color (overrides theme) |
| `align` | `'left' \| 'center' \| 'right'` | `'center'` | Text alignment |
| `maxCharsPerLine` | `number` | - | Text wrapping threshold |
| `lineHeight` | `number` | `1.4` | Line height multiplier |
| `letterSpacing` | `number` | `0` | Letter spacing in pixels |
| `wordSpacing` | `number` | `0` | Word spacing in pixels |
| `strokeWidth` | `number` | auto | Explicit stroke width |
| `strokeRatio` | `number` | `0.16` | Stroke ratio relative to font size |
| `italic` | `boolean` | `false` | Italic style |
| `opacity` | `number` | `1` | Global opacity (0-1) |
| `fillOpacity` | `number` | - | Fill-only opacity |
| `strokeOpacity` | `number` | - | Stroke-only opacity |
| `textDecoration` | `TextDecoration` | `'none'` | underline, overline, line-through |
| `textTransform` | `TextTransform` | `'none'` | uppercase, lowercase, capitalize |
| `rotate` | `number` | `0` | Rotation in degrees |
| `skewX` | `number` | `0` | Horizontal skew in degrees |
| `skewY` | `number` | `0` | Vertical skew in degrees |
| `scaleX` | `number` | `1` | Horizontal scale |
| `scaleY` | `number` | `1` | Vertical scale |
| `dx` | `number` | `0` | Horizontal offset |
| `dy` | `number` | `0` | Vertical offset |
| `shadow` | `TextShadow` | - | Drop shadow config |
| `gradient` | `TextGradient` | - | Gradient fill config |
| `svgWidth` | `number` | `1000` | SVG viewBox width |

### TikTokTextBlock Additional Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `backgroundColor` | `string` | from theme | Background color (overrides theme) |
| `align` | `'left' \| 'center' \| 'right'` | `'center'` | Text alignment |
| `textTransform` | `TextTransform` | `'lowercase'` | Text transform |
| `lineHeight` | `number` | `1.4` | Line height multiplier (auto-boosted for small sizes) |
| `letterSpacing` | `number` | `-1` | Letter spacing in pixels |
| `paddingX` | `number` | `0.5` | Horizontal padding in em units |
| `paddingTop` | `number` | `6` | Top padding in pixels |
| `paddingBottom` | `number` | `10` | Bottom padding in pixels |
| `blurRadius` | `number` | auto | Blur radius for gooey effect (auto-scales with font size) |
| `maxWidth` | `number \| string` | - | Max width for text wrapping (enables word wrap when set) |
| `fontFamily` | `string` | TikTok Sans | Custom font family |
| `filterId` | `string` | auto | Custom SVG filter ID |

### Shadow Config

```tsx
shadow={{
  offsetX: 4,
  offsetY: 4,
  blur: 8,
  color: 'rgba(0,0,0,0.5)'
}}
```

### Gradient Config

```tsx
gradient={{
  type: 'linear', // or 'radial'
  angle: 90,      // for linear gradients
  stops: [
    { offset: '0%', color: '#FF0000' },
    { offset: '100%', color: '#FFFF00' }
  ]
}}
```

## Utilities

### loadTikTokFont

Helper function to load the TikTok Sans variable font.

```tsx
import { loadTikTokFont, isTikTokFontLoaded } from '@getbluma/tiktok-text';

// Load the font
await loadTikTokFont('/path/to/TikTokSans-Variable.ttf');

// Check if loaded
if (isTikTokFontLoaded()) {
  console.log('Font ready!');
}
```

### wrapText

Helper function to wrap text by character count.

```tsx
import { wrapText } from '@getbluma/tiktok-text';

const lines = wrapText('Long text that needs wrapping', 20);
// Returns: ['Long text that needs', 'wrapping']
```

## Exports

```tsx
// Components
export { TikTokText, TikTokTextOutline, TikTokTextBlock } from '@getbluma/tiktok-text';

// Font utilities
export { loadTikTokFont, isTikTokFontLoaded, TIKTOK_SANS } from '@getbluma/tiktok-text';

// Helper functions
export { wrapText } from '@getbluma/tiktok-text';

// Types
export type {
  TikTokTextProps,
  TikTokTextOutlineProps,
  TikTokTextBlockProps,
  ColorPreset,
  TextSize,
  FontWeight,
  TextAlign,
  TextDecoration,
  TextTransform,
  TextShadow,
  TextGradient,
  GradientStop,
} from '@getbluma/tiktok-text';
```

## License

MIT

TikTok Sans font is licensed under SIL Open Font License.