@sendbird/actionbook-core 0.10.1 → 0.10.3
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.d.ts +10 -1
- package/dist/index.js +21 -5
- package/dist/index.js.map +1 -1
- package/dist/ui/index.d.ts +9 -1
- package/dist/ui/index.js +621 -52
- package/dist/ui/index.js.map +1 -1
- package/package.json +1 -1
package/dist/ui/index.js
CHANGED
|
@@ -5149,6 +5149,320 @@ function analyzeJinjaBlocks(doc2) {
|
|
|
5149
5149
|
});
|
|
5150
5150
|
}
|
|
5151
5151
|
|
|
5152
|
+
// src/jinja/evaluator.ts
|
|
5153
|
+
var KEYWORDS2 = {
|
|
5154
|
+
and: "AND",
|
|
5155
|
+
or: "OR",
|
|
5156
|
+
not: "NOT",
|
|
5157
|
+
in: "IN",
|
|
5158
|
+
is: "IS",
|
|
5159
|
+
True: "BOOL",
|
|
5160
|
+
False: "BOOL",
|
|
5161
|
+
true: "BOOL",
|
|
5162
|
+
false: "BOOL",
|
|
5163
|
+
None: "NONE",
|
|
5164
|
+
null: "NONE"
|
|
5165
|
+
};
|
|
5166
|
+
function tokenize(input) {
|
|
5167
|
+
const tokens = [];
|
|
5168
|
+
let i = 0;
|
|
5169
|
+
while (i < input.length) {
|
|
5170
|
+
if (/\s/.test(input[i])) {
|
|
5171
|
+
i++;
|
|
5172
|
+
continue;
|
|
5173
|
+
}
|
|
5174
|
+
if (input[i] === '"' || input[i] === "'") {
|
|
5175
|
+
const quote = input[i];
|
|
5176
|
+
let str = "";
|
|
5177
|
+
i++;
|
|
5178
|
+
while (i < input.length && input[i] !== quote) {
|
|
5179
|
+
if (input[i] === "\\" && i + 1 < input.length) {
|
|
5180
|
+
str += input[i + 1];
|
|
5181
|
+
i += 2;
|
|
5182
|
+
} else {
|
|
5183
|
+
str += input[i];
|
|
5184
|
+
i++;
|
|
5185
|
+
}
|
|
5186
|
+
}
|
|
5187
|
+
if (i >= input.length) return { tokens: [], error: "Unterminated string literal" };
|
|
5188
|
+
i++;
|
|
5189
|
+
tokens.push({ type: "STRING", value: str });
|
|
5190
|
+
continue;
|
|
5191
|
+
}
|
|
5192
|
+
if (/[0-9]/.test(input[i]) || input[i] === "-" && i + 1 < input.length && /[0-9]/.test(input[i + 1]) && (tokens.length === 0 || ["AND", "OR", "NOT", "EQ", "NEQ", "LT", "GT", "LTE", "GTE", "LPAREN", "IN", "IS"].includes(tokens[tokens.length - 1].type))) {
|
|
5193
|
+
let num = "";
|
|
5194
|
+
if (input[i] === "-") {
|
|
5195
|
+
num = "-";
|
|
5196
|
+
i++;
|
|
5197
|
+
}
|
|
5198
|
+
while (i < input.length && /[0-9]/.test(input[i])) {
|
|
5199
|
+
num += input[i];
|
|
5200
|
+
i++;
|
|
5201
|
+
}
|
|
5202
|
+
if (i < input.length && input[i] === ".") {
|
|
5203
|
+
num += ".";
|
|
5204
|
+
i++;
|
|
5205
|
+
while (i < input.length && /[0-9]/.test(input[i])) {
|
|
5206
|
+
num += input[i];
|
|
5207
|
+
i++;
|
|
5208
|
+
}
|
|
5209
|
+
}
|
|
5210
|
+
tokens.push({ type: "NUMBER", value: num });
|
|
5211
|
+
continue;
|
|
5212
|
+
}
|
|
5213
|
+
if (/[a-zA-Z_]/.test(input[i])) {
|
|
5214
|
+
let ident = "";
|
|
5215
|
+
while (i < input.length && /[a-zA-Z0-9_.]/.test(input[i])) {
|
|
5216
|
+
ident += input[i];
|
|
5217
|
+
i++;
|
|
5218
|
+
}
|
|
5219
|
+
const kwType = KEYWORDS2[ident];
|
|
5220
|
+
if (kwType) {
|
|
5221
|
+
tokens.push({ type: kwType, value: ident });
|
|
5222
|
+
} else {
|
|
5223
|
+
tokens.push({ type: "IDENT", value: ident });
|
|
5224
|
+
}
|
|
5225
|
+
continue;
|
|
5226
|
+
}
|
|
5227
|
+
if (i + 1 < input.length) {
|
|
5228
|
+
const two = input[i] + input[i + 1];
|
|
5229
|
+
if (two === "==") {
|
|
5230
|
+
tokens.push({ type: "EQ", value: "==" });
|
|
5231
|
+
i += 2;
|
|
5232
|
+
continue;
|
|
5233
|
+
}
|
|
5234
|
+
if (two === "!=") {
|
|
5235
|
+
tokens.push({ type: "NEQ", value: "!=" });
|
|
5236
|
+
i += 2;
|
|
5237
|
+
continue;
|
|
5238
|
+
}
|
|
5239
|
+
if (two === "<=") {
|
|
5240
|
+
tokens.push({ type: "LTE", value: "<=" });
|
|
5241
|
+
i += 2;
|
|
5242
|
+
continue;
|
|
5243
|
+
}
|
|
5244
|
+
if (two === ">=") {
|
|
5245
|
+
tokens.push({ type: "GTE", value: ">=" });
|
|
5246
|
+
i += 2;
|
|
5247
|
+
continue;
|
|
5248
|
+
}
|
|
5249
|
+
}
|
|
5250
|
+
if (input[i] === "<") {
|
|
5251
|
+
tokens.push({ type: "LT", value: "<" });
|
|
5252
|
+
i++;
|
|
5253
|
+
continue;
|
|
5254
|
+
}
|
|
5255
|
+
if (input[i] === ">") {
|
|
5256
|
+
tokens.push({ type: "GT", value: ">" });
|
|
5257
|
+
i++;
|
|
5258
|
+
continue;
|
|
5259
|
+
}
|
|
5260
|
+
if (input[i] === "(") {
|
|
5261
|
+
tokens.push({ type: "LPAREN", value: "(" });
|
|
5262
|
+
i++;
|
|
5263
|
+
continue;
|
|
5264
|
+
}
|
|
5265
|
+
if (input[i] === ")") {
|
|
5266
|
+
tokens.push({ type: "RPAREN", value: ")" });
|
|
5267
|
+
i++;
|
|
5268
|
+
continue;
|
|
5269
|
+
}
|
|
5270
|
+
return { tokens: [], error: `Unexpected character: ${input[i]}` };
|
|
5271
|
+
}
|
|
5272
|
+
tokens.push({ type: "EOF", value: "" });
|
|
5273
|
+
return { tokens };
|
|
5274
|
+
}
|
|
5275
|
+
var Parser = class {
|
|
5276
|
+
pos = 0;
|
|
5277
|
+
tokens;
|
|
5278
|
+
variables;
|
|
5279
|
+
constructor(tokens, variables) {
|
|
5280
|
+
this.tokens = tokens;
|
|
5281
|
+
this.variables = variables;
|
|
5282
|
+
}
|
|
5283
|
+
peek() {
|
|
5284
|
+
return this.tokens[this.pos] ?? { type: "EOF", value: "" };
|
|
5285
|
+
}
|
|
5286
|
+
advance() {
|
|
5287
|
+
const t = this.tokens[this.pos];
|
|
5288
|
+
this.pos++;
|
|
5289
|
+
return t;
|
|
5290
|
+
}
|
|
5291
|
+
expect(type) {
|
|
5292
|
+
const t = this.peek();
|
|
5293
|
+
if (t.type !== type) {
|
|
5294
|
+
throw new Error(`Expected ${type}, got ${t.type}`);
|
|
5295
|
+
}
|
|
5296
|
+
return this.advance();
|
|
5297
|
+
}
|
|
5298
|
+
// Grammar (precedence low→high):
|
|
5299
|
+
// expr → or_expr
|
|
5300
|
+
// or_expr → and_expr ('or' and_expr)*
|
|
5301
|
+
// and_expr → not_expr ('and' not_expr)*
|
|
5302
|
+
// not_expr → 'not' not_expr | cmp_expr
|
|
5303
|
+
// cmp_expr → primary (('=='|'!='|'<'|'>'|'<='|'>='|'in'|'is'|'is not') primary)?
|
|
5304
|
+
// primary → STRING | NUMBER | BOOL | NONE | IDENT | '(' expr ')'
|
|
5305
|
+
evaluate() {
|
|
5306
|
+
const result = this.orExpr();
|
|
5307
|
+
if (this.peek().type !== "EOF") {
|
|
5308
|
+
throw new Error(`Unexpected token: ${this.peek().value}`);
|
|
5309
|
+
}
|
|
5310
|
+
return result;
|
|
5311
|
+
}
|
|
5312
|
+
orExpr() {
|
|
5313
|
+
let left = this.andExpr();
|
|
5314
|
+
while (this.peek().type === "OR") {
|
|
5315
|
+
this.advance();
|
|
5316
|
+
const right = this.andExpr();
|
|
5317
|
+
left = isTruthy(left) || isTruthy(right);
|
|
5318
|
+
}
|
|
5319
|
+
return left;
|
|
5320
|
+
}
|
|
5321
|
+
andExpr() {
|
|
5322
|
+
let left = this.notExpr();
|
|
5323
|
+
while (this.peek().type === "AND") {
|
|
5324
|
+
this.advance();
|
|
5325
|
+
const right = this.notExpr();
|
|
5326
|
+
left = isTruthy(left) && isTruthy(right);
|
|
5327
|
+
}
|
|
5328
|
+
return left;
|
|
5329
|
+
}
|
|
5330
|
+
notExpr() {
|
|
5331
|
+
if (this.peek().type === "NOT") {
|
|
5332
|
+
this.advance();
|
|
5333
|
+
const val = this.notExpr();
|
|
5334
|
+
return !isTruthy(val);
|
|
5335
|
+
}
|
|
5336
|
+
return this.cmpExpr();
|
|
5337
|
+
}
|
|
5338
|
+
cmpExpr() {
|
|
5339
|
+
const left = this.primary();
|
|
5340
|
+
const op = this.peek().type;
|
|
5341
|
+
switch (op) {
|
|
5342
|
+
case "EQ":
|
|
5343
|
+
this.advance();
|
|
5344
|
+
return looseEqual(left, this.primary());
|
|
5345
|
+
case "NEQ":
|
|
5346
|
+
this.advance();
|
|
5347
|
+
return !looseEqual(left, this.primary());
|
|
5348
|
+
case "LT":
|
|
5349
|
+
this.advance();
|
|
5350
|
+
return toNumber(left) < toNumber(this.primary());
|
|
5351
|
+
case "GT":
|
|
5352
|
+
this.advance();
|
|
5353
|
+
return toNumber(left) > toNumber(this.primary());
|
|
5354
|
+
case "LTE":
|
|
5355
|
+
this.advance();
|
|
5356
|
+
return toNumber(left) <= toNumber(this.primary());
|
|
5357
|
+
case "GTE":
|
|
5358
|
+
this.advance();
|
|
5359
|
+
return toNumber(left) >= toNumber(this.primary());
|
|
5360
|
+
case "IN": {
|
|
5361
|
+
this.advance();
|
|
5362
|
+
const collection = this.primary();
|
|
5363
|
+
if (Array.isArray(collection)) {
|
|
5364
|
+
return collection.some((item) => looseEqual(item, left));
|
|
5365
|
+
}
|
|
5366
|
+
if (typeof collection === "string" && typeof left === "string") {
|
|
5367
|
+
return collection.includes(left);
|
|
5368
|
+
}
|
|
5369
|
+
return false;
|
|
5370
|
+
}
|
|
5371
|
+
case "IS": {
|
|
5372
|
+
this.advance();
|
|
5373
|
+
if (this.peek().type === "NOT") {
|
|
5374
|
+
this.advance();
|
|
5375
|
+
return !looseEqual(left, this.primary());
|
|
5376
|
+
}
|
|
5377
|
+
return looseEqual(left, this.primary());
|
|
5378
|
+
}
|
|
5379
|
+
default:
|
|
5380
|
+
return left;
|
|
5381
|
+
}
|
|
5382
|
+
}
|
|
5383
|
+
primary() {
|
|
5384
|
+
const t = this.peek();
|
|
5385
|
+
switch (t.type) {
|
|
5386
|
+
case "STRING":
|
|
5387
|
+
this.advance();
|
|
5388
|
+
return t.value;
|
|
5389
|
+
case "NUMBER":
|
|
5390
|
+
this.advance();
|
|
5391
|
+
return parseFloat(t.value);
|
|
5392
|
+
case "BOOL":
|
|
5393
|
+
this.advance();
|
|
5394
|
+
return t.value === "True" || t.value === "true";
|
|
5395
|
+
case "NONE":
|
|
5396
|
+
this.advance();
|
|
5397
|
+
return null;
|
|
5398
|
+
case "IDENT": {
|
|
5399
|
+
this.advance();
|
|
5400
|
+
return this.resolveVariable(t.value);
|
|
5401
|
+
}
|
|
5402
|
+
case "LPAREN": {
|
|
5403
|
+
this.advance();
|
|
5404
|
+
const val = this.orExpr();
|
|
5405
|
+
this.expect("RPAREN");
|
|
5406
|
+
return val;
|
|
5407
|
+
}
|
|
5408
|
+
default:
|
|
5409
|
+
throw new Error(`Unexpected token in primary: ${t.type} "${t.value}"`);
|
|
5410
|
+
}
|
|
5411
|
+
}
|
|
5412
|
+
resolveVariable(name) {
|
|
5413
|
+
const entry = this.variables.get(name);
|
|
5414
|
+
if (entry === void 0) {
|
|
5415
|
+
return null;
|
|
5416
|
+
}
|
|
5417
|
+
switch (entry.type) {
|
|
5418
|
+
case "string":
|
|
5419
|
+
return String(entry.value);
|
|
5420
|
+
case "number":
|
|
5421
|
+
return Number(entry.value);
|
|
5422
|
+
case "boolean":
|
|
5423
|
+
return entry.value === true || entry.value === "true";
|
|
5424
|
+
default:
|
|
5425
|
+
return String(entry.value);
|
|
5426
|
+
}
|
|
5427
|
+
}
|
|
5428
|
+
};
|
|
5429
|
+
function isTruthy(v) {
|
|
5430
|
+
if (v === null || v === void 0) return false;
|
|
5431
|
+
if (typeof v === "boolean") return v;
|
|
5432
|
+
if (typeof v === "number") return v !== 0;
|
|
5433
|
+
if (typeof v === "string") return v.length > 0;
|
|
5434
|
+
if (Array.isArray(v)) return v.length > 0;
|
|
5435
|
+
return true;
|
|
5436
|
+
}
|
|
5437
|
+
function looseEqual(a, b) {
|
|
5438
|
+
if (a === b) return true;
|
|
5439
|
+
if (a === null || b === null) return a === b;
|
|
5440
|
+
if (typeof a === "number" && typeof b === "string") return a === parseFloat(b);
|
|
5441
|
+
if (typeof a === "string" && typeof b === "number") return parseFloat(a) === b;
|
|
5442
|
+
return false;
|
|
5443
|
+
}
|
|
5444
|
+
function toNumber(v) {
|
|
5445
|
+
if (typeof v === "number") return v;
|
|
5446
|
+
if (typeof v === "string") return parseFloat(v) || 0;
|
|
5447
|
+
if (typeof v === "boolean") return v ? 1 : 0;
|
|
5448
|
+
return 0;
|
|
5449
|
+
}
|
|
5450
|
+
function validateCondition(condition) {
|
|
5451
|
+
const trimmed = condition.trim();
|
|
5452
|
+
if (trimmed === "") return { valid: true };
|
|
5453
|
+
const { tokens, error: tokenError } = tokenize(trimmed);
|
|
5454
|
+
if (tokenError) return { valid: false, error: tokenError };
|
|
5455
|
+
if (tokens.length === 0) return { valid: false, error: "Empty expression" };
|
|
5456
|
+
try {
|
|
5457
|
+
const parser = new Parser(tokens, /* @__PURE__ */ new Map());
|
|
5458
|
+
parser.evaluate();
|
|
5459
|
+
return { valid: true };
|
|
5460
|
+
} catch (e) {
|
|
5461
|
+
const msg = e instanceof Error ? e.message : "Invalid expression";
|
|
5462
|
+
return { valid: false, error: msg };
|
|
5463
|
+
}
|
|
5464
|
+
}
|
|
5465
|
+
|
|
5152
5466
|
// src/tree/documentTree.ts
|
|
5153
5467
|
var MAX_DEPTH6 = 128;
|
|
5154
5468
|
var END_ACTION_RESOURCE_IDS = /* @__PURE__ */ new Set([
|
|
@@ -6116,6 +6430,20 @@ var JINJA_STYLES = `
|
|
|
6116
6430
|
letter-spacing: -0.3px;
|
|
6117
6431
|
}
|
|
6118
6432
|
|
|
6433
|
+
.jinja-branch-header-invalid {
|
|
6434
|
+
border: 1px solid #D9352C;
|
|
6435
|
+
border-radius: 4px;
|
|
6436
|
+
}
|
|
6437
|
+
|
|
6438
|
+
.jinja-condition-error {
|
|
6439
|
+
display: flex;
|
|
6440
|
+
align-items: center;
|
|
6441
|
+
padding: 4px 0 4px 52px;
|
|
6442
|
+
color: #D9352C;
|
|
6443
|
+
font-size: 12px;
|
|
6444
|
+
line-height: 16px;
|
|
6445
|
+
}
|
|
6446
|
+
|
|
6119
6447
|
.jinja-token-variable {
|
|
6120
6448
|
color: #4141B2;
|
|
6121
6449
|
}
|
|
@@ -6501,7 +6829,8 @@ function ConditionDisplay({
|
|
|
6501
6829
|
condition,
|
|
6502
6830
|
editable = true,
|
|
6503
6831
|
onConditionChange,
|
|
6504
|
-
onBackspaceEmpty
|
|
6832
|
+
onBackspaceEmpty,
|
|
6833
|
+
onConditionBlur
|
|
6505
6834
|
}) {
|
|
6506
6835
|
const [isEditing, setIsEditing] = useState3(false);
|
|
6507
6836
|
const [draftValue, setDraftValue] = useState3(condition);
|
|
@@ -6529,6 +6858,7 @@ function ConditionDisplay({
|
|
|
6529
6858
|
}
|
|
6530
6859
|
const commit = () => {
|
|
6531
6860
|
setIsEditing(false);
|
|
6861
|
+
onConditionBlur?.();
|
|
6532
6862
|
if (draftValue !== condition) {
|
|
6533
6863
|
onConditionChange(draftValue);
|
|
6534
6864
|
}
|
|
@@ -6670,8 +7000,17 @@ function JinjaBranchHeader({
|
|
|
6670
7000
|
}
|
|
6671
7001
|
const canOpenFooterMenu = editable && isLastBranch && branchType !== "else";
|
|
6672
7002
|
const isMenuOpen = (source) => menuSource === source && menuItems.length > 0;
|
|
7003
|
+
const [conditionTouched, setConditionTouched] = useState3(false);
|
|
7004
|
+
const conditionError = (() => {
|
|
7005
|
+
if (branchType === "else") return null;
|
|
7006
|
+
if (condition.length === 0) {
|
|
7007
|
+
return conditionTouched ? "This field is required." : null;
|
|
7008
|
+
}
|
|
7009
|
+
const result = validateCondition(condition);
|
|
7010
|
+
return result.valid ? null : result.error || "Invalid condition";
|
|
7011
|
+
})();
|
|
6673
7012
|
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
6674
|
-
/* @__PURE__ */ jsxs5("div", { className: "jinja-branch-header"
|
|
7013
|
+
/* @__PURE__ */ jsxs5("div", { className: `jinja-branch-header${conditionError ? " jinja-branch-header-invalid" : ""}`, children: [
|
|
6675
7014
|
/* @__PURE__ */ jsx6("span", { className: `jinja-branch-badge jinja-branch-badge-${branchType}`, children: branchType === "elif" ? "ELSE IF" : branchType.toUpperCase() }),
|
|
6676
7015
|
/* @__PURE__ */ jsx6(
|
|
6677
7016
|
ConditionDisplay,
|
|
@@ -6680,7 +7019,8 @@ function JinjaBranchHeader({
|
|
|
6680
7019
|
condition,
|
|
6681
7020
|
editable,
|
|
6682
7021
|
onConditionChange,
|
|
6683
|
-
onBackspaceEmpty: onDelete
|
|
7022
|
+
onBackspaceEmpty: onDelete,
|
|
7023
|
+
onConditionBlur: () => setConditionTouched(true)
|
|
6684
7024
|
}
|
|
6685
7025
|
),
|
|
6686
7026
|
editable ? /* @__PURE__ */ jsxs5("div", { className: "jinja-branch-actions", ref: kebabRef, children: [
|
|
@@ -6718,6 +7058,7 @@ function JinjaBranchHeader({
|
|
|
6718
7058
|
) : null
|
|
6719
7059
|
] }) : null
|
|
6720
7060
|
] }),
|
|
7061
|
+
conditionError && /* @__PURE__ */ jsx6("div", { className: "jinja-condition-error", children: conditionError }),
|
|
6721
7062
|
isLastBranch && editable ? /* @__PURE__ */ jsx6("div", { className: "jinja-add-footer", children: /* @__PURE__ */ jsx6("div", { className: "jinja-add-footer-col", children: /* @__PURE__ */ jsxs5("div", { className: "jinja-add-footer-actions", ref: footerRef, children: [
|
|
6722
7063
|
/* @__PURE__ */ jsx6(
|
|
6723
7064
|
"button",
|
|
@@ -7027,17 +7368,17 @@ function createLinkEditPlugin() {
|
|
|
7027
7368
|
if (match) {
|
|
7028
7369
|
const [, label, href, title] = match;
|
|
7029
7370
|
const linkMarkType = newState.schema.marks.link;
|
|
7030
|
-
if (
|
|
7371
|
+
if (!label) {
|
|
7372
|
+
reconvertTr.delete(safeFrom, safeTo);
|
|
7373
|
+
} else if (linkMarkType && href) {
|
|
7031
7374
|
const attrs = title ? { href, title: title.trim() } : { href };
|
|
7032
7375
|
reconvertTr.delete(safeFrom, safeTo);
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
);
|
|
7040
|
-
}
|
|
7376
|
+
reconvertTr.insertText(label, safeFrom);
|
|
7377
|
+
reconvertTr.addMark(
|
|
7378
|
+
safeFrom,
|
|
7379
|
+
safeFrom + label.length,
|
|
7380
|
+
linkMarkType.create(attrs)
|
|
7381
|
+
);
|
|
7041
7382
|
}
|
|
7042
7383
|
}
|
|
7043
7384
|
}
|
|
@@ -7051,12 +7392,17 @@ function createLinkInputRule() {
|
|
|
7051
7392
|
(state, match, start, end) => {
|
|
7052
7393
|
const [, label, href, title] = match;
|
|
7053
7394
|
const linkMarkType = state.schema.marks.link;
|
|
7054
|
-
if (!linkMarkType
|
|
7055
|
-
const displayText = label || href;
|
|
7056
|
-
const attrs = title ? { href, title: title.trim() } : { href };
|
|
7395
|
+
if (!linkMarkType) return null;
|
|
7057
7396
|
const { tr } = state;
|
|
7058
|
-
|
|
7059
|
-
|
|
7397
|
+
if (!label) {
|
|
7398
|
+
tr.delete(start, end);
|
|
7399
|
+
tr.setMeta(linkEditKey, null);
|
|
7400
|
+
return tr;
|
|
7401
|
+
}
|
|
7402
|
+
if (!href) return null;
|
|
7403
|
+
const attrs = title ? { href, title: title.trim() } : { href };
|
|
7404
|
+
tr.replaceWith(start, end, state.schema.text(label));
|
|
7405
|
+
tr.addMark(start, start + label.length, linkMarkType.create(attrs));
|
|
7060
7406
|
tr.setMeta(linkEditKey, null);
|
|
7061
7407
|
return tr;
|
|
7062
7408
|
}
|
|
@@ -8123,14 +8469,12 @@ function injectScrollbarStyle() {
|
|
|
8123
8469
|
const style = document.createElement("style");
|
|
8124
8470
|
style.id = SCROLLBAR_STYLE_ID;
|
|
8125
8471
|
style.textContent = `
|
|
8126
|
-
.ab-slash-menu::-webkit-scrollbar {
|
|
8127
|
-
.ab-slash-menu
|
|
8128
|
-
.ab-slash-menu::-webkit-scrollbar-thumb { background: #c4c4c4; border-radius: 3px; }
|
|
8129
|
-
.ab-slash-menu::-webkit-scrollbar-thumb:hover { background: #999; }
|
|
8472
|
+
.ab-slash-menu::-webkit-scrollbar { display: none; }
|
|
8473
|
+
.ab-slash-menu { scrollbar-width: none; }
|
|
8130
8474
|
`;
|
|
8131
8475
|
document.head.appendChild(style);
|
|
8132
8476
|
}
|
|
8133
|
-
var POPUP_SHADOW = "0
|
|
8477
|
+
var POPUP_SHADOW = "0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)";
|
|
8134
8478
|
var BTN_RESET = {
|
|
8135
8479
|
border: "none",
|
|
8136
8480
|
padding: 0,
|
|
@@ -8212,12 +8556,10 @@ function SlashCommandMenu({ view, editorState, items }) {
|
|
|
8212
8556
|
width: MENU_WIDTH,
|
|
8213
8557
|
maxHeight: MAX_MENU_H,
|
|
8214
8558
|
overflowY: "auto",
|
|
8215
|
-
scrollbarWidth: "thin",
|
|
8216
|
-
scrollbarColor: "#c4c4c4 transparent",
|
|
8217
8559
|
background: "#fff",
|
|
8218
|
-
borderRadius:
|
|
8560
|
+
borderRadius: 8,
|
|
8219
8561
|
boxShadow: POPUP_SHADOW,
|
|
8220
|
-
padding: "
|
|
8562
|
+
padding: "4px",
|
|
8221
8563
|
zIndex: 1100,
|
|
8222
8564
|
animation: "ab-float-in 0.12s ease"
|
|
8223
8565
|
},
|
|
@@ -8283,8 +8625,8 @@ function SlashMenuItem({ item, index, selected, onMouseEnter, onMouseDown }) {
|
|
|
8283
8625
|
display: "flex",
|
|
8284
8626
|
alignItems: "center",
|
|
8285
8627
|
gap: 12,
|
|
8286
|
-
padding: "6px
|
|
8287
|
-
background: selected ? "rgba(
|
|
8628
|
+
padding: "6px 8px",
|
|
8629
|
+
background: selected ? "rgba(0, 0, 0, 0.04)" : "transparent",
|
|
8288
8630
|
transition: "background 0.08s"
|
|
8289
8631
|
},
|
|
8290
8632
|
onMouseEnter,
|
|
@@ -8705,7 +9047,7 @@ function getSelectionDOMRect() {
|
|
|
8705
9047
|
if (rect.width === 0 && rect.height === 0) return null;
|
|
8706
9048
|
return rect;
|
|
8707
9049
|
}
|
|
8708
|
-
var POPUP_SHADOW2 = "0 0 0 1px
|
|
9050
|
+
var POPUP_SHADOW2 = "0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)";
|
|
8709
9051
|
var BTN_RESET2 = {
|
|
8710
9052
|
border: "none",
|
|
8711
9053
|
padding: 0,
|
|
@@ -8737,8 +9079,8 @@ function TBtn({ children, active, title, onMouseDown, style }) {
|
|
|
8737
9079
|
borderRadius: 6,
|
|
8738
9080
|
fontSize: 13,
|
|
8739
9081
|
fontWeight: 600,
|
|
8740
|
-
color: active ? "#
|
|
8741
|
-
background: active ? "rgba(
|
|
9082
|
+
color: active ? "#6210CC" : "#0D0D0D",
|
|
9083
|
+
background: active ? "rgba(98,16,204,0.08)" : hover ? "rgba(0,0,0,0.05)" : "transparent",
|
|
8742
9084
|
transition: "background 0.1s, color 0.1s",
|
|
8743
9085
|
...style
|
|
8744
9086
|
},
|
|
@@ -8832,8 +9174,8 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
8832
9174
|
borderRadius: 6,
|
|
8833
9175
|
fontSize: 11,
|
|
8834
9176
|
fontWeight: 600,
|
|
8835
|
-
color: open ? "#
|
|
8836
|
-
background: open ? "rgba(
|
|
9177
|
+
color: open ? "#6210CC" : "#0D0D0D",
|
|
9178
|
+
background: open ? "rgba(98,16,204,0.08)" : hover ? "rgba(0,0,0,0.04)" : "transparent",
|
|
8837
9179
|
transition: "background 0.1s, color 0.1s",
|
|
8838
9180
|
whiteSpace: "nowrap"
|
|
8839
9181
|
},
|
|
@@ -8854,9 +9196,9 @@ function BlockTypeDropdown({ view, state, label }) {
|
|
|
8854
9196
|
left: btnRect.left,
|
|
8855
9197
|
top: btnRect.bottom + 4,
|
|
8856
9198
|
background: "#fff",
|
|
8857
|
-
borderRadius:
|
|
9199
|
+
borderRadius: 8,
|
|
8858
9200
|
boxShadow: POPUP_SHADOW2,
|
|
8859
|
-
padding:
|
|
9201
|
+
padding: 4,
|
|
8860
9202
|
minWidth: 168,
|
|
8861
9203
|
animation: "ab-float-in 0.12s ease"
|
|
8862
9204
|
},
|
|
@@ -8887,16 +9229,16 @@ function DropdownItem({ item, onRun }) {
|
|
|
8887
9229
|
gap: 10,
|
|
8888
9230
|
width: "100%",
|
|
8889
9231
|
padding: "6px 8px",
|
|
8890
|
-
borderRadius:
|
|
9232
|
+
borderRadius: 4,
|
|
8891
9233
|
textAlign: "left",
|
|
8892
9234
|
fontSize: 13,
|
|
8893
|
-
color: item.active ? "#
|
|
9235
|
+
color: item.active ? "#6210CC" : "#0D0D0D",
|
|
8894
9236
|
fontWeight: item.active ? 600 : 400,
|
|
8895
9237
|
background: hover ? "rgba(0,0,0,0.04)" : "transparent",
|
|
8896
9238
|
transition: "background 0.1s"
|
|
8897
9239
|
},
|
|
8898
9240
|
children: [
|
|
8899
|
-
/* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: "#
|
|
9241
|
+
/* @__PURE__ */ jsx10("span", { style: { width: 24, flexShrink: 0, textAlign: "center", fontWeight: 700, fontSize: 12, fontFamily: "monospace", color: "#6210CC" }, children: item.shortLabel }),
|
|
8900
9242
|
item.label
|
|
8901
9243
|
]
|
|
8902
9244
|
}
|
|
@@ -8973,7 +9315,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
8973
9315
|
gap: 2,
|
|
8974
9316
|
padding: "0 6px",
|
|
8975
9317
|
background: "#fff",
|
|
8976
|
-
borderRadius:
|
|
9318
|
+
borderRadius: 8,
|
|
8977
9319
|
boxShadow: POPUP_SHADOW2,
|
|
8978
9320
|
userSelect: "none",
|
|
8979
9321
|
animation: "ab-float-in 0.12s ease"
|
|
@@ -9021,7 +9363,7 @@ function SelectionToolbar({ view, state, selectionRect }) {
|
|
|
9021
9363
|
e.preventDefault();
|
|
9022
9364
|
applyLink();
|
|
9023
9365
|
},
|
|
9024
|
-
style: { color: "#
|
|
9366
|
+
style: { color: "#6210CC", width: 24, fontSize: 14 },
|
|
9025
9367
|
children: "\u21B5"
|
|
9026
9368
|
}
|
|
9027
9369
|
),
|
|
@@ -9270,8 +9612,8 @@ function LinkEditDialog({ view, link: link2, onClose }) {
|
|
|
9270
9612
|
top = Math.min(anchorBottom + 12, window.innerHeight - estimatedDialogH - VPORT_MARGIN2);
|
|
9271
9613
|
}
|
|
9272
9614
|
const finalHref = normalizeLinkHref(hrefValue);
|
|
9273
|
-
const finalText = textValue.trim() ? textValue :
|
|
9274
|
-
const canSave = Boolean(finalHref) && (finalHref !== link2.href || finalText !== link2.text);
|
|
9615
|
+
const finalText = textValue.trim() ? textValue : "";
|
|
9616
|
+
const canSave = !textValue.trim() || Boolean(finalHref) && (finalHref !== link2.href || finalText !== link2.text);
|
|
9275
9617
|
const currentLink = () => {
|
|
9276
9618
|
const activeLink = getLinkAtCursor(view.state);
|
|
9277
9619
|
if (activeLink && activeLink.from === link2.from && activeLink.to === link2.to) {
|
|
@@ -9282,7 +9624,14 @@ function LinkEditDialog({ view, link: link2, onClose }) {
|
|
|
9282
9624
|
const saveLink = () => {
|
|
9283
9625
|
const activeLink = currentLink();
|
|
9284
9626
|
const nextHref = normalizeLinkHref(hrefValue);
|
|
9285
|
-
|
|
9627
|
+
if (!textValue.trim()) {
|
|
9628
|
+
const tr2 = view.state.tr.delete(activeLink.from, activeLink.to);
|
|
9629
|
+
view.dispatch(tr2);
|
|
9630
|
+
onClose();
|
|
9631
|
+
view.focus();
|
|
9632
|
+
return;
|
|
9633
|
+
}
|
|
9634
|
+
const nextText = textValue;
|
|
9286
9635
|
if (!nextHref) return;
|
|
9287
9636
|
if (nextHref === activeLink.href && nextText === activeLink.text) return;
|
|
9288
9637
|
const cursorOffset = Math.max(0, view.state.selection.from - activeLink.from);
|
|
@@ -9342,8 +9691,8 @@ function LinkEditDialog({ view, link: link2, onClose }) {
|
|
|
9342
9691
|
gap: 16,
|
|
9343
9692
|
padding: 16,
|
|
9344
9693
|
background: "#FFFFFF",
|
|
9345
|
-
borderRadius:
|
|
9346
|
-
boxShadow: "
|
|
9694
|
+
borderRadius: 8,
|
|
9695
|
+
boxShadow: "0 0 0 1px #CCCCCC, 0 4px 16px rgba(0, 0, 0, 0.12)",
|
|
9347
9696
|
boxSizing: "border-box",
|
|
9348
9697
|
animation: "ab-float-in 0.12s ease"
|
|
9349
9698
|
},
|
|
@@ -9511,6 +9860,189 @@ function LinkEditDialog({ view, link: link2, onClose }) {
|
|
|
9511
9860
|
document.body
|
|
9512
9861
|
);
|
|
9513
9862
|
}
|
|
9863
|
+
var INSERT_LINK_EVENT = "ab-insert-link";
|
|
9864
|
+
function LinkInsertDialog({ view, cursorPos, onClose }) {
|
|
9865
|
+
const [textValue, setTextValue] = useState7("");
|
|
9866
|
+
const [hrefValue, setHrefValue] = useState7("");
|
|
9867
|
+
const textInputRef = useRef4(null);
|
|
9868
|
+
useEffect4(() => {
|
|
9869
|
+
setTimeout(() => textInputRef.current?.focus(), 0);
|
|
9870
|
+
}, []);
|
|
9871
|
+
useEffect4(() => {
|
|
9872
|
+
const onDown = (e) => {
|
|
9873
|
+
if (!e.target.closest(`[${FLOAT_ATTR}]`)) {
|
|
9874
|
+
onClose();
|
|
9875
|
+
}
|
|
9876
|
+
};
|
|
9877
|
+
document.addEventListener("mousedown", onDown, true);
|
|
9878
|
+
return () => document.removeEventListener("mousedown", onDown, true);
|
|
9879
|
+
}, [onClose]);
|
|
9880
|
+
let coords;
|
|
9881
|
+
try {
|
|
9882
|
+
coords = view.coordsAtPos(cursorPos);
|
|
9883
|
+
} catch {
|
|
9884
|
+
onClose();
|
|
9885
|
+
return null;
|
|
9886
|
+
}
|
|
9887
|
+
const dialogW = 280;
|
|
9888
|
+
const left = Math.max(
|
|
9889
|
+
VPORT_MARGIN2,
|
|
9890
|
+
Math.min(coords.left - dialogW / 2, window.innerWidth - dialogW - VPORT_MARGIN2)
|
|
9891
|
+
);
|
|
9892
|
+
const top = Math.min(coords.bottom + 8, window.innerHeight - 220 - VPORT_MARGIN2);
|
|
9893
|
+
const finalHref = normalizeLinkHref(hrefValue);
|
|
9894
|
+
const canSave = Boolean(finalHref);
|
|
9895
|
+
const saveLink = () => {
|
|
9896
|
+
if (!finalHref) return;
|
|
9897
|
+
const displayText = textValue.trim() || finalHref;
|
|
9898
|
+
const tr = view.state.tr;
|
|
9899
|
+
const linkMarkType = view.state.schema.marks.link;
|
|
9900
|
+
if (!linkMarkType) return;
|
|
9901
|
+
tr.insertText(displayText, cursorPos);
|
|
9902
|
+
tr.addMark(cursorPos, cursorPos + displayText.length, linkMarkType.create({ href: finalHref }));
|
|
9903
|
+
view.dispatch(tr);
|
|
9904
|
+
onClose();
|
|
9905
|
+
view.focus();
|
|
9906
|
+
};
|
|
9907
|
+
const handleKeyDown = (e) => {
|
|
9908
|
+
if (e.key === "Escape") {
|
|
9909
|
+
e.preventDefault();
|
|
9910
|
+
onClose();
|
|
9911
|
+
view.focus();
|
|
9912
|
+
}
|
|
9913
|
+
if (e.key === "Enter") {
|
|
9914
|
+
e.preventDefault();
|
|
9915
|
+
saveLink();
|
|
9916
|
+
}
|
|
9917
|
+
};
|
|
9918
|
+
return createPortal2(
|
|
9919
|
+
/* @__PURE__ */ jsxs9(
|
|
9920
|
+
"div",
|
|
9921
|
+
{
|
|
9922
|
+
...{ [FLOAT_ATTR]: "" },
|
|
9923
|
+
style: {
|
|
9924
|
+
position: "fixed",
|
|
9925
|
+
left,
|
|
9926
|
+
top,
|
|
9927
|
+
zIndex: 1001,
|
|
9928
|
+
width: dialogW,
|
|
9929
|
+
display: "flex",
|
|
9930
|
+
flexDirection: "column",
|
|
9931
|
+
gap: 16,
|
|
9932
|
+
padding: 16,
|
|
9933
|
+
background: "#FFFFFF",
|
|
9934
|
+
borderRadius: 8,
|
|
9935
|
+
boxShadow: POPUP_SHADOW2,
|
|
9936
|
+
boxSizing: "border-box",
|
|
9937
|
+
animation: "ab-float-in 0.12s ease"
|
|
9938
|
+
},
|
|
9939
|
+
children: [
|
|
9940
|
+
/* @__PURE__ */ jsxs9("div", { ...{ [FLOAT_ATTR]: "" }, style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
9941
|
+
/* @__PURE__ */ jsxs9("div", { ...{ [FLOAT_ATTR]: "" }, style: { fontSize: 12, lineHeight: "16px", fontWeight: 600, color: "#0D0D0D" }, children: [
|
|
9942
|
+
"Text ",
|
|
9943
|
+
/* @__PURE__ */ jsx10("span", { style: { color: "#858585" }, children: "(optional)" })
|
|
9944
|
+
] }),
|
|
9945
|
+
/* @__PURE__ */ jsx10(
|
|
9946
|
+
"input",
|
|
9947
|
+
{
|
|
9948
|
+
ref: textInputRef,
|
|
9949
|
+
...{ [FLOAT_ATTR]: "" },
|
|
9950
|
+
value: textValue,
|
|
9951
|
+
placeholder: "",
|
|
9952
|
+
onChange: (e) => setTextValue(e.target.value),
|
|
9953
|
+
onKeyDown: handleKeyDown,
|
|
9954
|
+
style: {
|
|
9955
|
+
height: 32,
|
|
9956
|
+
border: "1px solid #CCCCCC",
|
|
9957
|
+
borderRadius: 4,
|
|
9958
|
+
padding: "0 16px",
|
|
9959
|
+
fontSize: 14,
|
|
9960
|
+
color: "#0D0D0D",
|
|
9961
|
+
outline: "none",
|
|
9962
|
+
boxSizing: "border-box"
|
|
9963
|
+
}
|
|
9964
|
+
}
|
|
9965
|
+
)
|
|
9966
|
+
] }),
|
|
9967
|
+
/* @__PURE__ */ jsxs9("div", { ...{ [FLOAT_ATTR]: "" }, style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
|
|
9968
|
+
/* @__PURE__ */ jsx10("div", { ...{ [FLOAT_ATTR]: "" }, style: { fontSize: 12, lineHeight: "16px", fontWeight: 600, color: "#0D0D0D" }, children: "Link" }),
|
|
9969
|
+
/* @__PURE__ */ jsx10(
|
|
9970
|
+
"input",
|
|
9971
|
+
{
|
|
9972
|
+
...{ [FLOAT_ATTR]: "" },
|
|
9973
|
+
value: hrefValue,
|
|
9974
|
+
onChange: (e) => setHrefValue(e.target.value),
|
|
9975
|
+
onKeyDown: handleKeyDown,
|
|
9976
|
+
style: {
|
|
9977
|
+
height: 32,
|
|
9978
|
+
border: "1px solid #CCCCCC",
|
|
9979
|
+
borderRadius: 4,
|
|
9980
|
+
padding: "0 16px",
|
|
9981
|
+
fontSize: 14,
|
|
9982
|
+
color: "#0D0D0D",
|
|
9983
|
+
outline: "none",
|
|
9984
|
+
boxSizing: "border-box"
|
|
9985
|
+
}
|
|
9986
|
+
}
|
|
9987
|
+
)
|
|
9988
|
+
] }),
|
|
9989
|
+
/* @__PURE__ */ jsxs9("div", { ...{ [FLOAT_ATTR]: "" }, style: { display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 8 }, children: [
|
|
9990
|
+
/* @__PURE__ */ jsx10(
|
|
9991
|
+
"button",
|
|
9992
|
+
{
|
|
9993
|
+
type: "button",
|
|
9994
|
+
...{ [FLOAT_ATTR]: "" },
|
|
9995
|
+
onMouseDown: (e) => {
|
|
9996
|
+
e.preventDefault();
|
|
9997
|
+
onClose();
|
|
9998
|
+
view.focus();
|
|
9999
|
+
},
|
|
10000
|
+
style: {
|
|
10001
|
+
...BTN_RESET2,
|
|
10002
|
+
height: 32,
|
|
10003
|
+
padding: "0 13px",
|
|
10004
|
+
border: "1px solid #CCCCCC",
|
|
10005
|
+
borderRadius: 4,
|
|
10006
|
+
fontSize: 14,
|
|
10007
|
+
lineHeight: "20px",
|
|
10008
|
+
fontWeight: 600,
|
|
10009
|
+
color: "#0D0D0D"
|
|
10010
|
+
},
|
|
10011
|
+
children: "Cancel"
|
|
10012
|
+
}
|
|
10013
|
+
),
|
|
10014
|
+
/* @__PURE__ */ jsx10(
|
|
10015
|
+
"button",
|
|
10016
|
+
{
|
|
10017
|
+
type: "button",
|
|
10018
|
+
disabled: !canSave,
|
|
10019
|
+
...{ [FLOAT_ATTR]: "" },
|
|
10020
|
+
onMouseDown: (e) => {
|
|
10021
|
+
e.preventDefault();
|
|
10022
|
+
if (canSave) saveLink();
|
|
10023
|
+
},
|
|
10024
|
+
style: {
|
|
10025
|
+
...BTN_RESET2,
|
|
10026
|
+
height: 32,
|
|
10027
|
+
padding: "0 13px",
|
|
10028
|
+
borderRadius: 4,
|
|
10029
|
+
fontSize: 14,
|
|
10030
|
+
lineHeight: "20px",
|
|
10031
|
+
fontWeight: 600,
|
|
10032
|
+
background: canSave ? "#6210CC" : "#ECECEC",
|
|
10033
|
+
color: canSave ? "#FFFFFF" : "#A6A6A6",
|
|
10034
|
+
cursor: canSave ? "pointer" : "default"
|
|
10035
|
+
},
|
|
10036
|
+
children: "Save"
|
|
10037
|
+
}
|
|
10038
|
+
)
|
|
10039
|
+
] })
|
|
10040
|
+
]
|
|
10041
|
+
}
|
|
10042
|
+
),
|
|
10043
|
+
document.body
|
|
10044
|
+
);
|
|
10045
|
+
}
|
|
9514
10046
|
var BLOCK_ITEMS = [
|
|
9515
10047
|
{
|
|
9516
10048
|
shortLabel: "\xB6",
|
|
@@ -9633,12 +10165,12 @@ function EmptyParaHandle({ view, cursorPos }) {
|
|
|
9633
10165
|
height: btnSize,
|
|
9634
10166
|
border: "1px solid rgba(0,0,0,0.1)",
|
|
9635
10167
|
borderRadius: 5,
|
|
9636
|
-
background: menuOpen ? "rgba(
|
|
10168
|
+
background: menuOpen ? "rgba(98,16,204,0.08)" : "#fff",
|
|
9637
10169
|
boxShadow: "0 1px 3px rgba(0,0,0,0.06)",
|
|
9638
10170
|
display: "flex",
|
|
9639
10171
|
alignItems: "center",
|
|
9640
10172
|
justifyContent: "center",
|
|
9641
|
-
color: menuOpen ? "#
|
|
10173
|
+
color: menuOpen ? "#6210CC" : "#9ca3af",
|
|
9642
10174
|
fontSize: 16,
|
|
9643
10175
|
animation: "ab-float-in 0.15s ease",
|
|
9644
10176
|
transition: "color 0.1s, background 0.1s, border-color 0.1s"
|
|
@@ -9656,9 +10188,9 @@ function EmptyParaHandle({ view, cursorPos }) {
|
|
|
9656
10188
|
left: menuLeft,
|
|
9657
10189
|
top: menuTop,
|
|
9658
10190
|
background: "#fff",
|
|
9659
|
-
borderRadius:
|
|
10191
|
+
borderRadius: 8,
|
|
9660
10192
|
boxShadow: POPUP_SHADOW2,
|
|
9661
|
-
padding:
|
|
10193
|
+
padding: 4,
|
|
9662
10194
|
minWidth: 168,
|
|
9663
10195
|
animation: "ab-float-in 0.12s ease"
|
|
9664
10196
|
},
|
|
@@ -9702,7 +10234,7 @@ function BlockMenuItem({
|
|
|
9702
10234
|
borderRadius: 6,
|
|
9703
10235
|
textAlign: "left",
|
|
9704
10236
|
fontSize: 13,
|
|
9705
|
-
color: "#
|
|
10237
|
+
color: "#0D0D0D",
|
|
9706
10238
|
background: hover ? "rgba(0,0,0,0.04)" : "transparent",
|
|
9707
10239
|
transition: "background 0.1s"
|
|
9708
10240
|
},
|
|
@@ -9717,7 +10249,7 @@ function BlockMenuItem({
|
|
|
9717
10249
|
fontWeight: 700,
|
|
9718
10250
|
fontSize: 12,
|
|
9719
10251
|
fontFamily: "monospace",
|
|
9720
|
-
color: "#
|
|
10252
|
+
color: "#6210CC"
|
|
9721
10253
|
},
|
|
9722
10254
|
children: item.shortLabel
|
|
9723
10255
|
}
|
|
@@ -9730,8 +10262,19 @@ function BlockMenuItem({
|
|
|
9730
10262
|
function FloatingMenu({ view, editorState }) {
|
|
9731
10263
|
const [showEmptyHandle, setShowEmptyHandle] = useState7(false);
|
|
9732
10264
|
const [editingLink, setEditingLink] = useState7(null);
|
|
10265
|
+
const [insertLinkPos, setInsertLinkPos] = useState7(null);
|
|
9733
10266
|
const dwellTimerRef = useRef4(null);
|
|
9734
10267
|
const lastEmptyPosRef = useRef4(null);
|
|
10268
|
+
useEffect4(() => {
|
|
10269
|
+
const dom = view?.dom;
|
|
10270
|
+
if (!dom) return;
|
|
10271
|
+
const handler = () => {
|
|
10272
|
+
const pos = view.state.selection.from;
|
|
10273
|
+
setInsertLinkPos(pos);
|
|
10274
|
+
};
|
|
10275
|
+
dom.addEventListener(INSERT_LINK_EVENT, handler);
|
|
10276
|
+
return () => dom.removeEventListener(INSERT_LINK_EVENT, handler);
|
|
10277
|
+
}, [view]);
|
|
9735
10278
|
const [, setScrollTick] = useState7(0);
|
|
9736
10279
|
useEffect4(() => {
|
|
9737
10280
|
const editorDom = view?.dom;
|
|
@@ -9804,7 +10347,15 @@ function FloatingMenu({ view, editorState }) {
|
|
|
9804
10347
|
onClose: () => setEditingLink(null)
|
|
9805
10348
|
}
|
|
9806
10349
|
),
|
|
9807
|
-
|
|
10350
|
+
insertLinkPos !== null && /* @__PURE__ */ jsx10(
|
|
10351
|
+
LinkInsertDialog,
|
|
10352
|
+
{
|
|
10353
|
+
view,
|
|
10354
|
+
cursorPos: insertLinkPos,
|
|
10355
|
+
onClose: () => setInsertLinkPos(null)
|
|
10356
|
+
}
|
|
10357
|
+
),
|
|
10358
|
+
!hasSelection && !linkAtCursor && !insertLinkPos && showEmptyHandle && emptyPos !== null && /* @__PURE__ */ jsx10(EmptyParaHandle, { view, cursorPos: emptyPos })
|
|
9808
10359
|
] }),
|
|
9809
10360
|
document.body
|
|
9810
10361
|
);
|
|
@@ -9971,11 +10522,28 @@ function createInlineSuggestPlugin(provider, endpoint, options) {
|
|
|
9971
10522
|
]
|
|
9972
10523
|
};
|
|
9973
10524
|
}
|
|
10525
|
+
|
|
10526
|
+
// src/ui/bridge/jinjaValidation.ts
|
|
10527
|
+
function hasInvalidJinjaConditions(state) {
|
|
10528
|
+
let found = false;
|
|
10529
|
+
state.doc.descendants((node) => {
|
|
10530
|
+
if (found) return false;
|
|
10531
|
+
if (node.type.name === "jinjaIfBranch") {
|
|
10532
|
+
const condition = String(node.attrs.condition ?? "");
|
|
10533
|
+
if (condition && !validateCondition(condition).valid) {
|
|
10534
|
+
found = true;
|
|
10535
|
+
}
|
|
10536
|
+
return false;
|
|
10537
|
+
}
|
|
10538
|
+
});
|
|
10539
|
+
return found;
|
|
10540
|
+
}
|
|
9974
10541
|
export {
|
|
9975
10542
|
ActionbookRenderer,
|
|
9976
10543
|
DocumentTreeView,
|
|
9977
10544
|
EditorShell,
|
|
9978
10545
|
FloatingMenu,
|
|
10546
|
+
INSERT_LINK_EVENT,
|
|
9979
10547
|
JUMP_POINT_ADJACENT_SPEC,
|
|
9980
10548
|
JinjaTreeView,
|
|
9981
10549
|
SlashCommandMenu,
|
|
@@ -10004,6 +10572,7 @@ export {
|
|
|
10004
10572
|
createTodoNodeViewPlugin,
|
|
10005
10573
|
hasBrokenAnchorRefs,
|
|
10006
10574
|
hasDuplicateJumpPoints,
|
|
10575
|
+
hasInvalidJinjaConditions,
|
|
10007
10576
|
inlineSuggestKey,
|
|
10008
10577
|
slashCommandKey,
|
|
10009
10578
|
toProseMirrorJSON,
|