Skip to content

feat(compose): add Clip node for embedding pattern values in the DSL #90

Description

@l2hyunwoo

Summary

The core builder DSL embeds a compiled pattern with include(pattern) (dsl/HapticPatternScope.kt:175). The Compose DSL has no counterpart, so algebra results cannot be placed on a timeline next to inline nodes. Add one:

Jindong(speed) {
    Sequence {
        Clip(heartbeat.timeStretch(1f / speed))
        Delay(200.ms)
        Haptic(60.ms, HapticIntensity.MEDIUM)
    }
}

Scope:

  • @Composable fun JindongScope.Clip(pattern: HapticPattern) in jindong-compose, wrapping the existing PatternElement. No core changes.
  • fun clip(pattern: HapticPattern) alias for include on HapticPatternScope, so both DSLs share one vocabulary. include stays as is.

Why "Clip"

Content-emitting composables are named with nouns, which rules out Include. Pattern is too generic: everything in this DSL is a pattern, and the name invites Pattern(Sequence { ... }) misreadings. A clip is a prebuilt, self-contained unit placed on a timeline, which is exactly what this node does, and the word cannot be mistaken for something that wraps inline content.

Semantics

The composition inside Jindong is single-shot: compilePattern composes once and disposes the host (Jindong.kt:120-127), so ComposeNode update blocks never re-run after insertion. Clip therefore follows the same idiom as every other node (value captured at compile time), and reactivity comes from threading the pattern through the trigger keys:

Jindong(pattern) { Clip(pattern) }

HapticPattern is a data class, so the key comparison is structural.

Acceptance criteria

  • Compose UI tests (RecordingHapticExecutor idiom): a pattern threaded through keys re-fires with the new events; a pattern changed without a key does not.
  • apiDump regenerated for both modules.

Depends on #85 and #88.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions