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

cal-webcomponents

v1.0.2

Published

Readme

cal-components

面向 AI Agents 的日历 Web Components 库:让 Agent 在静态 HTML 中以纯声明式的方式快速嵌入月历 / 周历 / 日历交互,零 JS 即可获得完整可用的日程视图。典型场景:旅行计划安排、行程单、课程表、会议日程等 Agent 直接输出 HTML 的场合。

基于 Lit 构建,产物为原生 Custom Elements。使用方完全不需要 node 或任何构建工具:一个 <script> 标签从 unpkg 引入(依赖已全部打包进产物),即可在任意静态 HTML 文件中使用,双击打开本地文件也能运行。

为什么适合 AI Agent

  • 纯 HTML 声明式:数据就是 <cal-event> 标签,Agent 生成文本即得可交互日历,无需编写任何 JavaScript。
  • 业务字段自由扩展:任意 data-* 属性(如 data-locationdata-order)自动进入模板通道,Agent 可按场景自定义字段。
  • 详情卡片也是 HTML<template slot="detail"> + {{占位符}} 插值即完成点击详情弹层,样式完全由页面 CSS 控制。
  • 健壮的时间解析:全天事件、跨夜酒店(≥24h)、跨午夜行程(21:00–08:00)等旅行场景的时间语义内置处理。

特性

  • 三种视图:月(month)/ 周(week,可见日数 1–14 可调)/ 日(day),切换带淡入淡出过渡
  • 高度自适应容器:周/日视图默认完整显示 24 小时、月视图默认整 6 周行填满可视区(可用 hour-height / start-hour / end-hour / row-height 覆盖恢复固定高度 + 滚动)
  • 无限滚动:月视图纵向周行流、周视图时间+日期双向无限、日视图日块堆叠(基于 lenis,滚轮/触摸惯性滑动)
  • 重叠事件自动分列布局;跨天事件按天分段并裁剪圆角
  • 全天泳道:纯日期或时长 ≥24h 的事件渲染为跨天横条
  • 点击事件高亮 + 模板驱动的详情弹层(自动避让边界,Esc/点击空白关闭)
  • 月视图 +n 展开当日列表弹层
  • 丰富的定制口:CSS 变量、itemRenderertimeFormattercal-event-click / cal-day-click 事件

快速开始(零构建)

使用方无需安装 node、无需打包,在 HTML 的 <head> 中加一行 <script> 即可(UMD 产物,加载时自动注册 <cal-calendar> / <cal-event>):

<script src="https://unpkg.com/cal-webcomponents@1"></script>

建议锁定主版本号(@1)避免意外升级;https://unpkg.com/cal-webcomponents 默认解析到 UMD 产物。 如需 ES Module:<script type="module" src="https://unpkg.com/cal-webcomponents/dist/cal-webcomponents.js"></script>

一个完整可运行的单文件示例(保存为 .html 直接用浏览器打开):

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>日本关西 5 日游</title>
    <script src="https://unpkg.com/cal-webcomponents@1"></script>
    <style>
      body {
        margin: 0;
        padding: 20px;
        background: #f2f3f5;
        font-family: -apple-system, 'PingFang SC', sans-serif;
      }
      cal-calendar {
        --cal-height: 80vh;
      }
      /* 详情卡片样式:slot 模板内容在 Shadow DOM 外渲染,CSS 完全由页面控制 */
      .dcard {
        padding: 12px 14px;
      }
      .dcard-t {
        font-size: 14px;
        font-weight: 600;
      }
      .dcard-r {
        margin-top: 5px;
        color: #4e5969;
      }
      .dcard-r.order {
        color: #2f6fe0;
      }
    </style>
  </head>
  <body>
    <cal-calendar type="month" initial-date="2026-08-10">
      <!-- 点击事件的详情弹层模板(可选,纯 HTML + 占位符) -->
      <template slot="detail">
        <div class="dcard">
          <div class="dcard-t">{{data.icon}} {{title}}</div>
          <div class="dcard-r">🕐 {{time}}</div>
          <div class="dcard-r">📍 {{data.location}}</div>
          <div class="dcard-r order">订单号:{{data.order}}</div>
        </div>
      </template>

      <cal-event
        start="2026-08-10 08:55"
        end="2026-08-10 12:40"
        title="深圳 → 大阪 CA133"
        data-icon="✈️"
        color="#2f6fe0"
        data-location="宝安 T3 → 关西 T1"
        data-order="FL2026081001"
      ></cal-event>
      <cal-event
        start="2026-08-10 15:00"
        end="2026-08-12 11:00"
        title="大阪难波酒店"
        data-icon="🏨"
        color="#7c5ce0"
        data-location="难波站步行 5 分钟"
        data-order="HT2026081001"
      ></cal-event>
      <cal-event
        start="2026-08-10 18:00"
        end="2026-08-10 20:00"
        title="道顿堀晚餐"
        data-icon="🍜"
        color="#e8483f"
        data-location="蟹道乐 道顿堀本店"
      ></cal-event>
    </cal-calendar>
  </body>
</html>

<cal-calendar> 属性

| 属性 | 类型 | 默认值 | 说明 | | -------------- | ---------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | type | day \| week \| month | month | 视图类型,可动态切换 | | initial-date | string | 今天 | 初始定位日期,如 "2026-08-10" | | days | number | 7 | 周视图可见日数(≥1) | | scroll-x | boolean | true | 周视图是否允许横向滚动 | | hour-height | number | - | 周/日视图每小时高度(px,固定高度模式);不设置时按 start-hour/end-hour 时间窗均分容器高度 | | start-hour | number | 0 | 周/日视图时间窗起始小时(0–23);与 end-hour 的差值即可视区显示的小时数(差值 <24 时可上下滚动),同时作为初始滚动锚点(未设置时:今天定位到当前时间前 1 小时,否则 8 点) | | end-hour | number | 24 | 周/日视图时间窗结束小时(1–24) | | row-height | number | - | 月视图行高(px);不设置时按容器高度均分 6 行自适应 |

start-hour / end-hour 直接声明默认时间窗口。例如旅行规划的周日历,默认显示 8:00–22:00、早晚仍可滚动查看:

<cal-calendar
  type="week"
  start-hour="8"
  end-hour="22"
  initial-date="2026-08-10"
>
  ...
</cal-calendar>

说明:start-hour/end-hour 不裁剪时间轴——时间格始终是完整 24 小时,只是默认窗口落在该范围。都不设置时默认 0–24(一整天填满可视区,无纵向滚动)。优先级:hour-height(固定像素)> start-hour/end-hour(时间窗均分)。

参数按视图适用范围

属性管布局/行为,CSS 变量只管外观;不适用当前视图的属性会被安全忽略(不报错):

| 参数 | month | week | day | | ----------------------------------------- | ----- | ---- | --- | | type / initial-date | ✓ | ✓ | ✓ | | days | - | ✓ | - | | scroll-x | - | ✓ | - | | hour-height / start-hour / end-hour | - | ✓ | ✓ | | row-height | ✓ | - | - |

<cal-event> 属性

<cal-event> 仅作数据载体,自身不渲染。

| 属性 | 说明 | | -------- | --------------------------------------------------------------------------- | | start | 开始时间:"2026-08-10 08:55""2026-08-10"(全天) | | end | 结束时间;省略时 timed 按 1 小时、全天按 1 天;纯日期的 end 包含当天 | | title | 事件标题 | | color | 主题色(如 #e8483f),自动派生背景/前景色 | | data-* | 任意业务扩展字段(icon/location/desc/order…),模板中以 {{data.xxx}} 引用 |

时间语义(旅行场景重点):

  • 纯日期输入,或时长 ≥24h(如酒店 15:00 入住~隔日 11:00 退房)→ 渲染到全天泳道的跨天横条
  • 跨午夜但 <24h(如 21:00–08:00 的跨夜发版)→ 在时间格内按天分段渲染,段边缘自动去圆角
  • end 早于 start 时自动兜底为 1 小时

模板与占位符

<cal-calendar> 内放置 <template> 即可定制 UI,全部为声明式 HTML,插值自动 HTML 转义

| 模板 | 触发时机 | | ---------------------------- | ---------------------------------------------------- | | <template slot="detail"> | 点击事件弹出的详情卡片 | | <template slot="day-item"> | 月视图 +n 弹层中当日事件的行内容 | | <template slot="item"> | 日历格子内事件项的内容(低于 itemRenderer 优先级) |

可用占位符:

  • 内核字段:{{title}} {{color}} {{time}}(长时间格式){{timeShort}}(简短){{date}} {{weekday}} {{start}} {{end}}
  • 扩展数据:{{data.xxx}},对应 <cal-event>data-xxx 属性

弹层渲染在 light DOM(挂在 document.bodyposition: fixed),模板内容的样式完全由页面普通 CSS 控制(不受 Shadow DOM 隔离影响);弹层外壳可用 --cal-popover-width / --cal-popover-radius / --cal-popover-bg / --cal-popover-shadow 等变量定制(定义在 cal-calendar 上,打开弹层时自动继承过去)。

JS API(可选进阶)

声明式用法已覆盖大多数场景;需要编程控制时:

const cal = document.querySelector('cal-calendar')!;

cal.jumpTo('2026-08-01'); // 跳转到指定日期
cal.goToday(); // 回到今天

// 自定义事件项渲染(返回 HTML 字符串或 lit TemplateResult,返回 null 回退默认)
cal.itemRenderer = (ev, kind) =>
  kind === 'block' ? `<b>${ev.data.icon} ${ev.title}</b>` : null;

// 自定义时间格式(kind: 'long' 用于 {{time}},'short' 用于 {{timeShort}})
cal.timeFormatter = (ev, kind) => '...';

// 调用方自行实现详情 UI 时:监听事件并用 anchor 定位,setActiveEvent 同步高亮
cal.addEventListener('cal-event-click', (e) => {
  e.preventDefault(); // 抑制内置弹层
  const { event, anchor, kind } = e.detail;
  // ...打开自己的气泡/抽屉
  cal.setActiveEvent(event); // 关闭时传 null
});
cal.addEventListener('cal-day-click', (e) => {
  const { date, events, anchor } = e.detail;
});

事件均 bubbles + composed + cancelableitemRendererkind 取值:chip(月格子)/ bar(全天泳道)/ block(时间格)。

样式定制(CSS 变量)

cal-calendar {
  --cal-height: 72vh; /* 组件高度(默认 640px) */
  --cal-accent: #2f6fe0; /* 强调色:今天、高亮、当前时间线 */
  --cal-bg: #ffffff;
  --cal-border: #e5e6eb;
  --cal-radius: 10px;
  --cal-text: #1f2329;
  --cal-sub: #86909c; /* 次级文字 */
  --cal-grid: #f2f3f5; /* 网格线 */
  --cal-event-bg: #e8f0fe; /* 无 color 事件的默认底色 */
  --cal-event-text: #1d5fd4;
  --cal-gutter: 56px; /* 时间轴左侧宽度 */
  --cal-popover-width: 280px;
  --cal-font: 14px/1.4...; /* 字体 */
}

事件未指定 color 时使用默认配色;指定后按 color-mix 自动派生浅色背景与深色文字。

项目结构

src/
  index.ts            入口:注册 custom elements 并导出 API
  cal-calendar.ts     宿主组件:属性、事件收集、视图分发、弹层
  cal-event.ts        事件数据载体元素
  views/              视图控制器(month-view / week-view / day-view)
  event-utils.ts      cal-event 解析、时间格式化、重叠分列布局
  event-templates.ts  模板插值(占位符 + HTML 转义)
  date-utils.ts       日期工具
  calendar-styles.ts  组件样式(含全部 CSS 变量默认值)

开发(组件库贡献者)

仅开发本组件库时需要 node 环境;使用组件无需此步骤

pnpm install
pnpm dev      # 打开 showcase(index.html,含旅行计划 / 工作安排 / 课程表 / 自定义渲染 4 个案例)
pnpm build    # 产出 dist/cal-webcomponents.js (ES) 与 dist/cal-webcomponents.umd.js (UMD)

产物为自包含单文件(lit、lenis 已打包入内),发布 npm 后使用方经 unpkg / jsDelivr 等 CDN 直接引用:

  • UMD:https://unpkg.com/cal-webcomponents(或 .../dist/cal-webcomponents.umd.js
  • ES Module:https://unpkg.com/cal-webcomponents/dist/cal-webcomponents.js

License

MIT