From fa1d5d854db3ad98170876fc477d502ed759d93f Mon Sep 17 00:00:00 2001 From: harang Date: Tue, 27 Oct 2026 21:42:24 +0900 Subject: [PATCH] feat: add fixed-layout typewriter reveals Reuse existing progress for discrete native-text visibility while preserving composed effects and the completed token layout. Keep decomposed Hangul clusters and UTF-16 source offsets intact in the grapheme fallback. Update examples, English/Korean documentation, capability gates, declaration checks, and regression coverage. --- README.ko.md | 52 ++- README.md | 52 ++- example/src/App.tsx | 94 +++- packages/text-motion/README.ko.md | 73 ++- packages/text-motion/README.md | 73 ++- .../scripts/check-declarations.mjs | 4 + .../src/__tests__/capability-types.test.ts | 17 + .../text-motion/src/__tests__/effects.test.ts | 17 +- .../src/__tests__/nativeTextPlayback.test.ts | 14 + .../src/__tests__/rendererMotion.test.ts | 22 + .../text-motion/src/__tests__/split.test.ts | 35 ++ .../src/__tests__/typewriter.test.tsx | 432 ++++++++++++++++++ packages/text-motion/src/effects/index.ts | 1 + .../text-motion/src/effects/typewriter.ts | 16 + packages/text-motion/src/index.tsx | 2 +- .../text-motion/src/renderers/nativeText.tsx | 7 +- .../src/renderers/nativeTextPlayback.ts | 1 + .../src/renderers/rendererMotion.ts | 12 +- packages/text-motion/src/split/segmenter.ts | 12 +- 19 files changed, 914 insertions(+), 22 deletions(-) create mode 100644 packages/text-motion/src/__tests__/typewriter.test.tsx create mode 100644 packages/text-motion/src/effects/typewriter.ts diff --git a/README.ko.md b/README.ko.md index 096f8e1..e550ee1 100644 --- a/README.ko.md +++ b/README.ko.md @@ -159,13 +159,60 @@ Responsive hero title, section heading, 짧은 product copy처럼 실제 시각 `overlayText()`는 rendered line frame에 적용되는 built-in style-transform effect(`fade`, `rise`, `slide`, `shake`, `scale`, `pulse`)도 받습니다. 내부적으로 `lineReveal()`은 opacity를 line frame에 적용하고, vertical reveal offset만 line mask 안의 paragraph copy에 적용합니다. 그래서 `lineReveal().and(scale())` 또는 `pulse()` 조합은 measured line center를 기준으로 커지며 renderer 자신의 line mask에 잘리지 않습니다. +## Typewriter + +짧은 인사말, 온보딩 문구, 라벨을 한 글자씩 보여주면서 완성 문장의 공간과 줄바꿈을 유지하고 싶다면 `typewriter()`를 사용하세요. 패키지 root에서 가져오는 옵션 없는 effect이며, preset이나 별도 renderer가 아닙니다. + +```tsx +import { + defineTextMotion, + graphemes, + nativeText, + parentLabelPolicy, + stagger, + typewriter, + useTextMotionControls, +} from '@react-native-motion-kit/text-motion'; +import { Button } from 'react-native'; + +const TypewriterText = defineTextMotion() + .split(graphemes()) + .layout(nativeText()) + .timeline(stagger(0.04)) + .effect(typewriter()) + .motion({ kind: 'timing', options: { duration: 0 } }) + .accessibility(parentLabelPolicy({ reducedMotion: 'final-state' })) + .component(); + +export function Greeting() { + const controls = useTextMotionControls(); + + return ( + <> + 안녕 세계! 👩🏽‍💻 +