@sendsay-ru/guidely-editor
v0.7.2
Published
Browser-based visual editor for Guidely configs.
Maintainers
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 pageDevelopment
The examples/editor playground shows the editor on a sample application with an iframe:
yarn workspace @sendsay-ru/example-editor devOpen 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.
