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

@mulmocast/deck-web

v1.1.1

Published

Vue 3 components for editing @mulmocast/deck SlideLayout decks live in the browser

Readme

@mulmocast/deck-web

npm version npm downloads License: MIT CI GitHub stars

Vue 3 components for editing @mulmocast/deck slide decks live in the browser.

A 3-pane editor that holds a SlideLayout[] (or a full MulmoScript) in memory, renders each slide live via generateSlideHTML() into a sandboxed iframe, and lets you edit through WYSIWYG click-to-edit + a floating toolbar + drag-and-drop reorder, plus a schema-aware Inspector for structural edits. No backend, no persistence, no AI — just data ↔ preview.

Highlights

  • WYSIWYG click-to-edit — click any text in the preview to edit in place. Blur or Enter commits, Escape cancels.
  • Floating toolbar — select text → toolbar appears with B (bold) / ★ amber highlight / 7 color swatches / × clear. Toggle off by clicking the same button again.
  • Drag-and-drop reorder — drag bullets, stats cards, timeline steps, manifesto lines, columns, grid items in the preview to reorder. Drag slides in the left list to reorder the deck.
  • Inspector for structure — add / remove / swap layout type / nest content blocks / edit non-text fields.

Install

yarn add @mulmocast/deck-web @mulmocast/deck vue

vue ^3.5 and @mulmocast/deck ^0.7.0 are peer dependencies (0.7.0 ships the data-mulmo-path / data-mulmo-item-path attributes the WYSIWYG / D&D rely on).

Usage

Edit a SlideLayout[] directly

<script setup lang="ts">
import { ref } from "vue";
import { DeckEditor, sampleDeck, defaultTheme } from "@mulmocast/deck-web";

const slides = ref(sampleDeck);
</script>

<template>
  <DeckEditor v-model:slides="slides" :theme="defaultTheme" />
</template>

Edit a MulmoScript directly

MulmoScriptDeckEditor is a companion component that takes a MulmoScript, extracts the slide beats (image.type === "slide"), and writes edits back into the script. Non-slide beats (movie / textSlide / voice_over / etc.) stay untouched.

<script setup lang="ts">
import { ref } from "vue";
import { MulmoScriptDeckEditor } from "@mulmocast/deck-web";

const script = ref({ /* your MulmoScript */ });
</script>

<template>
  <MulmoScriptDeckEditor v-model:script="script" />
</template>

Theme priority: prop theme > script.presentationStyle.slideParams.theme > script.slideParams.theme > built-in defaultTheme.

Use <SlidePreview> standalone

If you already have your own deck-list / inspector and only want WYSIWYG editing in an iframe:

<script setup lang="ts">
import { ref } from "vue";
import { SlidePreview, defaultTheme, type SlideLayout } from "@mulmocast/deck-web";

const slide = ref<SlideLayout>({ layout: "title", title: "Hello", subtitle: "Click any text to edit" });
</script>

<template>
  <SlidePreview :slide="slide" :theme="defaultTheme" @update="(s) => (slide = s)" />
</template>

<SlidePreview> is self-contained: click-to-edit, the floating toolbar, and D&D reorder of in-slide items all work out of the box.

Components

| Component | Purpose | |---|---| | <DeckEditor> | All-in-one 3-pane editor. v-model:slides (SlideLayout[]), optional theme, optional v-model:selectedIndex. | | <MulmoScriptDeckEditor> | Same UX but consumes/emits a MulmoScript. | | <DeckList> / <SlidePreview> / <Inspector> | The individual panes — drop into your own layout. | | defaultTheme / sampleDeck | Data helpers for quick starts. |

The Inspector covers every layout (title / bigQuote / columns / comparison / grid / stats / timeline / split / matrix / table / funnel / waterfall / manifesto) and every content block type (text / bullets / callout / tag / code / metric / divider / image / imageRef / chart / mermaid / section / table), with full CRUD + reorder on every array.

How preview works

Each slide is rendered through generateSlideHTML(theme, slide) from @mulmocast/deck and dropped into an <iframe srcdoc> sandbox. Tailwind is loaded inside the iframe via CDN, so the host page's CSS can't bleed in (or out).

How WYSIWYG / D&D wires through the iframe

@mulmocast/[email protected]+ emits two data attributes that consumers can rely on:

| Attribute | On | Used for | |--|--|--| | data-mulmo-path | Every editable leaf text element | click-to-edit (set contenteditable=true, commit on blur via setByPath). Tip of the WYSIWYG path. | | data-mulmo-item-path | List-item container (<li>, stat card, timeline step, manifesto line, columns / grid card) | HTML5 drag handle (draggable=true). Drop on a sibling → moveByPath. |

The pure helpers (parsePath, getByPath, setByPath, moveByPath, htmlToMarkup) are exposed from editorHelpers.ts and unit-tested under node:test.

Architecture

DeckEditor.vue           (controlled — props: slides, theme; emits: update:slides)
├── DeckList.vue         -- left  (slide list / add / remove / select)
├── SlidePreview.vue     -- center (iframe srcdoc = generateSlideHTML(theme, slide))
└── Inspector.vue        -- right (form for the selected slide)

MulmoScriptDeckEditor.vue
└── DeckEditor (with a beats↔slides adapter)

State is held by the parent (Vue v-model pattern). All mutations are immutable copies, so iframe re-renders reactively.

Scripts

yarn dev          # Vite dev server with the SPA demo
yarn build        # build the demo SPA → dist/
yarn build:lib    # build the publishable library → dist/lib/ (used by prepublishOnly)
yarn lint
yarn format

License

MIT