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

courseware-next-toolbox

v0.2.7

Published

Reusable teaching toolbox for courseware-next style drawing and classroom utilities.

Readme

courseware-next-toolbox

面向新项目的可复用课堂工具箱组件库,目标是尽量还原 kejian-usb-2.0 中的工具条、全屏画布和常用子工具能力。

提示TODO:

  • 目前此包是发布在npm官方镜像,后续建议发布至公司npm镜像中去,方便部门维护

能力

  • 浮动 / 贴边两种工具条形态
  • 默认激活 选择
  • 工具切换:选择、画笔、铅笔、橡皮、文本
  • 颜色面板
  • 线宽面板
  • 撤销 / 重做 / 清空
  • 子工具:聚光灯、白板、骰子、计时器
  • 工具条可拖动
  • 白板 / 骰子 / 计时器弹窗可拖动
  • overlayBoundary 可同时约束:
    • 白板弹窗的拖拽 / 缩放活动范围
    • 全屏画布与白板画布的可绘制安全区域
  • SDK 模式自动创建宿主容器
  • 实例暴露 show() / hide() / setTool() / updateState() / destroy()

安装

npm install courseware-next-toolbox

本地调试

npm install
npm run playground

推荐用法

推荐优先使用 setupCoursewareToolbox(),由 SDK 自己挂载画布层、工具条层和 overlay 层。

import { setupCoursewareToolbox } from 'courseware-next-toolbox';

const toolbox = setupCoursewareToolbox({
  defaultVisible: true,
  onClose: () => {
    // 工具箱点击 X 或调用 hide() 后触发,宿主可在这里同步按钮激活态。
  },
  onVisibleChange: (visible) => {
    // 工具箱显示 / 隐藏状态变化时触发。
    console.log('toolbox visible:', visible);
  },
});

toolbox.show();
toolbox.setTool('pencil');

说明:

  • setTool() 只切换全屏画布工具,例如 selectpencilbrusherasertext
  • 工具栏里的聚光灯、白板、骰子、计时器是独立子工具,可以同时打开
  • 再次点击已打开的子工具按钮,会关闭对应子工具,不影响其它已打开子工具
  • 子工具弹窗点击自己的 X 时,只关闭自己,不会关闭工具箱或其它子工具

约束白板和绘制区域

可以通过 overlayBoundary 指定安全区域,避免白板窗口或画布内容挡住页面上的全局操作元素。

import { setupCoursewareToolbox } from 'courseware-next-toolbox';

const toolbox = setupCoursewareToolbox({
  defaultVisible: true,
  overlayBoundary: {
    insets: {
      top: 64,
      right: 24,
      bottom: 24,
      left: 24,
    },
    padding: 8,
  },
});

也支持按 DOM 元素自动避让:

import { setupCoursewareToolbox } from 'courseware-next-toolbox';

const toolbox = setupCoursewareToolbox({
  defaultVisible: true,
  overlayBoundary: {
    elements: {
      top: document.querySelector('.page-toolbar'),
      right: document.querySelector('.floating-actions'),
      bottom: document.querySelector('.page-footer'),
    },
    padding: 8,
  },
});

如果需要让约束范围基于某个业务容器,而不是整个 viewport:

import { setupCoursewareToolbox } from 'courseware-next-toolbox';

const container = document.getElementById('courseware-stage');

const toolbox = setupCoursewareToolbox({
  defaultVisible: true,
  overlayBoundary: {
    strategy: 'container',
    container,
    insets: {
      top: 8,
      right: 8,
      bottom: 8,
      left: 8,
    },
  },
});

说明:

  • overlayBoundary 会约束白板弹窗的位置和缩放范围
  • overlayBoundary 也会作为主画布和白板画布的绘制边界
  • 超出安全区后:
    • 主画布不会继续落笔
    • 文本工具的新建和拖拽也会被限制在安全区内
    • 白板弹窗不能拖进或缩放到被避让区域中

控制显示隐藏

工具条本体不再内置显示 / 隐藏按钮,建议由宿主页面自己放一个按钮控制:

import { setupCoursewareToolbox } from 'courseware-next-toolbox';

const toolbox = setupCoursewareToolbox({
  defaultVisible: true,
});

const button = document.createElement('button');
let visible = true;

button.type = 'button';
button.textContent = '隐藏工具箱';

button.addEventListener('click', () => {
  visible = !visible;

  if (visible) {
    toolbox.show();
    button.textContent = '隐藏工具箱';
    return;
  }

  toolbox.hide();
  button.textContent = '显示工具箱';
});

document.body.appendChild(button);

手动挂载容器

如果你不想让 SDK 自动创建宿主节点,也可以自行预留:

<div id="app"></div>
<div id="courseware-toolbox-canvas-root"></div>
<div id="courseware-toolbox-toolbar-root"></div>
<div id="courseware-toolbox-overlay-root"></div>

然后显式传入:

import { setupCoursewareToolbox } from 'courseware-next-toolbox';

const toolbox = setupCoursewareToolbox({
  canvasAnchor: document.getElementById('courseware-toolbox-canvas-root')!,
  toolbarAnchor: document.getElementById('courseware-toolbox-toolbar-root')!,
  overlayAnchor: document.getElementById('courseware-toolbox-overlay-root')!,
  defaultVisible: true,
});

说明:

  • #app 是业务页面自己的 React 根节点
  • canvas / toolbar / overlay 三个节点是工具箱使用的宿主层
  • 如果使用 setupCoursewareToolbox({ defaultVisible: true }),这三个节点不是必须手写

控制器接口

setupCoursewareToolbox() 返回:

type CoursewareToolboxController = {
  destroy: () => void;
  hide: () => void;
  setTool: (tool: ToolboxTool) => void;
  show: () => void;
  updateState: (patch: Partial<ToolboxState>) => void;
};

常见用法:

toolbox.show();
toolbox.hide();
toolbox.setTool('select');
toolbox.setTool('pencil');
toolbox.updateState({
  color: '#25d1fc',
  lineSize: 18,
});

显示隐藏行为:

  • show() 只显示工具箱,不会自动关闭已经打开的子工具
  • hide() 隐藏工具箱;除计时器外,其它子工具会一起隐藏
  • 计时器在 hide() 后会保留,方便缩小计时器后继续放大或操作
  • destroy() 会卸载工具箱并关闭所有子工具,适合页面销毁时调用

类型补充

当前对外还额外导出了边界配置类型:

type CoursewareOverlayBoundaryInset = {
  top?: number;
  right?: number;
  bottom?: number;
  left?: number;
};

type CoursewareOverlayBoundaryElements = {
  top?: Element | null;
  right?: Element | null;
  bottom?: Element | null;
  left?: Element | null;
};

type CoursewareOverlayBoundaryConfig = {
  container?: Element | null;
  elements?: CoursewareOverlayBoundaryElements;
  insets?: CoursewareOverlayBoundaryInset;
  padding?: number;
  strategy?: 'viewport' | 'container';
};

当前说明

当前包已经内置:

  • 全屏绘制画布
  • 聚光灯
  • 白板
  • 骰子
  • 计时器