@wener/console
Version:
Base console UI toolkit
135 lines (134 loc) • 4.6 kB
JavaScript
import React, { cloneElement, isValidElement, useEffect, useRef } from "react";
import { createPortal } from "react-dom";
import { PiBrowser } from "react-icons/pi";
import { getGlobalStates } from "@wener/utils";
import { uniqBy } from "es-toolkit";
import { createStore, useStore } from "zustand";
import { mutative } from "zustand-mutative";
import { getConsoleEmitter } from "../ConsoleEmitter.js";
import { ConsoleEventType } from "../context.js";
function createLauncherStore() {
return createStore(mutative(function () {
return {
open: false,
items: []
};
}));
}
function LauncherHost() {
var emitter = getConsoleEmitter();
useEffect(function () {
return emitter.on(ConsoleEventType.LauncherToggle, function (param) {
var open = param.open;
Launcher.toggle(open);
});
}, [
emitter
]);
var store = Launcher.useStore();
var open = useStore(store, function (s) {
return s.open;
});
if (!open) {
return null;
}
return /*#__PURE__*/ createPortal(/*#__PURE__*/ React.createElement(LauncherContent, {
onLaunch: function (v) {
var _v_onLaunch;
(_v_onLaunch = v.onLaunch) === null || _v_onLaunch === void 0 ? void 0 : _v_onLaunch.call(v);
}
}), document.body, "Launcher");
}
/**
* @deprecated use {@link Launcher.Host} instead
*/ export var ConsoleLauncher = LauncherHost;
var LauncherContent = function (param) {
var onLaunch = param.onLaunch;
var store = Launcher.useStore();
var items = store.getState().items;
var ref = useRef(null);
useEffect(function () {
var _ref_current;
(_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.focus();
}, [
ref.current
]);
// note 左侧留出来 dock 的位置
// dismiss layer
// esc to close
// 初次渲染自动获取 focus
return /*#__PURE__*/ React.createElement("div", {
className: "absolute inset-0 z-[100]",
onClick: function () {
store.setState({
open: false
});
},
tabIndex: -1,
onKeyDown: function (e) {
if (e.key === "Escape") {
store.setState({
open: false
});
}
},
ref: ref
}, /*#__PURE__*/ React.createElement("div", {
className: "bg-base-300/20 absolute inset-0 left-14 backdrop-blur"
}, /*#__PURE__*/ React.createElement("div", {
className: "flex flex-wrap gap-10 px-20 py-10"
}, items.map(function (v) {
var key = v.key, title = v.title, icon = v.icon;
var ico = icon || /*#__PURE__*/ React.createElement(PiBrowser, null);
if ( /*#__PURE__*/isValidElement(ico)) {
ico = /*#__PURE__*/ cloneElement(ico, {
className: "w-24 h-24 drop-shadow-lg"
});
}
return /*#__PURE__*/ React.createElement("button", {
key: key,
type: "button",
className: "flex flex-col items-center justify-center gap-1 rounded-lg bg-gray-300/0 p-2 pt-1 transition-all hover:bg-gray-300/40",
onClick: function () {
onLaunch === null || onLaunch === void 0 ? void 0 : onLaunch(v);
}
}, /*#__PURE__*/ React.createElement("div", null, ico), /*#__PURE__*/ React.createElement("div", {
className: "text-sm"
}, title));
}))));
};
(function (Launcher) {
var _getStore = function () {
return getGlobalStates("LauncherStore", createLauncherStore);
};
function setStoreProvider(provider) {
_getStore = provider;
}
Launcher.setStoreProvider = setStoreProvider;
function getStore() {
return _getStore();
}
Launcher.getStore = getStore;
function useStore() {
return getStore();
}
Launcher.useStore = useStore;
Launcher.Host = LauncherHost;
function toggle(open) {
getStore().setState(function (s) {
s.open = open !== null && open !== void 0 ? open : !s.open;
});
}
Launcher.toggle = toggle;
function addItems(items) {
getStore().setState(function (s) {
s.items = uniqBy(s.items.concat(items), function (v) {
return v.key;
}).sort(function (a, b) {
return a.title.localeCompare(b.title);
});
});
}
Launcher.addItems = addItems;
})(Launcher || (Launcher = {}));
export var Launcher;