Components

Reusable components with props, outputs, events and context.

Contents:

  • k.Component: The only kind of reusable object: a subclass with props (k.Prop[T], inputs), static fields (name: T = default), outs (k.Out[T], outputs as signals) and events (k.Event), plus a build() that runs once and returns the visual.
  • k.Prop: Declares a reactive component prop: power: k.Prop[float] = k.prop(0.0).
  • k.Out: Declares a continuous component output: soc: k.Out[float].
  • k.Event: Declares an event on a component or a k.State: full: k.Event or, with a typed payload, bounce: k.Event[Impact].
  • k.field: Validated default for a static component field: k.field(0.2, range=(0, 1)) or k.field("a", choices=[...]).
  • k.prop: Validated default for a reactive prop: k.prop(0.0, range=(-5, 5)).
  • k.context: Declares a context (at module level): a value that many components need (clock, scale, unit), supplied with k.provide instead of passed down prop by prop.
  • k.Context: Clock = k.context("clock", default=k.time), declared at module level.
  • k.provide: with block that supplies a context value to the components constructed inside it.
  • k.from_context: Prop or field default that reads a context: time: k.Prop[float] = k.from_context(Clock).

Back to the reference index.

k.Component (class)

k.Component(*, name: str | None = None, **kwargs: object)

Written as: class Name(k.Component)

The only kind of reusable object: a subclass with props (k.Prop[T], inputs), static fields (name: T = default), outs (k.Out[T], outputs as signals) and events (k.Event), plus a build() that runs once and returns the visual. Parts stored on self.* are addressable from outside. Verbs use enter()/exit()/indicate() when the component defines them.

Parameters:

Name Type Default Description
name str | None None
**kwargs object variadic

Props inherited from k.Node: x, y, rotate, scale, scale_x, scale_y, anchor, opacity, z, visible.

Example:

class Tag(k.Component):
    text: str = "kinemo"

    def build(self) -> k.Node:
        self.box = k.RoundedRect(w=3, h=1)
        self.label = k.Text(self.text).place(inside=self.box)
        return k.Group(self.box, self.label)

@k.scene
def component(s: k.Scene):
    tag = Tag(text="Hello").place(at="center")
    s.play(k.draw(tag))
    s.play(tag.box.to(color=k.BLUE))

See also: k.Prop, k.Out, k.Event, k.clip.

Members:

  • build: Return the component's visual (a node built from the props); runs once, at construction.
  • copy: Rebuilds the component with the same arguments.

Inherited from k.Group: children, to, swap, insert, pop, fit. Inherited from k.Node: set, unbind, edge, age, entered, exited, place, to_place, unpin.

k.Component.build (method)

component.build() -> Node

Return the component's visual (a node built from the props); runs once, at construction.

k.Component.copy (method)

component.copy(frozen: bool = False) -> Component

Rebuilds the component with the same arguments.

Parameters:

Name Type Default Description
frozen bool False

k.Prop (class)

k.Prop()

Written as: name: k.Prop[T] = default

Declares a reactive component prop: power: k.Prop[float] = k.prop(0.0). Inside the component it is always a signal (Signal[float]), even if the author passed a constant; from outside, it accepts a value, signal or lambda and animates with comp.to(power=...). The default via k.prop is what passes Pyright strict.

Example:

class Gauge(k.Component):
    value: k.Prop[float] = k.prop(0.0)

    def build(self) -> k.Node:
        return k.Rect(w=0.6, h=self.value + 0.01, fill=k.GREEN, fill_opacity=1)

@k.scene
def gauge(s: k.Scene):
    m = Gauge(value=1.0).place(at="center")
    s.add(m)
    s.play(m.to(value=3))

See also: k.Component, k.prop, k.field.

k.Out (class)

k.Out()

Written as: name: k.Out[T]

Declares a continuous component output: soc: k.Out[float]. It must be assigned in build() (error K0602) and is read from outside as a read-only signal (bat.soc).

Example:

class Counter(k.Component):
    total: k.Out[float]

    def build(self) -> k.Node:
        self.total = k.integrate(0.5)
        return k.Text(lambda: f"{self.total():.1f}")

@k.scene
def output(s: k.Scene):
    c = Counter().place(at="center")
    bar = k.Rect(w=0.5, h=c.total + 0.01).place(below=c, gap=0.3)
    s.add(c, bar)
    s.wait(3)

See also: k.Component, k.integrate.

k.Event (class)

k.Event()

Written as: name: k.Event · name: k.Event[Payload]

Declares an event on a component or a k.State: full: k.Event or, with a typed payload, bounce: k.Event[Impact]. Fire it with k.when(cond, self.full) or self.full.emit(); react with @obj.full.on or s.wait_for(obj.full). String-based events do not exist.

Example:

class Alarm(k.Component):
    rang: k.Event

    def build(self) -> k.Node:
        k.when(k.time >= 2, self.rang)
        return k.Circle(r=0.5, fill=k.RED, fill_opacity=1)

@k.scene
def event(s: k.Scene):
    alarm = Alarm().place(at="center")
    s.add(alarm)
    s.wait_for(alarm.rang, timeout=5)
    s.play(k.flash(alarm))

See also: event.on, k.when, s.wait_for.

k.field (function)

k.field(
    default: T,
    *,
    range: tuple[float, float] | None = None,
    choices: Sequence[T] | None = None,
) -> T
k.field(
    *,
    range: tuple[float, float] | None = None,
    choices: Sequence[Any] | None = None,
) -> Any

Validated default for a static component field: k.field(0.2, range=(0, 1)) or k.field("a", choices=[...]). Out-of-range values are an error at construction; static fields reject signals (K0601).

Parameters:

Name Type Default Description
default T required
range tuple[float, float] | None None Validated default for a static component field: k.field(0.2, range=(0, 1)) or k.field("a", choices=[...]).
choices Sequence[T] | None None Validated default for a static component field: k.field(0.2, range=(0, 1)) or k.field("a", choices=[...]).

Example:

class Ring(k.Component):
    thickness: float = k.field(0.2, range=(0.05, 1))

    def build(self) -> k.Node:
        return k.Circle(r=1, stroke_width=self.thickness * 20)

@k.scene
def ring(s: k.Scene):
    r = Ring(thickness=0.4).place(at="center")
    s.play(k.draw(r))

See also: k.prop, k.Component.

k.prop (function)

k.prop(default: bool, *, range: tuple[float, float] | None = None) -> Prop[bool]
k.prop(default: float, *, range: tuple[float, float] | None = None) -> Prop[float]
k.prop(default: T, *, range: tuple[float, float] | None = None) -> Prop[T]

Validated default for a reactive prop: k.prop(0.0, range=(-5, 5)). Constants are validated at construction; for reactive values, lint W0602 samples the timeline.

Parameters:

Name Type Default Description
default bool required
range tuple[float, float] | None None Validated default for a reactive prop: k.prop(0.0, range=(-5, 5)).

Example:

class Needle(k.Component):
    angle: k.Prop[float] = k.prop(0.0, range=(0, 360))

    def build(self) -> k.Node:
        return k.Line(start=(0, 0), end=(2, 0), rotate=self.angle)

@k.scene
def needle(s: k.Scene):
    p = Needle(angle=30)
    s.add(p)
    s.play(p.to(angle=150))

See also: k.Prop, k.field.

k.context (function)

k.context(name: str, default: T) -> Context[T]
k.context(name: str) -> Context[Any]

Declares a context (at module level): a value that many components need (clock, scale, unit), supplied with k.provide instead of passed down prop by prop. The theme is a built-in context.

Parameters:

Name Type Default Description
name str required
default T required

Example:

Scale = k.context("scale", default=1.0)

class Point(k.Component):
    r: k.Prop[float] = k.from_context(Scale)

    def build(self) -> k.Node:
        return k.Dot(r=self.r * 0.2)

@k.scene
def context(s: k.Scene):
    with k.provide(Scale, 2.0):
        p = Point().place(at="center")
    s.play(k.fade_in(p))

See also: k.provide, k.from_context.

k.Context (class)

k.Context(name: str, default: T)

Clock = k.context("clock", default=k.time), declared at module level.

Documented together with k.context.

Parameters:

Name Type Default Description
name str required
default T required Clock = k.context("clock", default=k.time), declared at module level.

Members:

  • get: Value provided for this context in the enclosing k.provide block, or the default.

k.Context.get (method)

context.get() -> T

Value provided for this context in the enclosing k.provide block, or the default.

k.provide (function)

k.provide(ctx: Context[T], value: Val[T]) -> Iterator[None]

with block that supplies a context value to the components constructed inside it. It is resolved at construction (lexical scope of the build phase); passing the prop explicitly always wins over the context.

Parameters:

Name Type Default Description
ctx Context[T] required Components constructed inside the block receive value for ctx.
value Val[T] required Components constructed inside the block receive value for ctx.

Example: same as k.context.

See also: k.context, k.from_context.

k.from_context (function)

k.from_context(ctx: Context[Any]) -> Any

Prop or field default that reads a context: time: k.Prop[float] = k.from_context(Clock). Without k.provide, the context's default= applies.

Parameters:

Name Type Default Description
ctx Context[Any] required Default of a prop or field read from ctx at construction.

Example: same as k.context.

See also: k.context, k.provide.