npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@daywatch/cal-models

v0.1.1

Published

Framework-neutral derived models and controller helpers built on top of [@daywatch/cal](https://www.npmjs.com/package/@daywatch/cal).

Readme

@daywatch/cal-models

Framework-neutral derived models and controller helpers built on top of @daywatch/cal.

This package is intended for:

  • adapter packages like @daywatch/cal-react
  • advanced consumers who want ergonomic pure functions without committing to a UI framework adapter

Install

npm install @daywatch/cal-models @daywatch/cal

What it provides

  • Calendar model builders and navigation helpers
  • Event normalization helpers
  • Range evaluation helpers
  • Timeline/day-detail derived models
  • Conflict, free-slot, span, schedule-score, and year-grid derived models

Example

import { buildCalendarModel, createCalendarController } from '@daywatch/cal-models';

const model = buildCalendarModel({
  focusDate: '2026-03-15',
  numberOfMonths: 1,
  ranges: myRanges,
  fidelity: 'month',
});

const controller = createCalendarController({
  focusDate: model.focusDate,
});

Date Selection

updateDateSelection(selection, action, config) is a pure reducer for controlled date-range selection. It works with the DateSelection, DateSelectionAction, and DateSelectionConfig types exported by this package.

import { updateDateSelection } from '@daywatch/cal-models';
import type { DateSelection } from '@daywatch/cal-models';

let selection: DateSelection = {
  start: null,
  end: null,
  preview: null,
};

selection = updateDateSelection(selection, {
  type: 'click',
  date: '2026-04-10',
});

selection = updateDateSelection(selection, {
  type: 'hover',
  date: '2026-04-12',
});

selection = updateDateSelection(selection, {
  type: 'click',
  date: '2026-04-12',
});

The first click sets start, hover updates preview, and the second click completes the range by setting end. Because it is a pure reducer, it composes cleanly with React, Preact, Solid, or any other state container.

createIsDateBlocked(ranges, options) builds a predicate that returns true when a date falls inside one of the supplied DateRange values.

import {
  createIsDateBlocked,
  updateDateSelection,
} from '@daywatch/cal-models';

const isDateBlocked = createIsDateBlocked(existingRanges, {
  userTimezone: 'America/New_York',
});

const next = updateDateSelection(selection, {
  type: 'click',
  date: '2026-04-14',
}, {
  isDateSelectable: date => !isDateBlocked(date),
});

selectionToDateRange(selection, template) converts a completed selection into a DateRange.

import { selectionToDateRange } from '@daywatch/cal-models';

const range = selectionToDateRange(selection, {
  label: 'Vacation',
});

If start or end is missing, it returns null.

Time Selection

updateTimeSelection(selection, action, config) is the time-slot equivalent. It works with the TimeSelection, TimeSelectionAction, and TimeSelectionConfig types and snaps incoming times to the configured interval before applying reducer logic.

import { updateTimeSelection } from '@daywatch/cal-models';
import type { TimeSelection } from '@daywatch/cal-models';

let selection: TimeSelection = {
  date: '2026-04-10',
  startTime: null,
  endTime: null,
  preview: null,
};

selection = updateTimeSelection(selection, {
  type: 'click',
  time: '09:10',
}, {
  intervalMinutes: 30,
  minDuration: 30,
  dayStart: '08:00',
  dayEnd: '18:00',
});

selection = updateTimeSelection(selection, {
  type: 'hover',
  time: '10:05',
}, {
  intervalMinutes: 30,
});

selection = updateTimeSelection(selection, {
  type: 'click',
  time: '10:05',
}, {
  intervalMinutes: 30,
});

snapToInterval(time, intervalMinutes) is available separately when you want the same snapping behavior outside the reducer.

import { snapToInterval } from '@daywatch/cal-models';

snapToInterval('09:10', 30);
// => '09:00'

Composition

Date and time selection are designed to compose. A date picker can own DateSelection, a time picker can own TimeSelection, and once both are complete you can call selectionToDateRange() with time fields in the template to produce the final DateRange.