@casualoffice/sheets 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chrome.cjs +82 -63
- package/dist/chrome.cjs.map +1 -1
- package/dist/chrome.d.cts +33 -0
- package/dist/chrome.d.ts +33 -0
- package/dist/chrome.js +82 -63
- package/dist/chrome.js.map +1 -1
- package/dist/embed/embed-runtime.js +107 -107
- package/package.json +1 -1
- package/src/chrome/MenuBar.feature-gate.unit.test.ts +152 -0
- package/src/chrome/MenuBar.tsx +36 -141
- package/src/chrome/menu-model.ts +191 -0
package/dist/chrome.cjs
CHANGED
|
@@ -2750,6 +2750,68 @@ function ensurePluginByName(group) {
|
|
|
2750
2750
|
return ensurePlugin(currentUniver, group);
|
|
2751
2751
|
}
|
|
2752
2752
|
|
|
2753
|
+
// src/chrome/menu-model.ts
|
|
2754
|
+
function featureOn(feature, features) {
|
|
2755
|
+
if (!feature) return true;
|
|
2756
|
+
return features[feature] !== false;
|
|
2757
|
+
}
|
|
2758
|
+
function keepItem(item, features, canOpen) {
|
|
2759
|
+
if (!featureOn(item.feature, features)) return null;
|
|
2760
|
+
if (item.kind === "separator") return item;
|
|
2761
|
+
if (item.kind === "submenu") {
|
|
2762
|
+
const items = filterItems(item.items, features, canOpen);
|
|
2763
|
+
if (items.length === 0) return null;
|
|
2764
|
+
return { ...item, items };
|
|
2765
|
+
}
|
|
2766
|
+
if (item.dialog && !canOpen(item.dialog)) return null;
|
|
2767
|
+
return item;
|
|
2768
|
+
}
|
|
2769
|
+
function filterItems(items, features, canOpen) {
|
|
2770
|
+
const kept = items.map((i) => keepItem(i, features, canOpen)).filter((i) => i !== null);
|
|
2771
|
+
const out = [];
|
|
2772
|
+
for (const item of kept) {
|
|
2773
|
+
if (item.kind === "separator") {
|
|
2774
|
+
if (out.length === 0) continue;
|
|
2775
|
+
if (out[out.length - 1].kind === "separator") continue;
|
|
2776
|
+
}
|
|
2777
|
+
out.push(item);
|
|
2778
|
+
}
|
|
2779
|
+
while (out.length > 0 && out[out.length - 1].kind === "separator") out.pop();
|
|
2780
|
+
return out;
|
|
2781
|
+
}
|
|
2782
|
+
function withMenuExtensions(menus, ext) {
|
|
2783
|
+
if (!ext || ext.length === 0) return menus;
|
|
2784
|
+
const byMenu = /* @__PURE__ */ new Map();
|
|
2785
|
+
for (const e of ext) {
|
|
2786
|
+
const list = byMenu.get(e.menu) ?? [];
|
|
2787
|
+
list.push(e);
|
|
2788
|
+
byMenu.set(e.menu, list);
|
|
2789
|
+
}
|
|
2790
|
+
return menus.map((menu) => {
|
|
2791
|
+
const extras = byMenu.get(menu.id);
|
|
2792
|
+
if (!extras || extras.length === 0) return menu;
|
|
2793
|
+
const items = [...menu.items, { kind: "separator", id: `ext-sep-${menu.id}` }];
|
|
2794
|
+
for (const e of extras) {
|
|
2795
|
+
items.push({
|
|
2796
|
+
kind: "item",
|
|
2797
|
+
id: `ext-${e.id}`,
|
|
2798
|
+
label: e.label,
|
|
2799
|
+
icon: e.icon,
|
|
2800
|
+
shortcut: e.shortcut,
|
|
2801
|
+
dialog: e.dialog,
|
|
2802
|
+
run: e.onClick ? (api) => e.onClick?.(api) : void 0
|
|
2803
|
+
});
|
|
2804
|
+
}
|
|
2805
|
+
return { ...menu, items };
|
|
2806
|
+
});
|
|
2807
|
+
}
|
|
2808
|
+
function computeVisibleMenus(menus, features, canOpen, ext) {
|
|
2809
|
+
return withMenuExtensions(menus, ext).map((menu) => ({
|
|
2810
|
+
...menu,
|
|
2811
|
+
items: filterItems(menu.items, features, canOpen)
|
|
2812
|
+
})).filter((menu) => featureOn(menu.feature, features) && menu.items.length > 0);
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2753
2815
|
// src/chrome/MenuBar.tsx
|
|
2754
2816
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2755
2817
|
function fmtShortcut(shortcut) {
|
|
@@ -3107,7 +3169,8 @@ var MENUS = [
|
|
|
3107
3169
|
id: "about",
|
|
3108
3170
|
label: "About casual sheets",
|
|
3109
3171
|
icon: "help_outline",
|
|
3110
|
-
dialog: "about"
|
|
3172
|
+
dialog: "about",
|
|
3173
|
+
feature: "branding"
|
|
3111
3174
|
}
|
|
3112
3175
|
]
|
|
3113
3176
|
},
|
|
@@ -3655,6 +3718,12 @@ var MENUS = [
|
|
|
3655
3718
|
{
|
|
3656
3719
|
id: "help",
|
|
3657
3720
|
label: "Help",
|
|
3721
|
+
// Whole-menu gate: an embedded host passes `features={{ help: false }}` to
|
|
3722
|
+
// drop the Help menu entirely (no editor-branded surface). Individual
|
|
3723
|
+
// branding links below also carry `feature: 'branding'` so a host that
|
|
3724
|
+
// keeps Help (for keyboard shortcuts) can still hide the About / GitHub
|
|
3725
|
+
// links with `features={{ branding: false }}`.
|
|
3726
|
+
feature: "help",
|
|
3658
3727
|
items: [
|
|
3659
3728
|
{
|
|
3660
3729
|
kind: "item",
|
|
@@ -3664,14 +3733,22 @@ var MENUS = [
|
|
|
3664
3733
|
shortcut: "Ctrl+/",
|
|
3665
3734
|
dialog: "keyboard-shortcuts"
|
|
3666
3735
|
},
|
|
3667
|
-
{ kind: "separator", id: "sep-help" },
|
|
3668
|
-
{
|
|
3736
|
+
{ kind: "separator", id: "sep-help", feature: "branding" },
|
|
3737
|
+
{
|
|
3738
|
+
kind: "item",
|
|
3739
|
+
id: "about",
|
|
3740
|
+
label: "About casual sheets",
|
|
3741
|
+
icon: "info",
|
|
3742
|
+
dialog: "about",
|
|
3743
|
+
feature: "branding"
|
|
3744
|
+
},
|
|
3669
3745
|
{
|
|
3670
3746
|
kind: "item",
|
|
3671
3747
|
id: "github",
|
|
3672
3748
|
label: "View on GitHub",
|
|
3673
3749
|
icon: "open_in_new",
|
|
3674
|
-
run: () => openExternal("https://github.com/CasualOffice/sheets")
|
|
3750
|
+
run: () => openExternal("https://github.com/CasualOffice/sheets"),
|
|
3751
|
+
feature: "branding"
|
|
3675
3752
|
}
|
|
3676
3753
|
]
|
|
3677
3754
|
}
|
|
@@ -3758,60 +3835,6 @@ var SUBMENU_PANEL_STYLE = {
|
|
|
3758
3835
|
boxShadow: "0 6px 20px rgba(0,0,0,0.16)",
|
|
3759
3836
|
zIndex: 1001
|
|
3760
3837
|
};
|
|
3761
|
-
function featureOn(feature, features) {
|
|
3762
|
-
if (!feature) return true;
|
|
3763
|
-
return features[feature] !== false;
|
|
3764
|
-
}
|
|
3765
|
-
function keepItem(item, features, canOpen) {
|
|
3766
|
-
if (!featureOn(item.feature, features)) return null;
|
|
3767
|
-
if (item.kind === "separator") return item;
|
|
3768
|
-
if (item.kind === "submenu") {
|
|
3769
|
-
const items = filterItems(item.items, features, canOpen);
|
|
3770
|
-
if (items.length === 0) return null;
|
|
3771
|
-
return { ...item, items };
|
|
3772
|
-
}
|
|
3773
|
-
if (item.dialog && !canOpen(item.dialog)) return null;
|
|
3774
|
-
return item;
|
|
3775
|
-
}
|
|
3776
|
-
function filterItems(items, features, canOpen) {
|
|
3777
|
-
const kept = items.map((i) => keepItem(i, features, canOpen)).filter((i) => i !== null);
|
|
3778
|
-
const out = [];
|
|
3779
|
-
for (const item of kept) {
|
|
3780
|
-
if (item.kind === "separator") {
|
|
3781
|
-
if (out.length === 0) continue;
|
|
3782
|
-
if (out[out.length - 1].kind === "separator") continue;
|
|
3783
|
-
}
|
|
3784
|
-
out.push(item);
|
|
3785
|
-
}
|
|
3786
|
-
while (out.length > 0 && out[out.length - 1].kind === "separator") out.pop();
|
|
3787
|
-
return out;
|
|
3788
|
-
}
|
|
3789
|
-
function withMenuExtensions(menus, ext) {
|
|
3790
|
-
if (!ext || ext.length === 0) return menus;
|
|
3791
|
-
const byMenu = /* @__PURE__ */ new Map();
|
|
3792
|
-
for (const e of ext) {
|
|
3793
|
-
const list = byMenu.get(e.menu) ?? [];
|
|
3794
|
-
list.push(e);
|
|
3795
|
-
byMenu.set(e.menu, list);
|
|
3796
|
-
}
|
|
3797
|
-
return menus.map((menu) => {
|
|
3798
|
-
const extras = byMenu.get(menu.id);
|
|
3799
|
-
if (!extras || extras.length === 0) return menu;
|
|
3800
|
-
const items = [...menu.items, { kind: "separator", id: `ext-sep-${menu.id}` }];
|
|
3801
|
-
for (const e of extras) {
|
|
3802
|
-
items.push({
|
|
3803
|
-
kind: "item",
|
|
3804
|
-
id: `ext-${e.id}`,
|
|
3805
|
-
label: e.label,
|
|
3806
|
-
icon: e.icon,
|
|
3807
|
-
shortcut: e.shortcut,
|
|
3808
|
-
dialog: e.dialog,
|
|
3809
|
-
run: e.onClick ? (api) => e.onClick?.(api) : void 0
|
|
3810
|
-
});
|
|
3811
|
-
}
|
|
3812
|
-
return { ...menu, items };
|
|
3813
|
-
});
|
|
3814
|
-
}
|
|
3815
3838
|
function MenuBar({ api, features = {}, extensions }) {
|
|
3816
3839
|
const dialogs = useDialogs();
|
|
3817
3840
|
const [open, setOpen] = (0, import_react11.useState)(null);
|
|
@@ -3855,11 +3878,7 @@ function MenuBar({ api, features = {}, extensions }) {
|
|
|
3855
3878
|
}
|
|
3856
3879
|
item.run?.(api);
|
|
3857
3880
|
};
|
|
3858
|
-
const
|
|
3859
|
-
const visibleMenus = baseMenus.map((menu) => ({
|
|
3860
|
-
...menu,
|
|
3861
|
-
items: filterItems(menu.items, features, dialogs.canOpen)
|
|
3862
|
-
})).filter((menu) => featureOn(menu.feature, features) && menu.items.length > 0);
|
|
3881
|
+
const visibleMenus = computeVisibleMenus(MENUS, features, dialogs.canOpen, extensions?.menu);
|
|
3863
3882
|
const renderItems = (items) => items.map((item) => {
|
|
3864
3883
|
if (item.kind === "separator") {
|
|
3865
3884
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: SEPARATOR_STYLE, role: "separator", "aria-hidden": true }, item.id);
|