solid-command-palette
Version:
Add a command palette to your Solid.js App
1,551 lines (1,550 loc) • 56.2 kB
JavaScript
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
import { createRenderEffect, sharedConfig, createSignal, createRoot, onCleanup, batch, $PROXY, getListener, createContext, useContext, createMemo, createEffect, onMount, createComponent, children, mergeProps, createComputed, untrack, splitProps, For, Show, createUniqueId } from "solid-js";
import tinykeys, { parseKeybinding } from "tinykeys";
import Fuse from "fuse.js";
const booleans = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "indeterminate", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected"];
const Properties = new Set(["className", "value", "readOnly", "formNoValidate", "isMap", "noModule", "playsInline", ...booleans]);
const ChildProperties = new Set(["innerHTML", "textContent", "innerText", "children"]);
const Aliases = {
className: "class",
htmlFor: "for"
};
const PropAliases = {
class: "className",
formnovalidate: "formNoValidate",
ismap: "isMap",
nomodule: "noModule",
playsinline: "playsInline",
readonly: "readOnly"
};
const DelegatedEvents = new Set(["beforeinput", "click", "dblclick", "focusin", "focusout", "input", "keydown", "keyup", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup", "pointerdown", "pointermove", "pointerout", "pointerover", "pointerup", "touchend", "touchmove", "touchstart"]);
const SVGNamespace = {
xlink: "http://www.w3.org/1999/xlink",
xml: "http://www.w3.org/XML/1998/namespace"
};
function reconcileArrays(parentNode, a, b) {
let bLength = b.length, aEnd = a.length, bEnd = bLength, aStart = 0, bStart = 0, after = a[aEnd - 1].nextSibling, map = null;
while (aStart < aEnd || bStart < bEnd) {
if (a[aStart] === b[bStart]) {
aStart++;
bStart++;
continue;
}
while (a[aEnd - 1] === b[bEnd - 1]) {
aEnd--;
bEnd--;
}
if (aEnd === aStart) {
const node = bEnd < bLength ? bStart ? b[bStart - 1].nextSibling : b[bEnd - bStart] : after;
while (bStart < bEnd)
parentNode.insertBefore(b[bStart++], node);
} else if (bEnd === bStart) {
while (aStart < aEnd) {
if (!map || !map.has(a[aStart]))
a[aStart].remove();
aStart++;
}
} else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) {
const node = a[--aEnd].nextSibling;
parentNode.insertBefore(b[bStart++], a[aStart++].nextSibling);
parentNode.insertBefore(b[--bEnd], node);
a[aEnd] = b[bEnd];
} else {
if (!map) {
map = new Map();
let i = bStart;
while (i < bEnd)
map.set(b[i], i++);
}
const index = map.get(a[aStart]);
if (index != null) {
if (bStart < index && index < bEnd) {
let i = aStart, sequence = 1, t;
while (++i < aEnd && i < bEnd) {
if ((t = map.get(a[i])) == null || t !== index + sequence)
break;
sequence++;
}
if (sequence > index - bStart) {
const node = a[aStart];
while (bStart < index)
parentNode.insertBefore(b[bStart++], node);
} else
parentNode.replaceChild(b[bStart++], a[aStart++]);
} else
aStart++;
} else
a[aStart++].remove();
}
}
}
const $$EVENTS = "_$DX_DELEGATE";
function template(html, check, isSVG) {
const t = document.createElement("template");
t.innerHTML = html;
let node = t.content.firstChild;
if (isSVG)
node = node.firstChild;
return node;
}
function delegateEvents(eventNames, document2 = window.document) {
const e = document2[$$EVENTS] || (document2[$$EVENTS] = new Set());
for (let i = 0, l = eventNames.length; i < l; i++) {
const name = eventNames[i];
if (!e.has(name)) {
e.add(name);
document2.addEventListener(name, eventHandler);
}
}
}
function setAttribute(node, name, value) {
if (value == null)
node.removeAttribute(name);
else
node.setAttribute(name, value);
}
function setAttributeNS(node, namespace, name, value) {
if (value == null)
node.removeAttributeNS(namespace, name);
else
node.setAttributeNS(namespace, name, value);
}
function addEventListener(node, name, handler, delegate) {
if (delegate) {
if (Array.isArray(handler)) {
node[`$$${name}`] = handler[0];
node[`$$${name}Data`] = handler[1];
} else
node[`$$${name}`] = handler;
} else if (Array.isArray(handler)) {
node.addEventListener(name, (e) => handler[0](handler[1], e));
} else
node.addEventListener(name, handler);
}
function classList(node, value, prev = {}) {
const classKeys = Object.keys(value || {}), prevKeys = Object.keys(prev);
let i, len;
for (i = 0, len = prevKeys.length; i < len; i++) {
const key = prevKeys[i];
if (!key || key === "undefined" || value[key])
continue;
toggleClassKey(node, key, false);
delete prev[key];
}
for (i = 0, len = classKeys.length; i < len; i++) {
const key = classKeys[i], classValue = !!value[key];
if (!key || key === "undefined" || prev[key] === classValue || !classValue)
continue;
toggleClassKey(node, key, true);
prev[key] = classValue;
}
return prev;
}
function style(node, value, prev = {}) {
const nodeStyle = node.style;
if (value == null || typeof value === "string")
return nodeStyle.cssText = value;
typeof prev === "string" && (prev = {});
let v, s;
for (s in prev) {
value[s] == null && nodeStyle.removeProperty(s);
delete prev[s];
}
for (s in value) {
v = value[s];
if (v !== prev[s]) {
nodeStyle.setProperty(s, v);
prev[s] = v;
}
}
return prev;
}
function spread(node, accessor, isSVG, skipChildren) {
if (typeof accessor === "function") {
createRenderEffect((current) => spreadExpression(node, accessor(), current, isSVG, skipChildren));
} else
spreadExpression(node, accessor, void 0, isSVG, skipChildren);
}
function insert(parent, accessor, marker, initial) {
if (marker !== void 0 && !initial)
initial = [];
if (typeof accessor !== "function")
return insertExpression(parent, accessor, initial, marker);
createRenderEffect((current) => insertExpression(parent, accessor(), current, marker), initial);
}
function assign(node, props, isSVG, skipChildren, prevProps = {}) {
for (const prop in prevProps) {
if (!(prop in props)) {
if (prop === "children")
continue;
assignProp(node, prop, null, prevProps[prop], isSVG);
}
}
for (const prop in props) {
if (prop === "children") {
if (!skipChildren)
insertExpression(node, props.children);
continue;
}
const value = props[prop];
prevProps[prop] = assignProp(node, prop, value, prevProps[prop], isSVG);
}
}
function toPropertyName(name) {
return name.toLowerCase().replace(/-([a-z])/g, (_, w) => w.toUpperCase());
}
function toggleClassKey(node, key, value) {
const classNames = key.trim().split(/\s+/);
for (let i = 0, nameLen = classNames.length; i < nameLen; i++)
node.classList.toggle(classNames[i], value);
}
function assignProp(node, prop, value, prev, isSVG) {
let isCE, isProp, isChildProp;
if (prop === "style")
return style(node, value, prev);
if (prop === "classList")
return classList(node, value, prev);
if (value === prev)
return prev;
if (prop === "ref") {
value(node);
} else if (prop.slice(0, 3) === "on:") {
node.addEventListener(prop.slice(3), value);
} else if (prop.slice(0, 10) === "oncapture:") {
node.addEventListener(prop.slice(10), value, true);
} else if (prop.slice(0, 2) === "on") {
const name = prop.slice(2).toLowerCase();
const delegate = DelegatedEvents.has(name);
addEventListener(node, name, value, delegate);
delegate && delegateEvents([name]);
} else if ((isChildProp = ChildProperties.has(prop)) || !isSVG && (PropAliases[prop] || (isProp = Properties.has(prop))) || (isCE = node.nodeName.includes("-"))) {
if (isCE && !isProp && !isChildProp)
node[toPropertyName(prop)] = value;
else
node[PropAliases[prop] || prop] = value;
} else {
const ns = isSVG && prop.indexOf(":") > -1 && SVGNamespace[prop.split(":")[0]];
if (ns)
setAttributeNS(node, ns, prop, value);
else
setAttribute(node, Aliases[prop] || prop, value);
}
return value;
}
function eventHandler(e) {
const key = `$$${e.type}`;
let node = e.composedPath && e.composedPath()[0] || e.target;
if (e.target !== node) {
Object.defineProperty(e, "target", {
configurable: true,
value: node
});
}
Object.defineProperty(e, "currentTarget", {
configurable: true,
get() {
return node || document;
}
});
while (node !== null) {
const handler = node[key];
if (handler && !node.disabled) {
const data = node[`${key}Data`];
data !== void 0 ? handler(data, e) : handler(e);
if (e.cancelBubble)
return;
}
node = node.host && node.host !== node && node.host instanceof Node ? node.host : node.parentNode;
}
}
function spreadExpression(node, props, prevProps = {}, isSVG, skipChildren) {
if (!skipChildren && "children" in props) {
createRenderEffect(() => prevProps.children = insertExpression(node, props.children, prevProps.children));
}
createRenderEffect(() => assign(node, props, isSVG, true, prevProps));
return prevProps;
}
function insertExpression(parent, value, current, marker, unwrapArray) {
if (sharedConfig.context && !current)
current = [...parent.childNodes];
while (typeof current === "function")
current = current();
if (value === current)
return current;
const t = typeof value, multi = marker !== void 0;
parent = multi && current[0] && current[0].parentNode || parent;
if (t === "string" || t === "number") {
if (t === "number")
value = value.toString();
if (multi) {
let node = current[0];
if (node && node.nodeType === 3) {
node.data = value;
} else
node = document.createTextNode(value);
current = cleanChildren(parent, current, marker, node);
} else {
if (current !== "" && typeof current === "string") {
current = parent.firstChild.data = value;
} else
current = parent.textContent = value;
}
} else if (value == null || t === "boolean") {
if (sharedConfig.context)
return current;
current = cleanChildren(parent, current, marker);
} else if (t === "function") {
createRenderEffect(() => {
let v = value();
while (typeof v === "function")
v = v();
current = insertExpression(parent, v, current, marker);
});
return () => current;
} else if (Array.isArray(value)) {
const array = [];
if (normalizeIncomingArray(array, value, unwrapArray)) {
createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));
return () => current;
}
if (sharedConfig.context && current && current.length) {
for (let i = 0; i < array.length; i++) {
if (array[i].parentNode)
return current = array;
}
return current;
}
if (array.length === 0) {
current = cleanChildren(parent, current, marker);
if (multi)
return current;
} else {
if (Array.isArray(current)) {
if (current.length === 0) {
appendNodes(parent, array, marker);
} else
reconcileArrays(parent, current, array);
} else if (current == null || current === "") {
appendNodes(parent, array);
} else {
reconcileArrays(parent, multi && current || [parent.firstChild], array);
}
}
current = array;
} else if (value instanceof Node) {
if (sharedConfig.context)
return current = value.parentNode ? multi ? [value] : value : current;
if (Array.isArray(current)) {
if (multi)
return current = cleanChildren(parent, current, marker, value);
cleanChildren(parent, current, null, value);
} else if (current == null || current === "" || !parent.firstChild) {
parent.appendChild(value);
} else
parent.replaceChild(value, parent.firstChild);
current = value;
} else
;
return current;
}
function normalizeIncomingArray(normalized, array, unwrap2) {
let dynamic = false;
for (let i = 0, len = array.length; i < len; i++) {
let item = array[i], t;
if (item instanceof Node) {
normalized.push(item);
} else if (item == null || item === true || item === false)
;
else if (Array.isArray(item)) {
dynamic = normalizeIncomingArray(normalized, item) || dynamic;
} else if ((t = typeof item) === "string") {
normalized.push(document.createTextNode(item));
} else if (t === "function") {
if (unwrap2) {
while (typeof item === "function")
item = item();
dynamic = normalizeIncomingArray(normalized, Array.isArray(item) ? item : [item]) || dynamic;
} else {
normalized.push(item);
dynamic = true;
}
} else
normalized.push(document.createTextNode(item.toString()));
}
return dynamic;
}
function appendNodes(parent, array, marker) {
for (let i = 0, len = array.length; i < len; i++)
parent.insertBefore(array[i], marker);
}
function cleanChildren(parent, current, marker, replacement) {
if (marker === void 0)
return parent.textContent = "";
const node = replacement || document.createTextNode("");
if (current.length) {
let inserted = false;
for (let i = current.length - 1; i >= 0; i--) {
const el = current[i];
if (node !== el) {
const isParent = el.parentNode === parent;
if (!inserted && !i)
isParent ? parent.replaceChild(node, el) : parent.insertBefore(node, marker);
else
isParent && el.remove();
} else
inserted = true;
}
} else
parent.insertBefore(node, marker);
return [node];
}
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
function createElement(tagName, isSVG = false) {
return isSVG ? document.createElementNS(SVG_NAMESPACE, tagName) : document.createElement(tagName);
}
function Portal(props) {
const {
useShadow
} = props, marker = document.createTextNode(""), mount = props.mount || document.body;
function renderPortal() {
if (sharedConfig.context) {
const [s, set] = createSignal(false);
queueMicrotask(() => set(true));
return () => s() && props.children;
} else
return () => props.children;
}
if (mount instanceof HTMLHeadElement) {
const [clean, setClean] = createSignal(false);
const cleanup = () => setClean(true);
createRoot((dispose) => insert(mount, () => !clean() ? renderPortal()() : dispose(), null));
onCleanup(() => {
if (sharedConfig.context)
queueMicrotask(cleanup);
else
cleanup();
});
} else {
const container = createElement(props.isSVG ? "g" : "div", props.isSVG), renderRoot = useShadow && container.attachShadow ? container.attachShadow({
mode: "open"
}) : container;
Object.defineProperty(container, "host", {
get() {
return marker.parentNode;
}
});
insert(renderRoot, renderPortal());
mount.appendChild(container);
props.ref && props.ref(container);
onCleanup(() => mount.removeChild(container));
}
return marker;
}
const $RAW = Symbol("store-raw"), $NODE = Symbol("store-node"), $NAME = Symbol("store-name");
function wrap$1(value, name) {
let p = value[$PROXY];
if (!p) {
Object.defineProperty(value, $PROXY, {
value: p = new Proxy(value, proxyTraps$1)
});
const keys = Object.keys(value), desc = Object.getOwnPropertyDescriptors(value);
for (let i = 0, l = keys.length; i < l; i++) {
const prop = keys[i];
if (desc[prop].get) {
const get = desc[prop].get.bind(p);
Object.defineProperty(value, prop, {
get
});
}
}
}
return p;
}
function isWrappable(obj) {
return obj != null && typeof obj === "object" && (obj[$PROXY] || !obj.__proto__ || obj.__proto__ === Object.prototype || Array.isArray(obj));
}
function unwrap(item, set = new Set()) {
let result, unwrapped, v, prop;
if (result = item != null && item[$RAW])
return result;
if (!isWrappable(item) || set.has(item))
return item;
if (Array.isArray(item)) {
if (Object.isFrozen(item))
item = item.slice(0);
else
set.add(item);
for (let i = 0, l = item.length; i < l; i++) {
v = item[i];
if ((unwrapped = unwrap(v, set)) !== v)
item[i] = unwrapped;
}
} else {
if (Object.isFrozen(item))
item = Object.assign({}, item);
else
set.add(item);
const keys = Object.keys(item), desc = Object.getOwnPropertyDescriptors(item);
for (let i = 0, l = keys.length; i < l; i++) {
prop = keys[i];
if (desc[prop].get)
continue;
v = item[prop];
if ((unwrapped = unwrap(v, set)) !== v)
item[prop] = unwrapped;
}
}
return item;
}
function getDataNodes(target) {
let nodes = target[$NODE];
if (!nodes)
Object.defineProperty(target, $NODE, {
value: nodes = {}
});
return nodes;
}
function proxyDescriptor(target, property) {
const desc = Reflect.getOwnPropertyDescriptor(target, property);
if (!desc || desc.get || !desc.configurable || property === $PROXY || property === $NODE || property === $NAME)
return desc;
delete desc.value;
delete desc.writable;
desc.get = () => target[$PROXY][property];
return desc;
}
function ownKeys(target) {
if (getListener()) {
const nodes = getDataNodes(target);
(nodes._ || (nodes._ = createDataNode()))();
}
return Reflect.ownKeys(target);
}
function createDataNode() {
const [s, set] = createSignal(void 0, {
equals: false,
internal: true
});
s.$ = set;
return s;
}
const proxyTraps$1 = {
get(target, property, receiver) {
if (property === $RAW)
return target;
if (property === $PROXY)
return receiver;
const value = target[property];
if (property === $NODE || property === "__proto__")
return value;
const wrappable = isWrappable(value);
if (getListener() && (typeof value !== "function" || target.hasOwnProperty(property))) {
let nodes, node;
if (wrappable && (nodes = getDataNodes(value))) {
node = nodes._ || (nodes._ = createDataNode());
node();
}
nodes = getDataNodes(target);
node = nodes[property] || (nodes[property] = createDataNode());
node();
}
return wrappable ? wrap$1(value) : value;
},
set() {
return true;
},
deleteProperty() {
return true;
},
ownKeys,
getOwnPropertyDescriptor: proxyDescriptor
};
function setProperty(state, property, value) {
if (state[property] === value)
return;
const array = Array.isArray(state);
const len = state.length;
const isUndefined = value === void 0;
const notify = array || isUndefined === property in state;
if (isUndefined) {
delete state[property];
} else
state[property] = value;
let nodes = getDataNodes(state), node;
(node = nodes[property]) && node.$();
if (array && state.length !== len)
(node = nodes.length) && node.$();
notify && (node = nodes._) && node.$();
}
function mergeStoreNode(state, value) {
const keys = Object.keys(value);
for (let i = 0; i < keys.length; i += 1) {
const key = keys[i];
setProperty(state, key, value[key]);
}
}
function updatePath(current, path, traversed = []) {
let part, prev = current;
if (path.length > 1) {
part = path.shift();
const partType = typeof part, isArray = Array.isArray(current);
if (Array.isArray(part)) {
for (let i = 0; i < part.length; i++) {
updatePath(current, [part[i]].concat(path), [part[i]].concat(traversed));
}
return;
} else if (isArray && partType === "function") {
for (let i = 0; i < current.length; i++) {
if (part(current[i], i))
updatePath(current, [i].concat(path), [i].concat(traversed));
}
return;
} else if (isArray && partType === "object") {
const {
from = 0,
to = current.length - 1,
by = 1
} = part;
for (let i = from; i <= to; i += by) {
updatePath(current, [i].concat(path), [i].concat(traversed));
}
return;
} else if (path.length > 1) {
updatePath(current[part], path, [part].concat(traversed));
return;
}
prev = current[part];
traversed = [part].concat(traversed);
}
let value = path[0];
if (typeof value === "function") {
value = value(prev, traversed);
if (value === prev)
return;
}
if (part === void 0 && value == void 0)
return;
value = unwrap(value);
if (part === void 0 || isWrappable(prev) && isWrappable(value) && !Array.isArray(value)) {
mergeStoreNode(prev, value);
} else
setProperty(current, part, value);
}
function createStore(store, options) {
const unwrappedStore = unwrap(store || {});
const wrappedStore = wrap$1(unwrappedStore);
function setStore(...args) {
batch(() => updatePath(unwrappedStore, args));
}
return [wrappedStore, setStore];
}
const setterTraps = {
get(target, property) {
if (property === $RAW)
return target;
const value = target[property];
return isWrappable(value) ? new Proxy(value, setterTraps) : value;
},
set(target, property, value) {
setProperty(target, property, unwrap(value));
return true;
},
deleteProperty(target, property) {
setProperty(target, property, void 0);
return true;
}
};
function produce(fn) {
return (state) => {
if (isWrappable(state))
fn(new Proxy(state, setterTraps));
return state;
};
}
const storeContext = createContext();
const Provider = storeContext.Provider;
function useStore() {
const store = useContext(storeContext);
if (!store) {
throw new Error("Please use it inside Root component");
}
return store;
}
const rootParentActionId = "__ROOT__";
function getActionContext(action, actionsContext) {
const rootContext = actionsContext.root;
const dynamicContext = actionsContext.dynamic[action.id] || {};
return {
rootContext,
dynamicContext
};
}
function checkActionAllowed(action, actionsContext) {
if (!action.cond) {
return true;
}
const { rootContext, dynamicContext } = getActionContext(action, actionsContext);
const isAllowed = action.cond({ actionId: action.id, rootContext, dynamicContext });
return isAllowed;
}
function runAction(action, actionsContext, storeMethods) {
const { id, run } = action;
if (!run) {
storeMethods.selectParentAction(id);
return;
}
const { rootContext, dynamicContext } = getActionContext(action, actionsContext);
run({ actionId: id, rootContext, dynamicContext });
storeMethods.closePalette();
}
function getShortcutHandlersMap(actionsList, actionsContext, storeMethods) {
const shortcutMap = {};
actionsList.forEach((action) => {
const actionHandler = (event) => {
const targetElem = event.target;
const shortcutsAttr = targetElem.dataset.cpKbdShortcuts;
if (shortcutsAttr === "disabled") {
return;
}
const isAllowed = checkActionAllowed(action, actionsContext);
if (!isAllowed) {
return;
}
event.preventDefault();
runAction(action, actionsContext, storeMethods);
};
const shortcut2 = action.shortcut;
if (shortcut2) {
shortcutMap[shortcut2] = actionHandler;
}
});
return shortcutMap;
}
function getActiveParentAction(activeParentActionIdList) {
const activeId = activeParentActionIdList.at(-1);
const isRoot = activeId === rootParentActionId;
return {
activeId,
isRoot
};
}
function createActionList() {
const [state] = useStore();
const actionsList = createMemo(() => {
return Object.values(state.actions);
});
return actionsList;
}
function createNestedActionList() {
const actionsList = createActionList();
const [state] = useStore();
function nestedActionFilter(action) {
const { activeId, isRoot } = getActiveParentAction(state.activeParentActionIdList);
const isAllowed = isRoot || action.parentActionId === activeId;
return isAllowed;
}
const nestedActionsList = createMemo(() => {
const nestedActionsList2 = actionsList().filter(nestedActionFilter);
return nestedActionsList2;
});
return nestedActionsList;
}
function createConditionalActionList() {
const [state] = useStore();
const nestedActionsList = createNestedActionList();
function conditionalActionFilter(action) {
const isAllowed = checkActionAllowed(action, state.actionsContext);
return isAllowed;
}
const conditionalActionList = createMemo(() => {
const conditionalActionList2 = nestedActionsList().filter(conditionalActionFilter);
return conditionalActionList2;
});
return conditionalActionList;
}
function createSearchResultList() {
const [state] = useStore();
const conditionalActionList = createConditionalActionList();
const fuse = new Fuse(conditionalActionList(), {
keys: [
{
name: "title",
weight: 1
},
{
name: "subtitle",
weight: 0.7
},
{
name: "keywords",
weight: 0.5
}
]
});
const resultsList = createMemo(() => {
if (state.searchText.length === 0) {
return conditionalActionList();
}
const searchResults = fuse.search(state.searchText);
const resultsList2 = searchResults.map((result) => result.item);
return resultsList2;
});
createEffect(() => {
fuse.setCollection(conditionalActionList());
});
return resultsList;
}
function createKbdShortcuts() {
const [state, storeMethods] = useStore();
const { togglePalette } = storeMethods;
const actionsList = createActionList();
let unsubscribe = null;
onMount(() => {
const shortcutMap = getShortcutHandlersMap(actionsList(), state.actionsContext, storeMethods);
const commandPaletteHandler = (event) => {
event.preventDefault();
togglePalette();
};
unsubscribe = tinykeys(window, __spreadProps(__spreadValues({}, shortcutMap), {
"$mod+k": commandPaletteHandler
}));
});
onCleanup(() => {
if (unsubscribe) {
unsubscribe();
}
});
}
const _tmpl$$5 = template(`<div></div>`);
const RootInternal = () => {
createKbdShortcuts();
return null;
};
const Root = (p) => {
const initialActions = p.actions || {};
const initialActionsContext = p.actionsContext || {};
const [state, setState] = createStore({
visibility: "closed",
searchText: "",
activeParentActionIdList: [rootParentActionId],
actions: initialActions,
actionsContext: {
root: initialActionsContext,
dynamic: {}
}
});
const storeMethods = {
setSearchText(newValue) {
setState("searchText", newValue);
},
setActionsContext(actionId, newData) {
setState("actionsContext", "dynamic", actionId, newData);
},
resetActionsContext(actionId) {
setState("actionsContext", "dynamic", produce((dynamicContext) => {
delete dynamicContext[actionId];
}));
},
openPalette() {
setState("visibility", "opened");
},
closePalette() {
setState("visibility", "closed");
const hasActiveParent = state.activeParentActionIdList.length > 1;
if (hasActiveParent) {
storeMethods.setSearchText("");
storeMethods.resetParentAction();
}
},
togglePalette() {
setState("visibility", (prev) => prev === "opened" ? "closed" : "opened");
},
selectParentAction(parentActionId) {
if (parentActionId === rootParentActionId) {
return;
}
setState("activeParentActionIdList", (old) => {
return [...old, parentActionId];
});
storeMethods.setSearchText("");
},
revertParentAction() {
setState("activeParentActionIdList", (old) => {
const {
isRoot
} = getActiveParentAction(old);
if (isRoot) {
return old;
}
const copiedList = [...old];
copiedList.pop();
return copiedList;
});
},
resetParentAction() {
setState("activeParentActionIdList", [rootParentActionId]);
}
};
const store = [state, storeMethods];
return createComponent(Provider, {
value: store,
get children() {
const _el$ = _tmpl$$5.cloneNode(true);
insert(_el$, createComponent(RootInternal, {}), null);
insert(_el$, () => p.children, null);
return _el$;
}
});
};
const Transition = (props) => {
let el;
let first = true;
const [s1, set1] = createSignal();
const [s2, set2] = createSignal();
const resolved = children(() => props.children);
const name = props.name || "s";
props = mergeProps({
name,
enterActiveClass: name + "-enter-active",
enterClass: name + "-enter",
enterToClass: name + "-enter-to",
exitActiveClass: name + "-exit-active",
exitClass: name + "-exit",
exitToClass: name + "-exit-to"
}, props);
const {
onBeforeEnter,
onEnter,
onAfterEnter,
onBeforeExit,
onExit,
onAfterExit
} = props;
function enterTransition(el2, prev) {
if (!first || props.appear) {
let endTransition = function() {
if (el2) {
el2.classList.remove(...enterActiveClasses);
el2.classList.remove(...enterToClasses);
batch(() => {
s1() !== el2 && set1(el2);
s2() === el2 && set2(void 0);
});
onAfterEnter && onAfterEnter(el2);
if (props.mode === "inout")
exitTransition(el2, prev);
}
};
const enterClasses = props.enterClass.split(" ");
const enterActiveClasses = props.enterActiveClass.split(" ");
const enterToClasses = props.enterToClass.split(" ");
onBeforeEnter && onBeforeEnter(el2);
el2.classList.add(...enterClasses);
el2.classList.add(...enterActiveClasses);
requestAnimationFrame(() => {
el2.classList.remove(...enterClasses);
el2.classList.add(...enterToClasses);
onEnter && onEnter(el2, endTransition);
if (!onEnter || onEnter.length < 2) {
el2.addEventListener("transitionend", endTransition, {
once: true
});
el2.addEventListener("animationend", endTransition, {
once: true
});
}
});
}
prev && !props.mode ? set2(el2) : set1(el2);
}
function exitTransition(el2, prev) {
const exitClasses = props.exitClass.split(" ");
const exitActiveClasses = props.exitActiveClass.split(" ");
const exitToClasses = props.exitToClass.split(" ");
if (!prev.parentNode)
return endTransition();
onBeforeExit && onBeforeExit(prev);
prev.classList.add(...exitClasses);
prev.classList.add(...exitActiveClasses);
requestAnimationFrame(() => {
prev.classList.remove(...exitClasses);
prev.classList.add(...exitToClasses);
});
onExit && onExit(prev, endTransition);
if (!onExit || onExit.length < 2) {
prev.addEventListener("transitionend", endTransition, {
once: true
});
prev.addEventListener("animationend", endTransition, {
once: true
});
}
function endTransition() {
prev.classList.remove(...exitActiveClasses);
prev.classList.remove(...exitToClasses);
s1() === prev && set1(void 0);
onAfterExit && onAfterExit(prev);
if (props.mode === "outin")
enterTransition(el2, prev);
}
}
createComputed((prev) => {
el = resolved();
while (typeof el === "function")
el = el();
return untrack(() => {
if (el && el !== prev) {
if (props.mode !== "outin")
enterTransition(el, prev);
else if (first)
set1(el);
}
if (prev && prev !== el && props.mode !== "inout")
exitTransition(el, prev);
first = false;
return el;
});
});
return [s1, s2];
};
const CommandPalettePortal = (p) => {
let portalElem;
createRenderEffect(() => {
if (portalElem) {
return;
}
const parent = document.body;
const newPortalElem = document.createElement("div");
newPortalElem.classList.add("command-palette-portal");
parent.appendChild(newPortalElem);
portalElem = newPortalElem;
});
onCleanup(() => {
if (portalElem) {
portalElem.remove();
portalElem = void 0;
}
});
return createComponent(Portal, {
mount: portalElem,
get children() {
return p.children;
}
});
};
function getFormattedKey(key) {
if (key === "Meta") {
return "\u2318";
}
if (key === "Control") {
return "Ctrl";
}
if (key === "Escape") {
return "Esc";
}
return key;
}
const getFormattedShortcut = (shortcut2) => {
const parsedShortcut = parseKeybinding(shortcut2);
const formattedShortcut = parsedShortcut.map((group2) => {
const flatGroup = group2.flat();
const formattedGroup = flatGroup.map(getFormattedKey);
return formattedGroup;
});
return formattedShortcut;
};
const kbdShortcut = "_kbdShortcut_v1zud_1";
const kbdGroup = "_kbdGroup_v1zud_6";
const kbdKey = "_kbdKey_v1zud_11";
var styles$4 = {
kbdShortcut,
kbdGroup,
kbdKey
};
const _tmpl$$4 = template(`<kbd></kbd>`);
const KbdShortcut = (p) => {
const [l, others] = splitProps(p, ["shortcut", "class"]);
const formattedShortcut = getFormattedShortcut(l.shortcut);
const keyClasses = [styles$4.kbdKey, l.class].join(" ");
return (() => {
const _el$ = _tmpl$$4.cloneNode(true);
spread(_el$, others, false, true);
insert(_el$, createComponent(For, {
each: formattedShortcut,
children: (group2) => (() => {
const _el$2 = _tmpl$$4.cloneNode(true);
insert(_el$2, createComponent(For, {
each: group2,
children: (key) => (() => {
const _el$3 = _tmpl$$4.cloneNode(true);
_el$3.className = keyClasses;
insert(_el$3, key);
return _el$3;
})()
}));
createRenderEffect(() => _el$2.className = styles$4.kbdGroup);
return _el$2;
})()
}));
createRenderEffect(() => _el$.className = styles$4.kbdShortcut);
return _el$;
})();
};
const scrollShape = "_scrollShape_1199m_1";
var styles$3 = {
scrollShape
};
const _tmpl$$3 = template(`<div></div>`);
const ScrollAssist = (p) => {
let intervalId = null;
function triggerNavigation() {
p.onNavigate();
}
function startSelecting() {
triggerNavigation();
intervalId = setInterval(() => {
if (p.status === "running") {
triggerNavigation();
}
}, 500);
}
function stopSelecting() {
if (intervalId) {
clearInterval(intervalId);
}
intervalId = null;
}
function handleMouseEnter() {
if (p.status === "available") {
startSelecting();
}
}
function handleMouseMove(event) {
if (p.status !== "running") {
return;
}
let shouldStop = false;
if (p.direction === "up" && event.movementY > 0) {
shouldStop = true;
}
if (p.direction === "down" && event.movementY < 0) {
shouldStop = true;
}
if (shouldStop) {
p.onStop();
}
}
function handleMouseLeave() {
p.onStop();
}
createEffect(() => {
if (p.status === "stopped") {
stopSelecting();
}
});
return (() => {
const _el$ = _tmpl$$3.cloneNode(true);
_el$.addEventListener("mouseleave", handleMouseLeave);
_el$.$$mousemove = handleMouseMove;
_el$.addEventListener("mouseenter", handleMouseEnter);
createRenderEffect((_p$) => {
const _v$ = styles$3.scrollShape, _v$2 = p.direction, _v$3 = p.status;
_v$ !== _p$._v$ && (_el$.className = _p$._v$ = _v$);
_v$2 !== _p$._v$2 && setAttribute(_el$, "data-direction", _p$._v$2 = _v$2);
_v$3 !== _p$._v$3 && setAttribute(_el$, "data-status", _p$._v$3 = _v$3);
return _p$;
}, {
_v$: void 0,
_v$2: void 0,
_v$3: void 0
});
return _el$;
})();
};
delegateEvents(["mousemove"]);
const visuallyHidden = "_visuallyHidden_1rdqz_1";
const stripSpace = "_stripSpace_1rdqz_14";
var utilStyles = {
visuallyHidden,
stripSpace
};
const resultWrapper = "_resultWrapper_m81ar_1";
const resultList = "_resultList_m81ar_7";
const resultItem = "_resultItem_m81ar_11";
const activeItem = "_activeItem_m81ar_21";
const resultTitle = "_resultTitle_m81ar_25";
const resultSubtitle = "_resultSubtitle_m81ar_30";
const resultShortcut = "_resultShortcut_m81ar_37";
var styles$2 = {
resultWrapper,
resultList,
resultItem,
activeItem,
resultTitle,
resultSubtitle,
resultShortcut
};
const _tmpl$$2 = template(`<p></p>`), _tmpl$2$1 = template(`<li role="option"><div><h4></h4></div><div></div></li>`), _tmpl$3$1 = template(`<div><ul role="listbox"></ul></div>`), _tmpl$4 = template(`<div><h4>Couldn't find any matching actions</h4></div>`);
const ResultItem = (p) => {
let resultItemElem;
let isMoving = false;
function isActive() {
return p.action.id === p.activeItemId;
}
function handleMouseMove(action) {
if (isMoving) {
return;
}
isMoving = true;
p.onActionItemHover(action);
}
function handleMouseLeave() {
isMoving = false;
}
function handleMouseDown(event) {
event.preventDefault();
}
createEffect(() => {
if (isActive() && resultItemElem) {
resultItemElem.scrollIntoView({
behavior: "smooth",
block: "nearest"
});
}
});
return (() => {
const _el$ = _tmpl$2$1.cloneNode(true), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$5 = _el$2.nextSibling;
_el$.$$mousedown = handleMouseDown;
_el$.addEventListener("mouseleave", handleMouseLeave);
_el$.$$mousemove = handleMouseMove;
_el$.$$mousemoveData = p.action;
_el$.$$click = p.onActionItemSelect;
_el$.$$clickData = p.action;
const _ref$ = resultItemElem;
typeof _ref$ === "function" ? _ref$(_el$) : resultItemElem = _el$;
insert(_el$3, () => p.action.title);
insert(_el$2, createComponent(Show, {
get when() {
return p.action.subtitle;
},
get children() {
const _el$4 = _tmpl$$2.cloneNode(true);
insert(_el$4, () => p.action.subtitle);
createRenderEffect(() => _el$4.className = `${styles$2.resultSubtitle} ${utilStyles.stripSpace}`);
return _el$4;
}
}), null);
insert(_el$5, createComponent(Show, {
get when() {
return p.action.shortcut;
},
children: (shortcut2) => createComponent(KbdShortcut, {
get ["class"]() {
return styles$2.resultShortcut;
},
shortcut: shortcut2
})
}));
createRenderEffect((_p$) => {
const _v$ = `scp-result-item-${p.action.id}`, _v$2 = styles$2.resultItem, _v$3 = {
[styles$2.activeItem]: isActive()
}, _v$4 = isActive(), _v$5 = `${styles$2.resultTitle} ${utilStyles.stripSpace}`;
_v$ !== _p$._v$ && setAttribute(_el$, "id", _p$._v$ = _v$);
_v$2 !== _p$._v$2 && (_el$.className = _p$._v$2 = _v$2);
_p$._v$3 = classList(_el$, _v$3, _p$._v$3);
_v$4 !== _p$._v$4 && setAttribute(_el$, "aria-selected", _p$._v$4 = _v$4);
_v$5 !== _p$._v$5 && (_el$3.className = _p$._v$5 = _v$5);
return _p$;
}, {
_v$: void 0,
_v$2: void 0,
_v$3: void 0,
_v$4: void 0,
_v$5: void 0
});
return _el$;
})();
};
const PanelResult = (p) => {
return (() => {
const _el$6 = _tmpl$3$1.cloneNode(true), _el$7 = _el$6.firstChild;
insert(_el$7, createComponent(For, {
get each() {
return p.resultsList;
},
get fallback() {
return (() => {
const _el$8 = _tmpl$4.cloneNode(true), _el$9 = _el$8.firstChild;
createRenderEffect((_p$) => {
const _v$10 = styles$2.resultItem, _v$11 = `${styles$2.resultTitle} ${utilStyles.stripSpace}`;
_v$10 !== _p$._v$10 && (_el$8.className = _p$._v$10 = _v$10);
_v$11 !== _p$._v$11 && (_el$9.className = _p$._v$11 = _v$11);
return _p$;
}, {
_v$10: void 0,
_v$11: void 0
});
return _el$8;
})();
},
children: (action) => createComponent(ResultItem, {
action,
get activeItemId() {
return p.activeItemId;
},
get onActionItemHover() {
return p.onActionItemHover;
},
get onActionItemSelect() {
return p.onActionItemSelect;
}
})
}));
createRenderEffect((_p$) => {
const _v$6 = styles$2.resultWrapper, _v$7 = p.resultListId, _v$8 = p.searchLabelId, _v$9 = `${styles$2.resultList} ${utilStyles.stripSpace}`;
_v$6 !== _p$._v$6 && (_el$6.className = _p$._v$6 = _v$6);
_v$7 !== _p$._v$7 && setAttribute(_el$7, "id", _p$._v$7 = _v$7);
_v$8 !== _p$._v$8 && setAttribute(_el$7, "aria-labelledby", _p$._v$8 = _v$8);
_v$9 !== _p$._v$9 && (_el$7.className = _p$._v$9 = _v$9);
return _p$;
}, {
_v$6: void 0,
_v$7: void 0,
_v$8: void 0,
_v$9: void 0
});
return _el$6;
})();
};
delegateEvents(["click", "mousemove", "mousedown"]);
const footer = "_footer_14oge_1";
const group = "_group_14oge_11";
const shortcut = "_shortcut_14oge_17";
const runShortcut = "_runShortcut_14oge_27";
const icon = "_icon_14oge_31";
const iconArrow = "_iconArrow_14oge_36";
const iconReturn = "_iconReturn_14oge_40";
var styles$1 = {
footer,
group,
shortcut,
runShortcut,
icon,
iconArrow,
iconReturn
};
const _tmpl$$1 = template(`<svg fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M8 7l4-4m0 0l4 4m-4-4v18"></path></svg>`), _tmpl$2 = template(`<svg fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M3 10h10a8 8 0 018 8v2M3 10l6 6m-6-6l6-6"></path></svg>`), _tmpl$3 = template(`<div><div>Navigate with <kbd></kbd><kbd></kbd></div><div>Select using <kbd></kbd></div></div>`);
const IconArrow = (p) => {
return (() => {
const _el$ = _tmpl$$1.cloneNode(true);
createRenderEffect((_p$) => {
const _v$ = `${styles$1.icon} ${styles$1.iconArrow}`, _v$2 = p.direction || "up";
_v$ !== _p$._v$ && setAttribute(_el$, "class", _p$._v$ = _v$);
_v$2 !== _p$._v$2 && setAttribute(_el$, "data-arrow-direction", _p$._v$2 = _v$2);
return _p$;
}, {
_v$: void 0,
_v$2: void 0
});
return _el$;
})();
};
const IconReturn = () => {
return (() => {
const _el$2 = _tmpl$2.cloneNode(true);
createRenderEffect(() => setAttribute(_el$2, "class", `${styles$1.icon} ${styles$1.iconReturn}`));
return _el$2;
})();
};
const PanelFooter = () => {
return (() => {
const _el$3 = _tmpl$3.cloneNode(true), _el$4 = _el$3.firstChild, _el$5 = _el$4.firstChild, _el$7 = _el$5.nextSibling, _el$8 = _el$7.nextSibling, _el$9 = _el$4.nextSibling, _el$10 = _el$9.firstChild, _el$12 = _el$10.nextSibling;
insert(_el$7, createComponent(IconArrow, {}));
insert(_el$8, createComponent(IconArrow, {
direction: "down"
}));
insert(_el$12, createComponent(IconReturn, {}));
createRenderEffect((_p$) => {
const _v$3 = styles$1.footer, _v$4 = styles$1.group, _v$5 = styles$1.shortcut, _v$6 = styles$1.shortcut, _v$7 = styles$1.group, _v$8 = `${styles$1.shortcut} ${styles$1.runShortcut}`;
_v$3 !== _p$._v$3 && (_el$3.className = _p$._v$3 = _v$3);
_v$4 !== _p$._v$4 && (_el$4.className = _p$._v$4 = _v$4);
_v$5 !== _p$._v$5 && (_el$7.className = _p$._v$5 = _v$5);
_v$6 !== _p$._v$6 && (_el$8.className = _p$._v$6 = _v$6);
_v$7 !== _p$._v$7 && (_el$9.className = _p$._v$7 = _v$7);
_v$8 !== _p$._v$8 && (_el$12.className = _p$._v$8 = _v$8);
return _p$;
}, {
_v$3: void 0,
_v$4: void 0,
_v$5: void 0,
_v$6: void 0,
_v$7: void 0,
_v$8: void 0
});
return _el$3;
})();
};
const wrapper = "_wrapper_1lhwr_1";
const palette = "_palette_1lhwr_12";
const panel = "_panel_1lhwr_18";
const animEnter = "_animEnter_1lhwr_36";
const animEnterActive = "_animEnterActive_1lhwr_47";
const animExit = "_animExit_1lhwr_52";
const animExitActive = "_animExitActive_1lhwr_56";
const searchForm = "_searchForm_1lhwr_68";
const searchInput = "_searchInput_1lhwr_75";
const closeBtn = "_closeBtn_1lhwr_96";
var styles = {
wrapper,
palette,
panel,
animEnter,
animEnterActive,
animExit,
animExitActive,
searchForm,
searchInput,
closeBtn
};
const _tmpl$ = template(`<div><div><div role="combobox" aria-haspopup="listbox"><form role="search" novalidate><label>Search for an action and then select one of the option.</label><input type="search" aria-autocomplete="list" autocomplete="off" autocapitalize="off" placeholder="Type a command or search..." data-cp-kbd-shortcuts="disabled"><button type="button"><span>Close the Command Palette</span></button></form></div></div></div>`);
const CommandPaletteInternal = () => {
const [state, storeMethods] = useStore();
const {
closePalette,
setSearchText,
revertParentAction
} = storeMethods;
const resultsList = createSearchResultList();
const [activeItemId, setActiveItemId] = createSignal(null);
const [userInteraction, setUserInteraction] = createSignal("idle");
const searchLabelId = createUniqueId();
const searchInputId = createUniqueId();
const resultListId = createUniqueId();
let wrapperElem;
let searchInputElem;
let closeBtnElem;
let lastFocusedElem;
function triggerRun(action) {
runAction(action, state.actionsContext, storeMethods);
}
function activatePrevItem() {
const actionsList = resultsList();
const actionsCount = actionsList.length;
const activeActionId = activeItemId();
const currentActionIndex = actionsList.findIndex((action) => action.id === activeActionId);
if (currentActionIndex < 0) {
return;
}
const prevActionIndex = (actionsCount + currentActionIndex - 1) % actionsCount;
const prevActionId = actionsList[prevActionIndex].id;
setActiveItemId(prevActionId);
}
function activateNextItem() {
const actionsList = resultsList();
const actionsCount = actionsList.length;
const activeActionId = activeItemId();
const currentActionIndex = actionsList.findIndex((action) => action.id === activeActionId);
if (currentActionIndex < 0) {
return;
}
const nextActionIndex = (currentActionIndex + 1) % actionsCount;
const nextActionId = actionsList[nextActionIndex].id;
setActiveItemId(nextActionId);
}
function handleWrapperClick() {
closePalette();
}
function handlePanelClick(event) {
event.stopPropagation();
}
const handleSearchInput = (event) => {
const newValue = event.currentTarget.value;
setUserInteraction("search");
setSearchText(newValue);
};
function handleActionItemSelect(action) {
triggerRun(action);
}
function handleActionItemHover(action) {
setUserInteraction("navigate-mouse");
setActiveItemId(action.id);
}
function handleKbdEnter(event) {
const targetElem = event.target;
if (closeBtnElem && closeBtnElem.contains(targetElem)) {
return;
}
event.preventDefault();
const activeActionId = activeItemId();
if (!activeActionId) {
return null;
}
const action = state.actions[activeActionId];
triggerRun(action);
}
function handleKbdPrev(event) {
event.preventDefault();
setUserInteraction("navigate-kbd");
activatePrevItem();
}
function handleKbdNext(event) {
event.preventDefault();
setUserInteraction("navigate-kbd");
activateNextItem();
}
function handleKbdFirst(event) {
event.preventDefault();
const actionsList = resultsList();
const firstAction = actionsList[0];
if (firstAction) {
setUserInteraction("navigate-kbd");
setActiveItemId(firstAction.id);
}
}
function handleKbdLast(event) {
event.preventDefault();
const actionsList = resultsList();
const lastAction = actionsList.at(-1);
if (lastAction) {
setUserInteraction("navigate-kbd");
setActiveItemId(lastAction.id);
}
}
function handleKbdDelete() {
const isSearchEmpty = state.searchText.length <= 0;
if (isSearchEmpty) {
revertParentAction();
}
}
function handleScrollAssistPrev() {
setUserInteraction("navigate-scroll-assist");
activatePrevItem();
}
function handleScrollAssistNext() {
setUserInteraction("navigate-scroll-assist");
activateNextItem();
}
function handleScrollAssistStop() {
setUserInteraction("idle");
}
function getScrollAssistStatus() {
if (userInteraction() === "navigate-mouse") {
return "available";