@domternal/vue 0.15.0 → 1.0.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/README.md +44 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +171 -290
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent, h, computed, Fragment, ref, watch, shallowRef, onMounted, nextTick, onScopeDispose, watchEffect, Teleport, inject, provide, getCurrentInstance, customRef, markRaw, shallowReactive, render } from 'vue';
|
|
2
|
-
import { positionFloatingOnce, PluginKey, positionFloating, ToolbarController, refocusEditorAfterCommand, createFloatingMenuPlugin, FloatingMenuController, defaultIcons, defaultBubbleContexts, createBubbleMenuPlugin, Document, Paragraph, Text, BaseKeymap, History, Editor } from '@domternal/core';
|
|
2
|
+
import { positionFloatingOnce, PluginKey, positionFloating, ToolbarController, refocusEditorAfterCommand, createFloatingMenuPlugin, FloatingMenuController, defaultIcons, defaultBubbleContexts, buildBubbleItemMaps, createBubbleShouldShow, createBubbleMenuPlugin, resolveBubbleNames, Document, Paragraph, Text, BaseKeymap, History, Editor, resolveBubbleMenuItems } from '@domternal/core';
|
|
3
3
|
export { Editor, generateHTML, generateJSON, generateText } from '@domternal/core';
|
|
4
4
|
|
|
5
5
|
// src/useEditor.ts
|
|
@@ -866,11 +866,9 @@ var DomternalToolbar = defineComponent({
|
|
|
866
866
|
computed(() => props.editor ?? contextEditor.value),
|
|
867
867
|
props.layout
|
|
868
868
|
);
|
|
869
|
-
const {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
getDropdownTriggerHtml
|
|
873
|
-
} = useToolbarIcons(props.icons);
|
|
869
|
+
const { getCachedIcon, getCachedItemContent, getDropdownTriggerHtml } = useToolbarIcons(
|
|
870
|
+
props.icons
|
|
871
|
+
);
|
|
874
872
|
const { getTooltip } = useTooltip();
|
|
875
873
|
const { onKeyDown } = useKeyboardNav(controllerRef, toolbarRef, closeDropdown);
|
|
876
874
|
function onButtonClick(item, event) {
|
|
@@ -950,7 +948,9 @@ var DomternalToolbar = defineComponent({
|
|
|
950
948
|
}
|
|
951
949
|
if (item.type === "dropdown") {
|
|
952
950
|
const dd = item;
|
|
953
|
-
const activeItem = dd.items.find(
|
|
951
|
+
const activeItem = dd.items.find(
|
|
952
|
+
(sub) => controllerRef.current?.activeMap.get(sub.name)
|
|
953
|
+
);
|
|
954
954
|
let triggerHtml = getDropdownTriggerHtml(dd, activeItem);
|
|
955
955
|
if (dd.dynamicLabel && !activeItem && dd.computedStyleProperty) {
|
|
956
956
|
let computed7;
|
|
@@ -1000,20 +1000,6 @@ var INITIAL_TRAILING_STATE = {
|
|
|
1000
1000
|
currentBgColorVar: null,
|
|
1001
1001
|
hasAnyColor: false
|
|
1002
1002
|
};
|
|
1003
|
-
function isInsideTableCell($pos) {
|
|
1004
|
-
for (let d = $pos.depth; d > 0; d--) {
|
|
1005
|
-
const name = $pos.node(d).type.name;
|
|
1006
|
-
if (name === "tableCell" || name === "tableHeader") return true;
|
|
1007
|
-
}
|
|
1008
|
-
return false;
|
|
1009
|
-
}
|
|
1010
|
-
function findCellNode(pos) {
|
|
1011
|
-
for (let d = pos.depth; d > 0; d--) {
|
|
1012
|
-
const node = pos.node(d);
|
|
1013
|
-
if (node.type.name === "tableCell" || node.type.name === "tableHeader") return node;
|
|
1014
|
-
}
|
|
1015
|
-
return null;
|
|
1016
|
-
}
|
|
1017
1003
|
function useBubbleMenu(options) {
|
|
1018
1004
|
const { editor, shouldShow, placement = "top", offset = 8, updateDelay = 0, items, contexts: explicitContexts, icons: iconsRef } = options;
|
|
1019
1005
|
const menuRef = ref();
|
|
@@ -1026,9 +1012,7 @@ function useBubbleMenu(options) {
|
|
|
1026
1012
|
const trailing = shallowRef(INITIAL_TRAILING_STATE);
|
|
1027
1013
|
const activeMapRef = /* @__PURE__ */ new Map();
|
|
1028
1014
|
const disabledMapRef = /* @__PURE__ */ new Map();
|
|
1029
|
-
let
|
|
1030
|
-
let dropdownMap;
|
|
1031
|
-
let bubbleDefaults;
|
|
1015
|
+
let maps;
|
|
1032
1016
|
let currentResolvedItems = [];
|
|
1033
1017
|
let initialized = false;
|
|
1034
1018
|
let stopEditorWatch = null;
|
|
@@ -1039,125 +1023,8 @@ function useBubbleMenu(options) {
|
|
|
1039
1023
|
const exts = ed.extensionManager.extensions;
|
|
1040
1024
|
const hasNotionColorPicker = exts.some((e) => e.name === "notionColorPicker");
|
|
1041
1025
|
const hasBlockContextMenu = exts.some((e) => e.name === "blockContextMenu");
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
for (const item of ed.toolbarItems) {
|
|
1045
|
-
if (item.type === "button") {
|
|
1046
|
-
itemMap.set(item.name, item);
|
|
1047
|
-
} else if (item.type === "dropdown") {
|
|
1048
|
-
dropdownMap.set(item.name, item);
|
|
1049
|
-
for (const sub of item.items) {
|
|
1050
|
-
itemMap.set(sub.name, sub);
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
bubbleDefaults = /* @__PURE__ */ new Map();
|
|
1055
|
-
const byCtx = /* @__PURE__ */ new Map();
|
|
1056
|
-
const addItem = (btn) => {
|
|
1057
|
-
const ctx = btn["bubbleMenu"];
|
|
1058
|
-
if (!ctx) return;
|
|
1059
|
-
let arr = byCtx.get(ctx);
|
|
1060
|
-
if (!arr) {
|
|
1061
|
-
arr = [];
|
|
1062
|
-
byCtx.set(ctx, arr);
|
|
1063
|
-
}
|
|
1064
|
-
arr.push(btn);
|
|
1065
|
-
};
|
|
1066
|
-
for (const item of ed.toolbarItems) {
|
|
1067
|
-
if (item.type === "button") addItem(item);
|
|
1068
|
-
else if (item.type === "dropdown") {
|
|
1069
|
-
for (const sub of item.items) addItem(sub);
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
for (const [ctx, ctxItems] of byCtx) {
|
|
1073
|
-
ctxItems.sort((a, b) => (b.priority ?? 100) - (a.priority ?? 100));
|
|
1074
|
-
const result = [];
|
|
1075
|
-
let lastGroup;
|
|
1076
|
-
let sepIdx = 0;
|
|
1077
|
-
for (const item of ctxItems) {
|
|
1078
|
-
if (lastGroup !== void 0 && item.group !== lastGroup) {
|
|
1079
|
-
result.push({ type: "separator", name: `bsep-${String(sepIdx++)}` });
|
|
1080
|
-
}
|
|
1081
|
-
result.push(item);
|
|
1082
|
-
lastGroup = item.group;
|
|
1083
|
-
}
|
|
1084
|
-
bubbleDefaults.set(ctx, result);
|
|
1085
|
-
}
|
|
1086
|
-
const resolveNames = (names) => {
|
|
1087
|
-
const result = [];
|
|
1088
|
-
let sepIdx = 0;
|
|
1089
|
-
for (const name of names) {
|
|
1090
|
-
if (name === "|") {
|
|
1091
|
-
result.push({ type: "separator", name: `sep-${String(sepIdx++)}` });
|
|
1092
|
-
} else {
|
|
1093
|
-
const dropdown = dropdownMap.get(name);
|
|
1094
|
-
if (dropdown) {
|
|
1095
|
-
result.push(dropdown);
|
|
1096
|
-
continue;
|
|
1097
|
-
}
|
|
1098
|
-
const item = itemMap.get(name);
|
|
1099
|
-
if (item) result.push(item);
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
return result;
|
|
1103
|
-
};
|
|
1104
|
-
const getFormatItems = () => {
|
|
1105
|
-
return Array.from(itemMap.values()).filter((item) => item.group === "format").sort((a, b) => (b.priority ?? 100) - (a.priority ?? 100));
|
|
1106
|
-
};
|
|
1107
|
-
const detectContext = (selection, ctxs) => {
|
|
1108
|
-
if ("$anchorCell" in selection) return null;
|
|
1109
|
-
if (selection.node) return selection.node.type.name;
|
|
1110
|
-
if (selection.empty) return null;
|
|
1111
|
-
const fromCell = findCellNode(selection.$from);
|
|
1112
|
-
if (fromCell) {
|
|
1113
|
-
const toCell = findCellNode(selection.$to);
|
|
1114
|
-
if (toCell && fromCell !== toCell) return null;
|
|
1115
|
-
return "table";
|
|
1116
|
-
}
|
|
1117
|
-
const fromName = selection.$from.parent.type.name;
|
|
1118
|
-
if (fromName in ctxs) return fromName;
|
|
1119
|
-
if ("text" in ctxs && selection.$from.parent.type.spec.marks !== "") return "text";
|
|
1120
|
-
const toName = selection.$to.parent.type.name;
|
|
1121
|
-
if (toName in ctxs) return toName;
|
|
1122
|
-
if ("text" in ctxs && selection.$to.parent.type.spec.marks !== "") return "text";
|
|
1123
|
-
return null;
|
|
1124
|
-
};
|
|
1125
|
-
const filterBySchema = (contextName, schemaItems) => {
|
|
1126
|
-
if (contextName === "text" || contextName === "table") return schemaItems;
|
|
1127
|
-
const schema = ed.state.schema;
|
|
1128
|
-
if (!schema) return schemaItems;
|
|
1129
|
-
const nodeType = schema.nodes[contextName];
|
|
1130
|
-
if (!nodeType) return schemaItems;
|
|
1131
|
-
return schemaItems.filter((item) => {
|
|
1132
|
-
const markName = typeof item.isActive === "string" ? item.isActive : null;
|
|
1133
|
-
if (!markName) return true;
|
|
1134
|
-
const markType = schema.marks[markName];
|
|
1135
|
-
if (!markType) return true;
|
|
1136
|
-
return nodeType.allowsMarkType(markType);
|
|
1137
|
-
});
|
|
1138
|
-
};
|
|
1139
|
-
let shouldShowFn = shouldShow;
|
|
1140
|
-
if (!shouldShowFn) {
|
|
1141
|
-
if (contexts) {
|
|
1142
|
-
shouldShowFn = ({ state }) => {
|
|
1143
|
-
const context = detectContext(state.selection, contexts);
|
|
1144
|
-
if (!context) return false;
|
|
1145
|
-
if (context in contexts) {
|
|
1146
|
-
const val = contexts[context];
|
|
1147
|
-
if (val === null) return false;
|
|
1148
|
-
return val === true || Array.isArray(val) && val.length > 0;
|
|
1149
|
-
}
|
|
1150
|
-
return bubbleDefaults.has(context);
|
|
1151
|
-
};
|
|
1152
|
-
} else {
|
|
1153
|
-
shouldShowFn = ({ state }) => {
|
|
1154
|
-
if (state.selection.empty) return false;
|
|
1155
|
-
if (state.selection.node) return bubbleDefaults.has(state.selection.node.type.name);
|
|
1156
|
-
if (isInsideTableCell(state.selection.$from)) return false;
|
|
1157
|
-
return state.selection.$from.parent.type.spec.marks !== "" || state.selection.$to.parent.type.spec.marks !== "";
|
|
1158
|
-
};
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1026
|
+
maps = buildBubbleItemMaps(ed);
|
|
1027
|
+
const shouldShowFn = shouldShow ?? createBubbleShouldShow(maps, contexts);
|
|
1161
1028
|
const plugin = createBubbleMenuPlugin({
|
|
1162
1029
|
pluginKey,
|
|
1163
1030
|
editor: ed,
|
|
@@ -1172,13 +1039,15 @@ function useBubbleMenu(options) {
|
|
|
1172
1039
|
currentResolvedItems = newItems;
|
|
1173
1040
|
resolvedItems.value = newItems;
|
|
1174
1041
|
};
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1042
|
+
const fallbackItems = resolveBubbleNames(
|
|
1043
|
+
items ?? ["bold", "italic", "underline"],
|
|
1044
|
+
maps.itemMap,
|
|
1045
|
+
maps.dropdownMap
|
|
1046
|
+
);
|
|
1047
|
+
const refreshItems = () => {
|
|
1048
|
+
setItems(resolveBubbleMenuItems({ editor: ed, maps, contexts, fallbackItems }));
|
|
1049
|
+
};
|
|
1050
|
+
refreshItems();
|
|
1182
1051
|
const updateStates = (currentEd) => {
|
|
1183
1052
|
let canProxy = null;
|
|
1184
1053
|
try {
|
|
@@ -1203,7 +1072,6 @@ function useBubbleMenu(options) {
|
|
|
1203
1072
|
trackButton(item);
|
|
1204
1073
|
}
|
|
1205
1074
|
};
|
|
1206
|
-
const defaultItems = items ? resolveNames(items) : resolveNames(["bold", "italic", "underline"]);
|
|
1207
1075
|
const syncTrailingState = (currentEd) => {
|
|
1208
1076
|
const sel = currentEd.state.selection;
|
|
1209
1077
|
const isNode = !!sel.node;
|
|
@@ -1240,16 +1108,7 @@ function useBubbleMenu(options) {
|
|
|
1240
1108
|
};
|
|
1241
1109
|
};
|
|
1242
1110
|
const transactionHandler = () => {
|
|
1243
|
-
|
|
1244
|
-
updateContextItems(ed, contexts, detectContext, resolveNames, getFormatItems, filterBySchema, bubbleDefaults, setItems);
|
|
1245
|
-
} else {
|
|
1246
|
-
const sel = ed.state.selection;
|
|
1247
|
-
if (sel.node && bubbleDefaults.has(sel.node.type.name)) {
|
|
1248
|
-
setItems(bubbleDefaults.get(sel.node.type.name) ?? []);
|
|
1249
|
-
} else {
|
|
1250
|
-
setItems(defaultItems);
|
|
1251
|
-
}
|
|
1252
|
-
}
|
|
1111
|
+
refreshItems();
|
|
1253
1112
|
updateStates(ed);
|
|
1254
1113
|
syncTrailingState(ed);
|
|
1255
1114
|
activeVersion.value++;
|
|
@@ -1284,30 +1143,6 @@ function useBubbleMenu(options) {
|
|
|
1284
1143
|
}
|
|
1285
1144
|
}
|
|
1286
1145
|
});
|
|
1287
|
-
function updateContextItems(ed, ctxs, detectContext, resolveNames, getFormatItems, filterBySchema, defaults, setItems) {
|
|
1288
|
-
const ctx = detectContext(ed.state.selection, ctxs);
|
|
1289
|
-
if (!ctx) {
|
|
1290
|
-
setItems([]);
|
|
1291
|
-
return;
|
|
1292
|
-
}
|
|
1293
|
-
if (ctx in ctxs) {
|
|
1294
|
-
const val = ctxs[ctx];
|
|
1295
|
-
if (val === null || Array.isArray(val) && val.length === 0) {
|
|
1296
|
-
setItems([]);
|
|
1297
|
-
return;
|
|
1298
|
-
}
|
|
1299
|
-
if (val === true) {
|
|
1300
|
-
setItems(filterBySchema(ctx, getFormatItems()));
|
|
1301
|
-
} else if (Array.isArray(val)) {
|
|
1302
|
-
const resolved = resolveNames(val);
|
|
1303
|
-
const buttons = resolved.filter((i) => i.type !== "separator");
|
|
1304
|
-
const filtered = new Set(filterBySchema(ctx, buttons).map((b) => b.name));
|
|
1305
|
-
setItems(resolved.filter((i) => i.type === "separator" || filtered.has(i.name)));
|
|
1306
|
-
}
|
|
1307
|
-
} else {
|
|
1308
|
-
setItems(defaults.get(ctx) ?? []);
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
1146
|
const isItemActive = (item) => {
|
|
1312
1147
|
return activeMapRef.get(item.name) ?? false;
|
|
1313
1148
|
};
|
|
@@ -1460,9 +1295,13 @@ var DomternalBubbleMenu = defineComponent({
|
|
|
1460
1295
|
}
|
|
1461
1296
|
}));
|
|
1462
1297
|
}
|
|
1463
|
-
|
|
1298
|
+
const showColor = t.showColorPickerButton && !t.isNodeSelection;
|
|
1299
|
+
const showBlock = t.showBlockMenuButton && !t.isNodeSelection;
|
|
1300
|
+
if (showColor) {
|
|
1301
|
+
if (children.length > 0) {
|
|
1302
|
+
children.push(h("span", { class: "dm-toolbar-separator", role: "separator" }));
|
|
1303
|
+
}
|
|
1464
1304
|
children.push(
|
|
1465
|
-
h("span", { class: "dm-toolbar-separator", role: "separator" }),
|
|
1466
1305
|
h("button", {
|
|
1467
1306
|
ref: colorBtnRef,
|
|
1468
1307
|
type: "button",
|
|
@@ -1488,9 +1327,11 @@ var DomternalBubbleMenu = defineComponent({
|
|
|
1488
1327
|
])
|
|
1489
1328
|
);
|
|
1490
1329
|
}
|
|
1491
|
-
if (
|
|
1330
|
+
if (showBlock) {
|
|
1331
|
+
if (children.length > 0) {
|
|
1332
|
+
children.push(h("span", { class: "dm-toolbar-separator", role: "separator" }));
|
|
1333
|
+
}
|
|
1492
1334
|
children.push(
|
|
1493
|
-
h("span", { class: "dm-toolbar-separator", role: "separator" }),
|
|
1494
1335
|
h("button", {
|
|
1495
1336
|
ref: blockMenuBtnRef,
|
|
1496
1337
|
type: "button",
|
|
@@ -2047,10 +1888,10 @@ var CATEGORY_ICONS = {
|
|
|
2047
1888
|
"Animals & Nature": "\u{1F431}",
|
|
2048
1889
|
"Food & Drink": "\u{1F355}",
|
|
2049
1890
|
"Travel & Places": "\u{1F697}",
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
1891
|
+
Activities: "\u26BD",
|
|
1892
|
+
Objects: "\u{1F4A1}",
|
|
1893
|
+
Symbols: "\u{1F523}",
|
|
1894
|
+
Flags: "\u{1F3C1}"
|
|
2054
1895
|
};
|
|
2055
1896
|
function categoryIcon(cat) {
|
|
2056
1897
|
return CATEGORY_ICONS[cat] ?? cat.charAt(0);
|
|
@@ -2098,7 +1939,7 @@ var DomternalEmojiPicker = defineComponent({
|
|
|
2098
1939
|
return;
|
|
2099
1940
|
}
|
|
2100
1941
|
const cols = 8;
|
|
2101
|
-
let next
|
|
1942
|
+
let next;
|
|
2102
1943
|
switch (event.key) {
|
|
2103
1944
|
case "ArrowRight":
|
|
2104
1945
|
event.preventDefault();
|
|
@@ -2127,20 +1968,24 @@ var DomternalEmojiPicker = defineComponent({
|
|
|
2127
1968
|
swatches[next]?.focus();
|
|
2128
1969
|
}
|
|
2129
1970
|
function renderEmojiButton(item) {
|
|
2130
|
-
return h(
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
1971
|
+
return h(
|
|
1972
|
+
"button",
|
|
1973
|
+
{
|
|
1974
|
+
key: item.name,
|
|
1975
|
+
type: "button",
|
|
1976
|
+
class: "dm-emoji-swatch",
|
|
1977
|
+
tabindex: -1,
|
|
1978
|
+
title: formatName(item.name),
|
|
1979
|
+
"aria-label": formatName(item.name),
|
|
1980
|
+
onMousedown: (e) => {
|
|
1981
|
+
e.preventDefault();
|
|
1982
|
+
},
|
|
1983
|
+
onClick: () => {
|
|
1984
|
+
selectEmoji(item);
|
|
1985
|
+
}
|
|
2139
1986
|
},
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
}
|
|
2143
|
-
}, item.emoji);
|
|
1987
|
+
item.emoji
|
|
1988
|
+
);
|
|
2144
1989
|
}
|
|
2145
1990
|
return () => {
|
|
2146
1991
|
if (!isOpen.value) {
|
|
@@ -2166,21 +2011,28 @@ var DomternalEmojiPicker = defineComponent({
|
|
|
2166
2011
|
"div",
|
|
2167
2012
|
{ class: "dm-emoji-picker-tabs", role: "tablist" },
|
|
2168
2013
|
categoryNames.value.map(
|
|
2169
|
-
(cat) => h(
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2014
|
+
(cat) => h(
|
|
2015
|
+
"button",
|
|
2016
|
+
{
|
|
2017
|
+
key: cat,
|
|
2018
|
+
type: "button",
|
|
2019
|
+
class: [
|
|
2020
|
+
"dm-emoji-picker-tab",
|
|
2021
|
+
activeCategory.value === cat && "dm-emoji-picker-tab--active"
|
|
2022
|
+
],
|
|
2023
|
+
role: "tab",
|
|
2024
|
+
"aria-selected": activeCategory.value === cat,
|
|
2025
|
+
title: cat,
|
|
2026
|
+
"aria-label": cat,
|
|
2027
|
+
onMousedown: (e) => {
|
|
2028
|
+
e.preventDefault();
|
|
2029
|
+
},
|
|
2030
|
+
onClick: () => {
|
|
2031
|
+
scrollToCategory(cat);
|
|
2032
|
+
}
|
|
2179
2033
|
},
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
}
|
|
2183
|
-
}, categoryIcon(cat))
|
|
2034
|
+
categoryIcon(cat)
|
|
2035
|
+
)
|
|
2184
2036
|
)
|
|
2185
2037
|
),
|
|
2186
2038
|
// Grid
|
|
@@ -2195,11 +2047,15 @@ var DomternalEmojiPicker = defineComponent({
|
|
|
2195
2047
|
] : [],
|
|
2196
2048
|
// All categories
|
|
2197
2049
|
...categoryNames.value.flatMap((cat) => [
|
|
2198
|
-
h(
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2050
|
+
h(
|
|
2051
|
+
"div",
|
|
2052
|
+
{
|
|
2053
|
+
key: `label-${cat}`,
|
|
2054
|
+
class: "dm-emoji-picker-category-label",
|
|
2055
|
+
"data-category": cat
|
|
2056
|
+
},
|
|
2057
|
+
cat
|
|
2058
|
+
),
|
|
2203
2059
|
...(categories.value.get(cat) ?? []).map(renderEmojiButton)
|
|
2204
2060
|
])
|
|
2205
2061
|
]
|
|
@@ -2419,6 +2275,14 @@ var EditorContent = defineComponent({
|
|
|
2419
2275
|
});
|
|
2420
2276
|
}
|
|
2421
2277
|
});
|
|
2278
|
+
function paletteFromExtensionOptions(options) {
|
|
2279
|
+
if (typeof options !== "object" || options === null || !("palette" in options)) return [];
|
|
2280
|
+
const palette = options.palette;
|
|
2281
|
+
if (!Array.isArray(palette) || !palette.every((token) => typeof token === "string")) {
|
|
2282
|
+
return [];
|
|
2283
|
+
}
|
|
2284
|
+
return [...palette];
|
|
2285
|
+
}
|
|
2422
2286
|
var TOKEN_LABELS = {
|
|
2423
2287
|
gray: "Gray",
|
|
2424
2288
|
brown: "Brown",
|
|
@@ -2483,8 +2347,7 @@ function useNotionColorPicker(options) {
|
|
|
2483
2347
|
if (!ed || ed.isDestroyed) return;
|
|
2484
2348
|
hostEl.value = ed.view.dom.closest(".dm-editor");
|
|
2485
2349
|
const ext = ed.extensionManager.extensions.find((e) => e.name === "notionColorPicker");
|
|
2486
|
-
|
|
2487
|
-
palette.value = extOptions?.palette ? [...extOptions.palette] : [];
|
|
2350
|
+
palette.value = paletteFromExtensionOptions(ext?.options);
|
|
2488
2351
|
const onOpen = (...args) => {
|
|
2489
2352
|
const detail = args[0];
|
|
2490
2353
|
const incomingAnchor = detail?.anchorElement;
|
|
@@ -2524,19 +2387,27 @@ function useNotionColorPicker(options) {
|
|
|
2524
2387
|
if (!open) return;
|
|
2525
2388
|
const controller = new AbortController();
|
|
2526
2389
|
const { signal } = controller;
|
|
2527
|
-
document.addEventListener(
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2390
|
+
document.addEventListener(
|
|
2391
|
+
"mousedown",
|
|
2392
|
+
(e) => {
|
|
2393
|
+
const target = e.target;
|
|
2394
|
+
if (!target) return;
|
|
2395
|
+
if (panelRef.value?.contains(target)) return;
|
|
2396
|
+
if (anchorEl.value?.contains(target)) return;
|
|
2397
|
+
close({ refocus: false });
|
|
2398
|
+
},
|
|
2399
|
+
{ signal }
|
|
2400
|
+
);
|
|
2401
|
+
document.addEventListener(
|
|
2402
|
+
"keydown",
|
|
2403
|
+
(e) => {
|
|
2404
|
+
if (e.key === "Escape" && isOpen.value) {
|
|
2405
|
+
e.preventDefault();
|
|
2406
|
+
close({ refocus: true });
|
|
2407
|
+
}
|
|
2408
|
+
},
|
|
2409
|
+
{ signal }
|
|
2410
|
+
);
|
|
2540
2411
|
onCleanup(() => {
|
|
2541
2412
|
controller.abort();
|
|
2542
2413
|
});
|
|
@@ -2560,14 +2431,12 @@ function useNotionColorPicker(options) {
|
|
|
2560
2431
|
const cols = 5;
|
|
2561
2432
|
const root = panelRef.value;
|
|
2562
2433
|
if (!root) return;
|
|
2563
|
-
const swatches = Array.from(
|
|
2564
|
-
root.querySelectorAll(".dm-ncp-swatch")
|
|
2565
|
-
);
|
|
2434
|
+
const swatches = Array.from(root.querySelectorAll(".dm-ncp-swatch"));
|
|
2566
2435
|
if (!swatches.length) return;
|
|
2567
2436
|
const active = document.activeElement;
|
|
2568
2437
|
const idx = active ? swatches.indexOf(active) : -1;
|
|
2569
2438
|
if (idx === -1) return;
|
|
2570
|
-
let next
|
|
2439
|
+
let next;
|
|
2571
2440
|
switch (event.key) {
|
|
2572
2441
|
case "ArrowRight":
|
|
2573
2442
|
event.preventDefault();
|
|
@@ -2622,7 +2491,9 @@ var DomternalNotionColorPicker = defineComponent({
|
|
|
2622
2491
|
},
|
|
2623
2492
|
setup(props, { slots }) {
|
|
2624
2493
|
const { editor: contextEditor } = useCurrentEditor();
|
|
2625
|
-
const editorRef = computed(
|
|
2494
|
+
const editorRef = computed(
|
|
2495
|
+
() => props.editor ?? contextEditor.value
|
|
2496
|
+
);
|
|
2626
2497
|
const api = useNotionColorPicker({ editor: editorRef });
|
|
2627
2498
|
const {
|
|
2628
2499
|
isOpen,
|
|
@@ -2651,7 +2522,9 @@ var DomternalNotionColorPicker = defineComponent({
|
|
|
2651
2522
|
id2 = requestAnimationFrame(() => {
|
|
2652
2523
|
if (!panel.isConnected) return;
|
|
2653
2524
|
const active = panel.querySelector(".dm-ncp-swatch.dm-ncp-active");
|
|
2654
|
-
const fallback = panel.querySelector(
|
|
2525
|
+
const fallback = panel.querySelector(
|
|
2526
|
+
'.dm-ncp-swatch--text[data-color="null"]'
|
|
2527
|
+
);
|
|
2655
2528
|
(active ?? fallback)?.focus({ preventScroll: true });
|
|
2656
2529
|
});
|
|
2657
2530
|
});
|
|
@@ -2685,21 +2558,23 @@ var DomternalNotionColorPicker = defineComponent({
|
|
|
2685
2558
|
applyText(null);
|
|
2686
2559
|
}
|
|
2687
2560
|
}),
|
|
2688
|
-
...pal.map(
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
e
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2561
|
+
...pal.map(
|
|
2562
|
+
(t) => h("button", {
|
|
2563
|
+
key: t,
|
|
2564
|
+
type: "button",
|
|
2565
|
+
class: ["dm-ncp-swatch", "dm-ncp-swatch--text", tToken === t && "dm-ncp-active"],
|
|
2566
|
+
"aria-pressed": tToken === t,
|
|
2567
|
+
"data-color": t,
|
|
2568
|
+
title: tokenLabel(t),
|
|
2569
|
+
"aria-label": `${tokenLabel(t)} text`,
|
|
2570
|
+
onMousedown: (e) => {
|
|
2571
|
+
e.preventDefault();
|
|
2572
|
+
},
|
|
2573
|
+
onClick: () => {
|
|
2574
|
+
applyText(t);
|
|
2575
|
+
}
|
|
2576
|
+
})
|
|
2577
|
+
)
|
|
2703
2578
|
])
|
|
2704
2579
|
]),
|
|
2705
2580
|
h("div", { class: "dm-ncp-section" }, [
|
|
@@ -2719,21 +2594,23 @@ var DomternalNotionColorPicker = defineComponent({
|
|
|
2719
2594
|
applyBg(null);
|
|
2720
2595
|
}
|
|
2721
2596
|
}),
|
|
2722
|
-
...pal.map(
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
e
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2597
|
+
...pal.map(
|
|
2598
|
+
(t) => h("button", {
|
|
2599
|
+
key: t,
|
|
2600
|
+
type: "button",
|
|
2601
|
+
class: ["dm-ncp-swatch", "dm-ncp-swatch--bg", bToken === t && "dm-ncp-active"],
|
|
2602
|
+
"aria-pressed": bToken === t,
|
|
2603
|
+
"data-color": t,
|
|
2604
|
+
title: `${tokenLabel(t)} background`,
|
|
2605
|
+
"aria-label": `${tokenLabel(t)} background`,
|
|
2606
|
+
onMousedown: (e) => {
|
|
2607
|
+
e.preventDefault();
|
|
2608
|
+
},
|
|
2609
|
+
onClick: () => {
|
|
2610
|
+
applyBg(t);
|
|
2611
|
+
}
|
|
2612
|
+
})
|
|
2613
|
+
)
|
|
2737
2614
|
])
|
|
2738
2615
|
])
|
|
2739
2616
|
];
|
|
@@ -2744,19 +2621,23 @@ var DomternalNotionColorPicker = defineComponent({
|
|
|
2744
2621
|
const slotChildren = slot ? slot({ api }) : void 0;
|
|
2745
2622
|
const panelChildren = slotChildren ?? renderDefaultPanel();
|
|
2746
2623
|
return h(Teleport, { to: hostEl.value }, [
|
|
2747
|
-
h(
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2624
|
+
h(
|
|
2625
|
+
"div",
|
|
2626
|
+
{
|
|
2627
|
+
ref: panelRef,
|
|
2628
|
+
class: "dm-notion-color-picker",
|
|
2629
|
+
"data-show": "",
|
|
2630
|
+
"data-dm-editor-ui": "",
|
|
2631
|
+
role: "dialog",
|
|
2632
|
+
"aria-label": "Text and background color",
|
|
2633
|
+
// Intentional non-modal: the picker doesn't trap focus (outside-click
|
|
2634
|
+
// closes, editor stays interactive). `role="dialog"` defaults to
|
|
2635
|
+
// modal=true for screen readers, so we explicitly opt out.
|
|
2636
|
+
"aria-modal": "false",
|
|
2637
|
+
onKeydown: onPanelKeydown
|
|
2638
|
+
},
|
|
2639
|
+
panelChildren
|
|
2640
|
+
)
|
|
2760
2641
|
]);
|
|
2761
2642
|
};
|
|
2762
2643
|
}
|