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

@sendsay-ru/guidely-editor

v0.7.2

Published

Browser-based visual editor for Guidely configs.

Readme

@sendsay-ru/guidely-editor

Visual editor for @sendsay-ru/guidely tours. It opens as a compact side panel inside the application, so authors build tours on the real interface: they point at elements, write the text, and see each step on the page while they type.

The editor is meant for development, staging, and internal builds. Load it lazily so production bundles do not include it.

Features

  • Tours, steps, settings. The panel goes from the list of tours to a tour and then to a step. It covers the whole Guidely config: every trigger, including on-entry tours that wait for an element and route tours, start dates, highlight options, tooltip, hotspot and modal steps, placement, buttons, target events, target waiting, and auto-promotion settings.
  • Picking targets. Authors click an element on the page to use it as a step target. Elements inside iframes can be picked too when the application uses @sendsay-ru/guidely-frame-bridge.
  • Live preview. The step being edited is rendered on the page by the real Guidely renderer and updates as the author types. The preview never takes focus from the editor.
  • Playing tours. A tour can be played the way users meet it, or from any step, in an isolated runtime with in-memory state. Real users' progress is never touched.
  • Languages. Content is edited per language in tabs, and untranslated steps are marked.
  • Checks. Guidely's schema errors are shown next to the fields they belong to, together with editor warnings: missing translations, fragile CSS targets, duplicate step ids, and more. Each step shows whether its target is on the current page. The error count at the bottom of the panel leads to each error in turn: it opens the step, language tab and section with the error and focuses the field.
  • Interface in English and Russian. The interface follows the application's locale and can switch languages without reopening the editor.
  • Drafts. Edits are autosaved in the browser and survive reloads. Changes can be undone, and the config can be copied or imported as JSON.

Install

yarn add @sendsay-ru/guidely @sendsay-ru/guidely-editor

@sendsay-ru/guidely is a peer dependency. It validates configs and renders previews. The editor bundles its own small UI runtime (Preact), so it works in any application, with or without a framework.

Usage

const { createGuidelyEditor } = await import("@sendsay-ru/guidely-editor");

const editor = createGuidelyEditor({
  config, // the config the application ships
  locale: "ru", // the application's locale
  locales: ["en", "ru"],
});

editor.mount();

The editor starts from config and keeps its own draft. Copy the draft with Copy JSON and put it into the application's config when the tours are ready.

Options

createGuidelyEditor({
  config, // the config the draft starts from
  locale, // the application's locale: the interface language and the content tab it opens with
  locales, // content languages to fill in; languages found in the config are added
  container, // where the editor and previews are mounted; default: document.body
  onChange, // called with the draft after changes, debounced while the author types
  targetResolver, // the application's resolver, for example a frame bridge resolver
  theme, // theme applied to previews, so they look like the application
  labels, // button labels applied to previews
  storageKey, // localStorage key for the draft; default: "guidely-editor"; false disables it
  path, // the page the application shows, for route tours
});

Drafts can be invalid while an author works on them, for example when a new tour has no steps yet. Validate the config with parseConfig before running it.

Interface language

The interface is available in English and Russian. It follows locale, so "ru" and "ru-RU" show it in Russian and other languages get English. Without locale, the editor uses the lang of the page. When the application's language changes, pass the new locale to setLocale:

editor.setLocale("en");

Content languages are separate: authors switch them in the step's tabs, and previews use them.

Route tours

Route tours start when the user opens a matching page, for example /campaigns/:id. Pass the page the application shows as path and report navigation with setPath, the same way as to Guidely itself:

const editor = createGuidelyEditor({ config, path: location.pathname });

router.subscribe((location) => {
  editor.setPath(location.pathname);
});

The tour screen then shows whether the current page matches the tour's path, and Use it puts the current path into the field. A tour switched to On route starts with the path of the page the author is on. Play starts a route tour the way users meet it: right away on a matching page, otherwise once the author opens one. Without path the editor cannot tell which page is open, so Play starts route tours right away.

Drafts

The draft is saved in localStorage under storageKey, so a reload does not lose work. The panel shows how many changes the draft has compared to the application's config.

When the application's config changes after the draft was saved, for example after other tours were released, the editor merges the draft onto it on the next start:

  • tours the author did not touch follow the application;
  • tours the application did not change keep the author's edits;
  • tours changed on both sides keep the author's version, and the editor says so.

Discard the draft in the menu goes back to the application's config. The discard can be undone.

Targets

Picking prefers the closest element with a data-<attributePrefix>-id attribute, because such targets survive markup changes. Hold Alt to pick the exact element under the pointer instead. It is then targeted by a generated CSS selector, and the editor suggests a data-id to add to the element.

New steps take their id from the picked element, for example send-test for data-guidely-id="send-test".

An on-entry tour can start when an element appears instead of when the application opens, for example an announcement shown when the user opens an editor inside an iframe. Choose When an element appears in the tour's start settings and pick the element the same way as a step target.

Iframe targets

Pass the application's frame target resolver as targetResolver:

import { createDynamicFrameTargetResolver } from "@sendsay-ru/guidely-frame-bridge";

const targetResolver = createDynamicFrameTargetResolver({
  iframe: "#builder-frame",
  bridgeId: "email-builder",
  scope: "frame",
});

const editor = createGuidelyEditor({ config, targetResolver });

Previews and target status then work for iframe targets. Picking also reaches into the iframe: there, only elements marked with a data-id can be picked, and only their ids and positions leave the iframe. Iframe picking needs the application inside the iframe to use a version of @sendsay-ru/guidely-frame-bridge that supports picking.

Targets picked in the host page get scope: "document" when a targetResolver is passed, so the runtime routes them the same way as iframe targets.

Keyboard

  • Escape cancels picking.
  • Cmd+Z or Ctrl+Z undoes a change, and Shift+Cmd+Z or Ctrl+Y redoes it, when focus is not in a text field. Text fields keep their own undo.
  • With a step's drag handle focused, the up and down arrow keys move the step.

API

editor.mount(container?); // shows the editor
editor.unmount(); // removes the editor and its previews; the draft stays saved
editor.destroy(); // the same as unmount, for final cleanup
editor.open(); // expands the panel
editor.close(); // collapses the panel into its button
editor.getConfig(); // a copy of the draft
editor.setConfig(config); // replaces the draft; the change can be undone
editor.startPicking(); // picks a target for the open step
editor.stopPicking();
await editor.preview(); // plays the open tour, or the first one
await editor.copyConfig(); // copies the draft as JSON
editor.setLocale(locale); // switches the interface language
editor.setPath(path); // tells the editor that the application has moved to another page

Development

The examples/editor playground shows the editor on a sample application with an iframe:

yarn workspace @sendsay-ru/example-editor dev

Open it with ?fresh to start without the saved draft, and with ?locale=ru to start in Russian. The language switch in its header changes the editor's language on the fly, and the links in its navigation switch pages the way a router would, so route tours can be tried there.