@storybook/api
Version:
Core Storybook API & Context
453 lines (392 loc) • 15.5 kB
JavaScript
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
import "regenerator-runtime/runtime.js";
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
import "core-js/modules/es.regexp.exec.js";
import "core-js/modules/es.string.match.js";
import "core-js/modules/es.object.keys.js";
import "core-js/modules/es.object.freeze.js";
import "core-js/modules/es.object.assign.js";
import "core-js/modules/es.object.to-string.js";
import "core-js/modules/web.dom-collections.for-each.js";
import "core-js/modules/es.object.entries.js";
import "core-js/modules/es.array.concat.js";
import "core-js/modules/es.array.find.js";
import "core-js/modules/es.symbol.js";
import "core-js/modules/es.symbol.description.js";
import "core-js/modules/es.symbol.iterator.js";
import "core-js/modules/es.array.iterator.js";
import "core-js/modules/es.string.iterator.js";
import "core-js/modules/web.dom-collections.iterator.js";
import "core-js/modules/es.array.slice.js";
import "core-js/modules/es.function.name.js";
import "core-js/modules/es.array.from.js";
import "core-js/modules/es.promise.js";
import global from 'global';
import { PREVIEW_KEYDOWN } from '@storybook/core-events';
import { shortcutMatchesShortcut, eventToShortcut } from '../lib/shortcut';
import { focusableUIElements } from './layout';
var navigator = global.navigator,
document = global.document;
export var isMacLike = function isMacLike() {
return navigator && navigator.platform ? !!navigator.platform.match(/(Mac|iPhone|iPod|iPad)/i) : false;
};
export var controlOrMetaKey = function controlOrMetaKey() {
return isMacLike() ? 'meta' : 'control';
};
export function keys(o) {
return Object.keys(o);
}
export var defaultShortcuts = Object.freeze({
fullScreen: ['F'],
togglePanel: ['A'],
panelPosition: ['D'],
toggleNav: ['S'],
toolbar: ['T'],
search: ['/'],
focusNav: ['1'],
focusIframe: ['2'],
focusPanel: ['3'],
prevComponent: ['alt', 'ArrowUp'],
nextComponent: ['alt', 'ArrowDown'],
prevStory: ['alt', 'ArrowLeft'],
nextStory: ['alt', 'ArrowRight'],
shortcutsPage: [controlOrMetaKey(), 'shift', ','],
aboutPage: [','],
escape: ['escape'],
// This one is not customizable
collapseAll: [controlOrMetaKey(), 'shift', 'ArrowUp'],
expandAll: [controlOrMetaKey(), 'shift', 'ArrowDown']
});
var addonsShortcuts = {};
function focusInInput(event) {
return /input|textarea/i.test(event.target.tagName) || event.target.getAttribute('contenteditable') !== null;
}
export var init = function init(_ref) {
var store = _ref.store,
fullAPI = _ref.fullAPI;
var api = {
// Getting and setting shortcuts
getShortcutKeys: function getShortcutKeys() {
return store.getState().shortcuts;
},
getDefaultShortcuts: function getDefaultShortcuts() {
return Object.assign({}, defaultShortcuts, api.getAddonsShortcutDefaults());
},
getAddonsShortcuts: function getAddonsShortcuts() {
return addonsShortcuts;
},
getAddonsShortcutLabels: function getAddonsShortcutLabels() {
var labels = {};
Object.entries(api.getAddonsShortcuts()).forEach(function (_ref2) {
var _ref3 = _slicedToArray(_ref2, 2),
actionName = _ref3[0],
label = _ref3[1].label;
labels[actionName] = label;
});
return labels;
},
getAddonsShortcutDefaults: function getAddonsShortcutDefaults() {
var defaults = {};
Object.entries(api.getAddonsShortcuts()).forEach(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 2),
actionName = _ref5[0],
defaultShortcut = _ref5[1].defaultShortcut;
defaults[actionName] = defaultShortcut;
});
return defaults;
},
setShortcuts: function setShortcuts(shortcuts) {
return _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return store.setState({
shortcuts: shortcuts
}, {
persistence: 'permanent'
});
case 2:
return _context.abrupt("return", shortcuts);
case 3:
case "end":
return _context.stop();
}
}
}, _callee);
}))();
},
restoreAllDefaultShortcuts: function restoreAllDefaultShortcuts() {
return _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
return _context2.abrupt("return", api.setShortcuts(api.getDefaultShortcuts()));
case 1:
case "end":
return _context2.stop();
}
}
}, _callee2);
}))();
},
setShortcut: function setShortcut(action, value) {
return _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3() {
var shortcuts;
return regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
shortcuts = api.getShortcutKeys();
_context3.next = 3;
return api.setShortcuts(Object.assign({}, shortcuts, _defineProperty({}, action, value)));
case 3:
return _context3.abrupt("return", value);
case 4:
case "end":
return _context3.stop();
}
}
}, _callee3);
}))();
},
setAddonShortcut: function setAddonShortcut(addon, shortcut) {
return _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
var shortcuts;
return regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
shortcuts = api.getShortcutKeys();
_context4.next = 3;
return api.setShortcuts(Object.assign({}, shortcuts, _defineProperty({}, "".concat(addon, "-").concat(shortcut.actionName), shortcut.defaultShortcut)));
case 3:
addonsShortcuts["".concat(addon, "-").concat(shortcut.actionName)] = shortcut;
return _context4.abrupt("return", shortcut);
case 5:
case "end":
return _context4.stop();
}
}
}, _callee4);
}))();
},
restoreDefaultShortcut: function restoreDefaultShortcut(action) {
return _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5() {
var defaultShortcut;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
defaultShortcut = api.getDefaultShortcuts()[action];
return _context5.abrupt("return", api.setShortcut(action, defaultShortcut));
case 2:
case "end":
return _context5.stop();
}
}
}, _callee5);
}))();
},
// Listening to shortcut events
handleKeydownEvent: function handleKeydownEvent(event) {
var shortcut = eventToShortcut(event);
var shortcuts = api.getShortcutKeys();
var actions = keys(shortcuts);
var matchedFeature = actions.find(function (feature) {
return shortcutMatchesShortcut(shortcut, shortcuts[feature]);
});
if (matchedFeature) {
// Event.prototype.preventDefault is missing when received from the MessageChannel.
if (event !== null && event !== void 0 && event.preventDefault) event.preventDefault();
api.handleShortcutFeature(matchedFeature);
}
},
// warning: event might not have a full prototype chain because it may originate from the channel
handleShortcutFeature: function handleShortcutFeature(feature) {
var _store$getState = store.getState(),
_store$getState$layou = _store$getState.layout,
isFullscreen = _store$getState$layou.isFullscreen,
showNav = _store$getState$layou.showNav,
showPanel = _store$getState$layou.showPanel,
enableShortcuts = _store$getState.ui.enableShortcuts;
if (!enableShortcuts) {
return;
}
switch (feature) {
case 'escape':
{
if (isFullscreen) {
fullAPI.toggleFullscreen();
} else if (!showNav) {
fullAPI.toggleNav();
}
break;
}
case 'focusNav':
{
if (isFullscreen) {
fullAPI.toggleFullscreen();
}
if (!showNav) {
fullAPI.toggleNav();
}
fullAPI.focusOnUIElement(focusableUIElements.storyListMenu);
break;
}
case 'search':
{
if (isFullscreen) {
fullAPI.toggleFullscreen();
}
if (!showNav) {
fullAPI.toggleNav();
}
setTimeout(function () {
fullAPI.focusOnUIElement(focusableUIElements.storySearchField, true);
}, 0);
break;
}
case 'focusIframe':
{
var element = document.getElementById('storybook-preview-iframe');
if (element) {
try {
// should be like a channel message and all that, but yolo for now
element.contentWindow.focus();
} catch (e) {//
}
}
break;
}
case 'focusPanel':
{
if (isFullscreen) {
fullAPI.toggleFullscreen();
}
if (!showPanel) {
fullAPI.togglePanel();
}
fullAPI.focusOnUIElement(focusableUIElements.storyPanelRoot);
break;
}
case 'nextStory':
{
fullAPI.jumpToStory(1);
break;
}
case 'prevStory':
{
fullAPI.jumpToStory(-1);
break;
}
case 'nextComponent':
{
fullAPI.jumpToComponent(1);
break;
}
case 'prevComponent':
{
fullAPI.jumpToComponent(-1);
break;
}
case 'fullScreen':
{
fullAPI.toggleFullscreen();
break;
}
case 'togglePanel':
{
if (isFullscreen) {
fullAPI.toggleFullscreen();
fullAPI.resetLayout();
}
fullAPI.togglePanel();
break;
}
case 'toggleNav':
{
if (isFullscreen) {
fullAPI.toggleFullscreen();
fullAPI.resetLayout();
}
fullAPI.toggleNav();
break;
}
case 'toolbar':
{
fullAPI.toggleToolbar();
break;
}
case 'panelPosition':
{
if (isFullscreen) {
fullAPI.toggleFullscreen();
}
if (!showPanel) {
fullAPI.togglePanel();
}
fullAPI.togglePanelPosition();
break;
}
case 'aboutPage':
{
fullAPI.navigate('/settings/about');
break;
}
case 'shortcutsPage':
{
fullAPI.navigate('/settings/shortcuts');
break;
}
case 'collapseAll':
{
fullAPI.collapseAll();
break;
}
case 'expandAll':
{
fullAPI.expandAll();
break;
}
default:
addonsShortcuts[feature].action();
break;
}
}
};
var _store$getState2 = store.getState(),
_store$getState2$shor = _store$getState2.shortcuts,
persistedShortcuts = _store$getState2$shor === void 0 ? defaultShortcuts : _store$getState2$shor;
var state = {
// Any saved shortcuts that are still in our set of defaults
shortcuts: keys(defaultShortcuts).reduce(function (acc, key) {
return Object.assign({}, acc, _defineProperty({}, key, persistedShortcuts[key] || defaultShortcuts[key]));
}, defaultShortcuts)
};
var initModule = function initModule() {
// Listen for keydown events in the manager
document.addEventListener('keydown', function (event) {
if (!focusInInput(event)) {
fullAPI.handleKeydownEvent(event);
}
}); // Also listen to keydown events sent over the channel
fullAPI.on(PREVIEW_KEYDOWN, function (data) {
fullAPI.handleKeydownEvent(data.event);
});
};
return {
api: api,
state: state,
init: initModule
};
};