@blockslides/extension-add-slide-button 0.1.0 → 0.2.1
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/index.cjs +279 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +279 -26
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/add-slide-button.ts +332 -31
package/dist/index.cjs
CHANGED
|
@@ -3097,6 +3097,7 @@ var PluginKey = class {
|
|
|
3097
3097
|
// src/add-slide-button.ts
|
|
3098
3098
|
var SlideNodeView = class {
|
|
3099
3099
|
constructor(node, view, getPos, options) {
|
|
3100
|
+
var _a;
|
|
3100
3101
|
this.node = node;
|
|
3101
3102
|
this.view = view;
|
|
3102
3103
|
this.getPos = getPos;
|
|
@@ -3122,21 +3123,37 @@ var SlideNodeView = class {
|
|
|
3122
3123
|
this.contentDOM.className = "slide";
|
|
3123
3124
|
this.contentDOM.setAttribute("data-node-type", "slide");
|
|
3124
3125
|
}
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3126
|
+
const createButton = (html) => {
|
|
3127
|
+
const btn = document.createElement("button");
|
|
3128
|
+
btn.className = "add-slide-button";
|
|
3129
|
+
btn.innerHTML = html;
|
|
3130
|
+
btn.setAttribute("type", "button");
|
|
3131
|
+
btn.contentEditable = "false";
|
|
3132
|
+
if (options.buttonStyle) {
|
|
3133
|
+
Object.entries(options.buttonStyle).forEach(([key, value]) => {
|
|
3134
|
+
if (key.startsWith("--")) {
|
|
3135
|
+
btn.style.setProperty(key, value);
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
const camelKey = key.replace(
|
|
3139
|
+
/-([a-z])/g,
|
|
3140
|
+
(_, letter) => letter.toUpperCase()
|
|
3141
|
+
);
|
|
3142
|
+
btn.style[camelKey] = value;
|
|
3143
|
+
});
|
|
3144
|
+
}
|
|
3145
|
+
return btn;
|
|
3146
|
+
};
|
|
3147
|
+
const insertEmptySlide = (pos) => {
|
|
3148
|
+
const schema = this.view.state.schema;
|
|
3149
|
+
const slideType = schema.nodes.slide;
|
|
3150
|
+
const paragraphType = schema.nodes.paragraph;
|
|
3151
|
+
const slideContent = paragraphType.create();
|
|
3152
|
+
const slide = slideType.create(null, slideContent);
|
|
3153
|
+
const tr = this.view.state.tr.insert(pos + this.node.nodeSize, slide);
|
|
3154
|
+
this.view.dispatch(tr);
|
|
3155
|
+
};
|
|
3156
|
+
const handlePlusClick = (event) => {
|
|
3140
3157
|
event.preventDefault();
|
|
3141
3158
|
event.stopPropagation();
|
|
3142
3159
|
const pos = this.getPos();
|
|
@@ -3153,17 +3170,117 @@ var SlideNodeView = class {
|
|
|
3153
3170
|
event
|
|
3154
3171
|
});
|
|
3155
3172
|
} else {
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3173
|
+
insertEmptySlide(pos);
|
|
3174
|
+
}
|
|
3175
|
+
};
|
|
3176
|
+
const openPresetModal = (pos) => {
|
|
3177
|
+
if (this.presetModal) {
|
|
3178
|
+
this.presetModal.remove();
|
|
3179
|
+
}
|
|
3180
|
+
const overlay = document.createElement("div");
|
|
3181
|
+
overlay.className = "add-slide-preset-modal";
|
|
3182
|
+
const dialog = document.createElement("div");
|
|
3183
|
+
dialog.className = "add-slide-preset-dialog";
|
|
3184
|
+
if (options.presetBackground) {
|
|
3185
|
+
dialog.style.setProperty("--add-slide-preset-bg", options.presetBackground);
|
|
3163
3186
|
}
|
|
3187
|
+
if (options.presetForeground) {
|
|
3188
|
+
dialog.style.setProperty("--add-slide-preset-fg", options.presetForeground);
|
|
3189
|
+
}
|
|
3190
|
+
const search = document.createElement("input");
|
|
3191
|
+
search.className = "add-slide-preset-search";
|
|
3192
|
+
search.type = "search";
|
|
3193
|
+
search.placeholder = "Choose a template";
|
|
3194
|
+
dialog.appendChild(search);
|
|
3195
|
+
const list = document.createElement("div");
|
|
3196
|
+
list.className = "add-slide-preset-list";
|
|
3197
|
+
const items = [];
|
|
3198
|
+
(options.presets || []).forEach((preset) => {
|
|
3199
|
+
var _a2;
|
|
3200
|
+
const item = document.createElement("button");
|
|
3201
|
+
item.className = "add-slide-preset-item";
|
|
3202
|
+
item.setAttribute("type", "button");
|
|
3203
|
+
item.innerHTML = `
|
|
3204
|
+
<span class="add-slide-preset-icon">${(_a2 = preset.icon) != null ? _a2 : ""}</span>
|
|
3205
|
+
<span class="add-slide-preset-label">${preset.label}</span>
|
|
3206
|
+
`;
|
|
3207
|
+
item.onclick = (event) => {
|
|
3208
|
+
event.preventDefault();
|
|
3209
|
+
event.stopPropagation();
|
|
3210
|
+
try {
|
|
3211
|
+
const nodeJSON = preset.build();
|
|
3212
|
+
const newSlide = this.view.state.schema.nodeFromJSON(nodeJSON);
|
|
3213
|
+
const tr = this.view.state.tr.insert(
|
|
3214
|
+
pos + this.node.nodeSize,
|
|
3215
|
+
newSlide
|
|
3216
|
+
);
|
|
3217
|
+
this.view.dispatch(tr);
|
|
3218
|
+
} catch (err) {
|
|
3219
|
+
console.error("Failed to insert preset slide", err);
|
|
3220
|
+
} finally {
|
|
3221
|
+
overlay.remove();
|
|
3222
|
+
this.presetModal = null;
|
|
3223
|
+
}
|
|
3224
|
+
};
|
|
3225
|
+
list.appendChild(item);
|
|
3226
|
+
items.push(item);
|
|
3227
|
+
});
|
|
3228
|
+
search.oninput = () => {
|
|
3229
|
+
const term = search.value.toLowerCase();
|
|
3230
|
+
items.forEach((item) => {
|
|
3231
|
+
var _a2, _b;
|
|
3232
|
+
const label = (_b = (_a2 = item.querySelector(".add-slide-preset-label")) == null ? void 0 : _a2.textContent) == null ? void 0 : _b.toLowerCase();
|
|
3233
|
+
item.style.display = !term || (label == null ? void 0 : label.includes(term)) ? "" : "none";
|
|
3234
|
+
});
|
|
3235
|
+
};
|
|
3236
|
+
dialog.appendChild(list);
|
|
3237
|
+
const close2 = () => {
|
|
3238
|
+
overlay.remove();
|
|
3239
|
+
this.presetModal = null;
|
|
3240
|
+
};
|
|
3241
|
+
overlay.onclick = (e) => {
|
|
3242
|
+
if (e.target === overlay) {
|
|
3243
|
+
close2();
|
|
3244
|
+
}
|
|
3245
|
+
};
|
|
3246
|
+
document.addEventListener(
|
|
3247
|
+
"keydown",
|
|
3248
|
+
(e) => {
|
|
3249
|
+
if (e.key === "Escape") {
|
|
3250
|
+
close2();
|
|
3251
|
+
}
|
|
3252
|
+
},
|
|
3253
|
+
{ once: true }
|
|
3254
|
+
);
|
|
3255
|
+
overlay.appendChild(dialog);
|
|
3256
|
+
document.body.appendChild(overlay);
|
|
3257
|
+
this.presetModal = overlay;
|
|
3164
3258
|
};
|
|
3165
|
-
|
|
3166
|
-
|
|
3259
|
+
const plusButton = createButton(options.content);
|
|
3260
|
+
plusButton.onclick = handlePlusClick;
|
|
3261
|
+
this.button = plusButton;
|
|
3262
|
+
if (options.showPresets) {
|
|
3263
|
+
const templateButton = createButton(
|
|
3264
|
+
(_a = options.templateButtonContent) != null ? _a : "\u2728"
|
|
3265
|
+
);
|
|
3266
|
+
templateButton.onclick = (event) => {
|
|
3267
|
+
event.preventDefault();
|
|
3268
|
+
event.stopPropagation();
|
|
3269
|
+
const pos = this.getPos();
|
|
3270
|
+
if (pos === void 0) return;
|
|
3271
|
+
openPresetModal(pos);
|
|
3272
|
+
};
|
|
3273
|
+
const group = document.createElement("div");
|
|
3274
|
+
group.className = "add-slide-button-group";
|
|
3275
|
+
group.appendChild(plusButton);
|
|
3276
|
+
group.appendChild(templateButton);
|
|
3277
|
+
this.dom.appendChild(this.contentDOM);
|
|
3278
|
+
this.dom.appendChild(group);
|
|
3279
|
+
} else {
|
|
3280
|
+
this.button = plusButton;
|
|
3281
|
+
this.dom.appendChild(this.contentDOM);
|
|
3282
|
+
this.dom.appendChild(this.button);
|
|
3283
|
+
}
|
|
3167
3284
|
}
|
|
3168
3285
|
update(node) {
|
|
3169
3286
|
if (node.type.name !== "slide") return false;
|
|
@@ -3171,7 +3288,13 @@ var SlideNodeView = class {
|
|
|
3171
3288
|
return true;
|
|
3172
3289
|
}
|
|
3173
3290
|
destroy() {
|
|
3174
|
-
this.button
|
|
3291
|
+
if (this.button) {
|
|
3292
|
+
this.button.onclick = null;
|
|
3293
|
+
}
|
|
3294
|
+
if (this.presetModal) {
|
|
3295
|
+
this.presetModal.remove();
|
|
3296
|
+
this.presetModal = null;
|
|
3297
|
+
}
|
|
3175
3298
|
}
|
|
3176
3299
|
};
|
|
3177
3300
|
var addSlideButtonStyles = `
|
|
@@ -3213,6 +3336,131 @@ var addSlideButtonStyles = `
|
|
|
3213
3336
|
outline: 2px solid var(--editor-focus, #3b82f6);
|
|
3214
3337
|
outline-offset: 2px;
|
|
3215
3338
|
}
|
|
3339
|
+
|
|
3340
|
+
.add-slide-button-group {
|
|
3341
|
+
display: grid;
|
|
3342
|
+
grid-template-columns: repeat(2, 1fr);
|
|
3343
|
+
width: 180px;
|
|
3344
|
+
margin: 16px auto 32px auto;
|
|
3345
|
+
border: 1px solid var(--slide-border, #e5e5e5);
|
|
3346
|
+
border-radius: 12px;
|
|
3347
|
+
overflow: hidden;
|
|
3348
|
+
background-color: var(--slide-bg, #ffffff);
|
|
3349
|
+
box-shadow: var(--slide-shadow, 0 4px 12px rgba(0, 0, 0, 0.08));
|
|
3350
|
+
}
|
|
3351
|
+
|
|
3352
|
+
.add-slide-button-group .add-slide-button {
|
|
3353
|
+
margin: 0;
|
|
3354
|
+
border: none;
|
|
3355
|
+
border-radius: 0;
|
|
3356
|
+
width: 100%;
|
|
3357
|
+
height: 48px;
|
|
3358
|
+
}
|
|
3359
|
+
|
|
3360
|
+
.add-slide-button-group .add-slide-button:first-child {
|
|
3361
|
+
border-right: 1px solid var(--slide-border, #e5e5e5);
|
|
3362
|
+
border-top-left-radius: 12px;
|
|
3363
|
+
border-bottom-left-radius: 12px;
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3366
|
+
.add-slide-button-group .add-slide-button:last-child {
|
|
3367
|
+
border-top-right-radius: 12px;
|
|
3368
|
+
border-bottom-right-radius: 12px;
|
|
3369
|
+
white-space: nowrap;
|
|
3370
|
+
font-size: 14px;
|
|
3371
|
+
padding: 0 12px;
|
|
3372
|
+
}
|
|
3373
|
+
|
|
3374
|
+
.add-slide-preset-modal {
|
|
3375
|
+
position: fixed;
|
|
3376
|
+
inset: 0;
|
|
3377
|
+
background: rgba(0, 0, 0, 0.35);
|
|
3378
|
+
display: flex;
|
|
3379
|
+
align-items: center;
|
|
3380
|
+
justify-content: center;
|
|
3381
|
+
z-index: 9999;
|
|
3382
|
+
}
|
|
3383
|
+
|
|
3384
|
+
.add-slide-preset-dialog {
|
|
3385
|
+
background: var(--add-slide-preset-bg, #ffffff);
|
|
3386
|
+
color: var(--add-slide-preset-fg, #000000);
|
|
3387
|
+
border-radius: 8px;
|
|
3388
|
+
padding: 16px 16px 12px 16px;
|
|
3389
|
+
min-width: 140px;
|
|
3390
|
+
max-width: 480px;
|
|
3391
|
+
max-height: 60vh;
|
|
3392
|
+
overflow: hidden;
|
|
3393
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
|
|
3394
|
+
}
|
|
3395
|
+
|
|
3396
|
+
.add-slide-preset-search {
|
|
3397
|
+
width: 100%;
|
|
3398
|
+
padding: 10px 12px;
|
|
3399
|
+
margin-bottom: 10px;
|
|
3400
|
+
border-radius: 8px;
|
|
3401
|
+
border: 1px solid color-mix(in srgb, var(--add-slide-preset-fg, #000000) 18%, transparent);
|
|
3402
|
+
font-size: 14px;
|
|
3403
|
+
color: inherit;
|
|
3404
|
+
background: color-mix(in srgb, var(--add-slide-preset-bg, #ffffff) 90%, var(--add-slide-preset-fg, #000000) 10%);
|
|
3405
|
+
}
|
|
3406
|
+
.add-slide-preset-search:focus {
|
|
3407
|
+
outline: 2px solid color-mix(in srgb, var(--add-slide-preset-fg, #3b82f6) 35%, transparent);
|
|
3408
|
+
outline-offset: 1px;
|
|
3409
|
+
}
|
|
3410
|
+
|
|
3411
|
+
.add-slide-preset-list {
|
|
3412
|
+
display: flex;
|
|
3413
|
+
flex-direction: column;
|
|
3414
|
+
gap: 6px;
|
|
3415
|
+
max-height: 52vh;
|
|
3416
|
+
overflow: auto;
|
|
3417
|
+
scrollbar-width: none;
|
|
3418
|
+
}
|
|
3419
|
+
|
|
3420
|
+
.add-slide-preset-list::-webkit-scrollbar {
|
|
3421
|
+
display: none;
|
|
3422
|
+
}
|
|
3423
|
+
|
|
3424
|
+
.add-slide-preset-item {
|
|
3425
|
+
display: flex;
|
|
3426
|
+
flex-direction: column;
|
|
3427
|
+
align-items: center;
|
|
3428
|
+
gap: 8px;
|
|
3429
|
+
width: 100%;
|
|
3430
|
+
border: none;
|
|
3431
|
+
background: transparent;
|
|
3432
|
+
color: inherit;
|
|
3433
|
+
padding: 10px 0 12px 0;
|
|
3434
|
+
cursor: pointer;
|
|
3435
|
+
border-bottom: 1px solid color-mix(in srgb, var(--add-slide-preset-fg, #000000) 12%, transparent);
|
|
3436
|
+
}
|
|
3437
|
+
|
|
3438
|
+
.add-slide-preset-item:last-child {
|
|
3439
|
+
border-bottom: none;
|
|
3440
|
+
}
|
|
3441
|
+
|
|
3442
|
+
.add-slide-preset-item:hover {
|
|
3443
|
+
background: rgba(0, 0, 0, 0.03);
|
|
3444
|
+
}
|
|
3445
|
+
|
|
3446
|
+
.add-slide-preset-icon {
|
|
3447
|
+
display: block;
|
|
3448
|
+
width: 100%;
|
|
3449
|
+
height: auto;
|
|
3450
|
+
line-height: 0;
|
|
3451
|
+
}
|
|
3452
|
+
.add-slide-preset-icon > svg {
|
|
3453
|
+
width: 100%;
|
|
3454
|
+
height: auto;
|
|
3455
|
+
display: block;
|
|
3456
|
+
}
|
|
3457
|
+
|
|
3458
|
+
.add-slide-preset-label {
|
|
3459
|
+
text-align: center;
|
|
3460
|
+
font-size: 14px;
|
|
3461
|
+
font-weight: 600;
|
|
3462
|
+
width: 100%;
|
|
3463
|
+
}
|
|
3216
3464
|
`;
|
|
3217
3465
|
var AddSlideButton = import_core.Extension.create({
|
|
3218
3466
|
name: "addSlideButton",
|
|
@@ -3222,7 +3470,12 @@ var AddSlideButton = import_core.Extension.create({
|
|
|
3222
3470
|
injectNonce: void 0,
|
|
3223
3471
|
buttonStyle: {},
|
|
3224
3472
|
content: "+",
|
|
3225
|
-
|
|
3473
|
+
showPresets: false,
|
|
3474
|
+
presets: [],
|
|
3475
|
+
templateButtonContent: "Template +",
|
|
3476
|
+
onClick: null,
|
|
3477
|
+
presetBackground: "#ffffff",
|
|
3478
|
+
presetForeground: "#000000"
|
|
3226
3479
|
};
|
|
3227
3480
|
},
|
|
3228
3481
|
addProseMirrorPlugins() {
|