Mixins / foldkit-mixins-ui

RangeSlider

namespace · packages/mixins-ui/src/rangeSlider.ts:1

export * as RangeSlider from './rangeSlider.js'

In the guides

Members

RangeSlider.Bounds

interface · packages/mixins-ui/src/rangeSlider.ts:41

interface Bounds {
  readonly min?: number | undefined
  readonly max?: number | undefined
  readonly step?: number | undefined
}

RangeSlider.moved

function · packages/mixins-ui/src/rangeSlider.ts:77

function moved(
  range: Range,
  thumb: 'low' | 'high',
  value: number,
  bounds?: Bounds,
): Range

The range after thumb moves to value: on the step, within the bounds, and never past the other thumb. The same range when nothing changed, so update can return its Model as it was.

RangeSlider.Range

interface · packages/mixins-ui/src/rangeSlider.ts:36

interface Range {
  readonly low: number
  readonly high: number
}

RangeSlider.RangeSliderSlots

const · packages/mixins-ui/src/rangeSlider.ts:23

const RangeSliderSlots: Slots.Contract<{ readonly root: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly [Attr.AttrToken<"role">], readonly Slot.RequirementName[], boolean>; readonly label: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly control: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly track: Slot.UnnamedSlot<Capability.Capability<"Base", readonly []>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly range: Slot.UnnamedSlot<Capability.Capability<"Base", readonly []>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly thumb: Slot.UnnamedSlot<Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>, readonly [Event.EventToken<"input">], readonly [Attr.AttrToken<"aria-label">, Attr.AttrToken<"disabled">, Attr.AttrToken<"value">], readonly Slot.RequirementName[], boolean>; …;

A range slider, the APG's multi-thumb slider: a root group named by its label, and two native input type="range" thumbs over one track, each a real slider with its own name, keys and form value. Upstream's Slider has one thumb, so this is not built on it.

The thumbs cannot cross, and the browser keeps that: the low thumb's max is the high value and the high thumb's min the low one, as the APG has it, and each input spans only the part of the track it may travel (from --fk-range-low and --fk-range-high on control, 0 to 1), so a thumb sits where it would on the whole track. A drag past the other thumb stops at it with no redraw needed, which a clamp in update alone could not do: an unchanged Model draws nothing, and the input would keep its own value.

The range is the application's: the view draws value and sends onChange with the next range from moved.

RangeSlider.RangeSliderView

interface · packages/mixins-ui/src/rangeSlider.ts:50

interface RangeSliderView<Message> extends Bounds {
  readonly id: string
  readonly label: string
  readonly value: Range
  readonly onChange: (value: Range) => NoInfer<Message>
  readonly format?: ((value: number) => string) | undefined
  readonly thumbLabels?:
    | {
        readonly low: string
        readonly high: string
      }
    | undefined
  readonly name?: string | undefined
  readonly disabled?: boolean | undefined
  readonly style?: NamedStyle<typeof RangeSliderSlots> | undefined
  readonly mixins?: MixinList<Message> | undefined
}

RangeSlider.view

function · packages/mixins-ui/src/rangeSlider.ts:94

function view<Message>(
  options: RangeSliderView<Message>,
  h: HtmlBuilder<Message>,
): Html