@threadlabs/looma 0.26.21 → 0.26.23
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/components/ui-combobox/ui-combobox.html +4 -0
- package/components/ui-combobox/ui-combobox.js +1 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/vanilla/UiCombobox.d.ts +1 -0
- package/vanilla/UiCombobox.js +69 -71
- package/vue/UiCombobox.d.ts +9 -0
- package/vue/UiCombobox.vue +25 -0
- package/vue/chunks/UiCombobox.js +23 -1
- package/vue/components.css +62 -53
- package/vue/editor/index.js +72 -16
package/vue/components.css
CHANGED
|
@@ -2211,7 +2211,7 @@ input[data-v-a7d28848]:focus-visible {
|
|
|
2211
2211
|
syntax: "*";
|
|
2212
2212
|
inherits: false;
|
|
2213
2213
|
}
|
|
2214
|
-
[data-component~="ui-combobox"][data-v-
|
|
2214
|
+
[data-component~="ui-combobox"][data-v-33359776] {
|
|
2215
2215
|
/* Hooks do not inherit, so the parts below read them from the root. */
|
|
2216
2216
|
--_ui-combobox-label-text: var(--ui-combobox-label-text);
|
|
2217
2217
|
--_ui-combobox-label-font-size: var(--ui-combobox-label-font-size);
|
|
@@ -2236,20 +2236,20 @@ input[data-v-a7d28848]:focus-visible {
|
|
|
2236
2236
|
color: var(--ui-text-primary);
|
|
2237
2237
|
font: inherit;
|
|
2238
2238
|
}
|
|
2239
|
-
label[data-v-
|
|
2239
|
+
label[data-v-33359776] {
|
|
2240
2240
|
color: var(--_ui-combobox-label-text, var(--ui-text-primary));
|
|
2241
2241
|
font-size: var(--_ui-combobox-label-font-size, var(--ui-font-size-sm));
|
|
2242
2242
|
font-weight: 500;
|
|
2243
2243
|
}
|
|
2244
2244
|
/* The field and anything that annotates it sit on one row; the help button is beside the box,
|
|
2245
2245
|
not inside it, because a control's box holds its value. */
|
|
2246
|
-
.control[data-v-
|
|
2246
|
+
.control[data-v-33359776] {
|
|
2247
2247
|
display: flex;
|
|
2248
2248
|
align-items: center;
|
|
2249
2249
|
gap: var(--ui-space-2);
|
|
2250
2250
|
min-inline-size: 0;
|
|
2251
2251
|
}
|
|
2252
|
-
.field[data-v-
|
|
2252
|
+
.field[data-v-33359776] {
|
|
2253
2253
|
flex: 1 1 auto;
|
|
2254
2254
|
display: flex;
|
|
2255
2255
|
min-inline-size: 0;
|
|
@@ -2261,19 +2261,19 @@ label[data-v-2be0ffde] {
|
|
|
2261
2261
|
border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
2262
2262
|
box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
|
|
2263
2263
|
}
|
|
2264
|
-
.field[data-v-
|
|
2264
|
+
.field[data-v-33359776]:focus-within {
|
|
2265
2265
|
border-color: var(--ui-control-focus, var(--ui-accent-solid));
|
|
2266
2266
|
box-shadow:
|
|
2267
2267
|
var(--ui-control-inset),
|
|
2268
2268
|
var(--ui-control-focus-halo-shadow);
|
|
2269
2269
|
}
|
|
2270
|
-
.entry[data-v-
|
|
2270
|
+
.entry[data-v-33359776] {
|
|
2271
2271
|
display: flex;
|
|
2272
2272
|
flex: 1 1 auto;
|
|
2273
2273
|
min-inline-size: 0;
|
|
2274
2274
|
}
|
|
2275
2275
|
/* A ghost icon button: the affordance is the mark, not a box around it. */
|
|
2276
|
-
.help[data-v-
|
|
2276
|
+
.help[data-v-33359776] {
|
|
2277
2277
|
flex: none;
|
|
2278
2278
|
display: inline-flex;
|
|
2279
2279
|
align-items: center;
|
|
@@ -2290,28 +2290,28 @@ label[data-v-2be0ffde] {
|
|
|
2290
2290
|
background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
2291
2291
|
color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
2292
2292
|
}
|
|
2293
|
-
.help[data-v-
|
|
2294
|
-
.help[aria-expanded="true"][data-v-
|
|
2293
|
+
.help[data-v-33359776]:hover:enabled,
|
|
2294
|
+
.help[aria-expanded="true"][data-v-33359776] {
|
|
2295
2295
|
background: color-mix(in srgb, currentColor 8%, transparent);
|
|
2296
2296
|
color: var(--ui-text-primary);
|
|
2297
2297
|
}
|
|
2298
|
-
.help[data-v-
|
|
2298
|
+
.help[data-v-33359776]:focus-visible {
|
|
2299
2299
|
outline: none;
|
|
2300
2300
|
box-shadow: var(--ui-focus-halo);
|
|
2301
2301
|
}
|
|
2302
|
-
.help[data-v-
|
|
2302
|
+
.help[data-v-33359776]:disabled {
|
|
2303
2303
|
color: var(--ui-disabled-text);
|
|
2304
2304
|
cursor: not-allowed;
|
|
2305
2305
|
}
|
|
2306
|
-
.help-icon[data-v-
|
|
2306
|
+
.help-icon[data-v-33359776] {
|
|
2307
2307
|
inline-size: var(--ui-icon-size-sm);
|
|
2308
2308
|
block-size: var(--ui-icon-size-sm);
|
|
2309
2309
|
}
|
|
2310
|
-
input[data-v-
|
|
2310
|
+
input[data-v-33359776]::selection {
|
|
2311
2311
|
background: color-mix(in srgb, var(--ui-accent-solid) 20%, transparent);
|
|
2312
2312
|
color: inherit;
|
|
2313
2313
|
}
|
|
2314
|
-
input[data-v-
|
|
2314
|
+
input[data-v-33359776] {
|
|
2315
2315
|
appearance: none;
|
|
2316
2316
|
width: 100%;
|
|
2317
2317
|
min-inline-size: 0;
|
|
@@ -2327,20 +2327,20 @@ input[data-v-2be0ffde] {
|
|
|
2327
2327
|
margin: 0;
|
|
2328
2328
|
outline: none;
|
|
2329
2329
|
}
|
|
2330
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"][data-v-
|
|
2330
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"][data-v-33359776] {
|
|
2331
2331
|
--_row: var(--ui-control-size-sm);
|
|
2332
2332
|
}
|
|
2333
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input[data-v-
|
|
2333
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input[data-v-33359776] {
|
|
2334
2334
|
min-block-size: calc(var(--_row) - 2px);
|
|
2335
2335
|
padding: var(--ui-space-1) var(--ui-space-2);
|
|
2336
2336
|
font-size: var(--ui-font-size-sm);
|
|
2337
2337
|
}
|
|
2338
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="size=lg"] input[data-v-
|
|
2338
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="size=lg"] input[data-v-33359776] {
|
|
2339
2339
|
min-block-size: calc(var(--ui-control-size-lg) - 2px);
|
|
2340
2340
|
padding: var(--ui-space-3) var(--ui-space-4);
|
|
2341
2341
|
font-size: var(--ui-font-size-md);
|
|
2342
2342
|
}
|
|
2343
|
-
button[data-v-
|
|
2343
|
+
button[data-v-33359776] {
|
|
2344
2344
|
appearance: none;
|
|
2345
2345
|
display: inline-grid;
|
|
2346
2346
|
place-items: center;
|
|
@@ -2355,36 +2355,36 @@ button[data-v-2be0ffde] {
|
|
|
2355
2355
|
padding: 0 var(--ui-space-1);
|
|
2356
2356
|
cursor: pointer;
|
|
2357
2357
|
}
|
|
2358
|
-
.affordance-icon[data-v-
|
|
2358
|
+
.affordance-icon[data-v-33359776] {
|
|
2359
2359
|
display: block;
|
|
2360
2360
|
inline-size: var(--ui-icon-size-sm);
|
|
2361
2361
|
block-size: var(--ui-icon-size-sm);
|
|
2362
2362
|
}
|
|
2363
|
-
button[data-v-
|
|
2363
|
+
button[data-v-33359776]:hover:enabled {
|
|
2364
2364
|
background: var(--ui-surface-muted);
|
|
2365
2365
|
color: var(--ui-text-primary);
|
|
2366
2366
|
}
|
|
2367
|
-
button[data-v-
|
|
2367
|
+
button[data-v-33359776]:focus-visible {
|
|
2368
2368
|
outline: none;
|
|
2369
2369
|
background: var(--ui-surface-muted);
|
|
2370
2370
|
box-shadow: inset 0 0 0 var(--ui-focus-width)
|
|
2371
2371
|
color-mix(in srgb, var(--ui-focus-ring) 45%, transparent);
|
|
2372
2372
|
}
|
|
2373
|
-
input[data-v-
|
|
2373
|
+
input[data-v-33359776]:disabled, button[data-v-33359776]:disabled {
|
|
2374
2374
|
color: var(--ui-disabled-text);
|
|
2375
2375
|
cursor: not-allowed;
|
|
2376
2376
|
}
|
|
2377
|
-
.field[data-v-
|
|
2377
|
+
.field[data-v-33359776]:has(input:disabled) {
|
|
2378
2378
|
background: var(--ui-control-surface-disabled, var(--ui-surface-muted));
|
|
2379
2379
|
}
|
|
2380
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="validationStatus=error"] .field[data-v-
|
|
2381
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="invalid"] .field[data-v-
|
|
2380
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="validationStatus=error"] .field[data-v-33359776],
|
|
2381
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="invalid"] .field[data-v-33359776] {
|
|
2382
2382
|
border-color: var(
|
|
2383
2383
|
--_ui-combobox-invalid-border,
|
|
2384
2384
|
var(--ui-field-danger, var(--ui-danger-solid, var(--ui-accent-active)))
|
|
2385
2385
|
);
|
|
2386
2386
|
}
|
|
2387
|
-
.popup[data-v-
|
|
2387
|
+
.popup[data-v-33359776] {
|
|
2388
2388
|
box-sizing: border-box;
|
|
2389
2389
|
min-inline-size: 12rem;
|
|
2390
2390
|
max-inline-size: calc(100vw - 1rem);
|
|
@@ -2405,46 +2405,46 @@ input[data-v-2be0ffde]:disabled, button[data-v-2be0ffde]:disabled {
|
|
|
2405
2405
|
var(--ui-overlay-shadow, var(--ui-elevation-overlay, var(--ui-shadow-lg)))
|
|
2406
2406
|
);
|
|
2407
2407
|
}
|
|
2408
|
-
[hidden][data-v-
|
|
2408
|
+
[hidden][data-v-33359776] {
|
|
2409
2409
|
display: none;
|
|
2410
2410
|
}
|
|
2411
|
-
.option[aria-disabled="true"] .primary[data-v-
|
|
2412
|
-
.option[aria-disabled="true"] .secondary[data-v-
|
|
2411
|
+
.option[aria-disabled="true"] .primary[data-v-33359776],
|
|
2412
|
+
.option[aria-disabled="true"] .secondary[data-v-33359776] {
|
|
2413
2413
|
color: var(--ui-disabled-text);
|
|
2414
2414
|
}
|
|
2415
|
-
.primary[data-v-
|
|
2415
|
+
.primary[data-v-33359776] {
|
|
2416
2416
|
display: block;
|
|
2417
2417
|
color: var(--_ui-combobox-option-text, inherit);
|
|
2418
2418
|
font-weight: 500;
|
|
2419
2419
|
}
|
|
2420
2420
|
/* A row with a tag or a description: the label and its tag on one line, the description under them. */
|
|
2421
|
-
.detail[data-v-
|
|
2421
|
+
.detail[data-v-33359776] {
|
|
2422
2422
|
display: grid;
|
|
2423
2423
|
gap: var(--ui-space-0-5);
|
|
2424
2424
|
min-inline-size: 0;
|
|
2425
2425
|
}
|
|
2426
|
-
.line[data-v-
|
|
2426
|
+
.line[data-v-33359776] {
|
|
2427
2427
|
display: flex;
|
|
2428
2428
|
flex-wrap: wrap;
|
|
2429
2429
|
align-items: center;
|
|
2430
2430
|
gap: var(--ui-space-2);
|
|
2431
2431
|
}
|
|
2432
|
-
.description[data-v-
|
|
2432
|
+
.description[data-v-33359776] {
|
|
2433
2433
|
color: var(--ui-text-muted);
|
|
2434
2434
|
font-size: var(--ui-font-size-sm);
|
|
2435
2435
|
line-height: var(--ui-line-height-md);
|
|
2436
2436
|
}
|
|
2437
|
-
.message[data-v-
|
|
2437
|
+
.message[data-v-33359776], .group[data-v-33359776] {
|
|
2438
2438
|
color: var(--_ui-combobox-message-text, var(--ui-text-secondary));
|
|
2439
2439
|
font-weight: 400;
|
|
2440
2440
|
font-size: var(--ui-font-size-sm);
|
|
2441
2441
|
line-height: var(--ui-line-height-md);
|
|
2442
2442
|
overflow-wrap: anywhere;
|
|
2443
2443
|
}
|
|
2444
|
-
.group[data-v-
|
|
2444
|
+
.group[data-v-33359776], .popup .message[data-v-33359776] {
|
|
2445
2445
|
padding: var(--ui-space-2) var(--ui-space-3);
|
|
2446
2446
|
}
|
|
2447
|
-
.sr-only[data-v-
|
|
2447
|
+
.sr-only[data-v-33359776] {
|
|
2448
2448
|
position: absolute;
|
|
2449
2449
|
inline-size: 1px;
|
|
2450
2450
|
block-size: 1px;
|
|
@@ -2453,45 +2453,45 @@ input[data-v-2be0ffde]:disabled, button[data-v-2be0ffde]:disabled {
|
|
|
2453
2453
|
white-space: nowrap;
|
|
2454
2454
|
}
|
|
2455
2455
|
@media (pointer: coarse) {
|
|
2456
|
-
button[data-v-
|
|
2456
|
+
button[data-v-33359776] {
|
|
2457
2457
|
min-inline-size: 2.75rem;
|
|
2458
2458
|
min-block-size: 2.75rem;
|
|
2459
2459
|
}
|
|
2460
2460
|
/* Under touch a small field is still a touch-sized target, as a small button is, and keeps
|
|
2461
2461
|
body-size text: below 16px, iOS zooms the page into the focused field. */
|
|
2462
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"][data-v-
|
|
2462
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"][data-v-33359776] {
|
|
2463
2463
|
--_row: var(--ui-control-min-block-size);
|
|
2464
2464
|
}
|
|
2465
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input[data-v-
|
|
2465
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"] input[data-v-33359776] {
|
|
2466
2466
|
font-size: inherit;
|
|
2467
2467
|
}
|
|
2468
2468
|
}
|
|
2469
2469
|
@media (forced-colors: active) {
|
|
2470
|
-
.field[data-v-
|
|
2470
|
+
.field[data-v-33359776], .popup[data-v-33359776] {
|
|
2471
2471
|
border-color: CanvasText;
|
|
2472
2472
|
}
|
|
2473
|
-
.option.active[data-v-
|
|
2473
|
+
.option.active[data-v-33359776] {
|
|
2474
2474
|
outline-color: Highlight;
|
|
2475
2475
|
}
|
|
2476
2476
|
}
|
|
2477
2477
|
|
|
2478
2478
|
/* Multiple mode keeps one control height. Chips and the input scroll within the entry,
|
|
2479
2479
|
while the clear and disclosure controls remain fixed at the end of the field. */
|
|
2480
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .field[data-v-
|
|
2480
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .field[data-v-33359776] {
|
|
2481
2481
|
align-items: center;
|
|
2482
2482
|
min-block-size: var(--_ui-combobox-item-min-block-size, 2.5rem);
|
|
2483
2483
|
padding: var(--ui-space-1);
|
|
2484
2484
|
}
|
|
2485
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .entry[data-v-
|
|
2485
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .entry[data-v-33359776] {
|
|
2486
2486
|
align-items: center;
|
|
2487
2487
|
gap: var(--ui-space-1);
|
|
2488
2488
|
overflow-x: auto;
|
|
2489
2489
|
scrollbar-width: none;
|
|
2490
2490
|
}
|
|
2491
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .entry[data-v-
|
|
2491
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] .entry[data-v-33359776]::-webkit-scrollbar {
|
|
2492
2492
|
display: none;
|
|
2493
2493
|
}
|
|
2494
|
-
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] input[data-v-
|
|
2494
|
+
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"] input[data-v-33359776] {
|
|
2495
2495
|
flex: 1 0 var(--_ui-combobox-item-input-min-inline-size, 5rem);
|
|
2496
2496
|
width: auto;
|
|
2497
2497
|
min-block-size: 1.75rem;
|
|
@@ -2499,27 +2499,27 @@ button[data-v-2be0ffde] {
|
|
|
2499
2499
|
}
|
|
2500
2500
|
/* Size variants keep their control height as selections are added. */
|
|
2501
2501
|
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"][data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"]
|
|
2502
|
-
.field[data-v-
|
|
2502
|
+
.field[data-v-33359776] {
|
|
2503
2503
|
min-block-size: 0;
|
|
2504
2504
|
padding: var(--ui-space-0-5);
|
|
2505
2505
|
}
|
|
2506
2506
|
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"][data-component~="ui-combobox"][data-ui-combobox-state~="size=sm"]
|
|
2507
|
-
input[data-v-
|
|
2507
|
+
input[data-v-33359776] {
|
|
2508
2508
|
min-block-size: calc(var(--_row) - 2 * var(--ui-border-width) - 2 * var(--ui-space-0-5));
|
|
2509
2509
|
padding: 0 var(--ui-space-1);
|
|
2510
2510
|
}
|
|
2511
2511
|
/* A large multiple field starts at the large control height, as sm starts at the small one. */
|
|
2512
2512
|
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"][data-component~="ui-combobox"][data-ui-combobox-state~="size=lg"]
|
|
2513
|
-
.field[data-v-
|
|
2513
|
+
.field[data-v-33359776] {
|
|
2514
2514
|
min-block-size: 0;
|
|
2515
2515
|
}
|
|
2516
2516
|
[data-component~="ui-combobox"][data-ui-combobox-state~="multiple"][data-component~="ui-combobox"][data-ui-combobox-state~="size=lg"]
|
|
2517
|
-
input[data-v-
|
|
2517
|
+
input[data-v-33359776] {
|
|
2518
2518
|
min-block-size: calc(
|
|
2519
2519
|
var(--ui-control-size-lg) - 2 * var(--ui-border-width) - 2 * var(--ui-space-1)
|
|
2520
2520
|
);
|
|
2521
2521
|
}
|
|
2522
|
-
.item[data-v-
|
|
2522
|
+
.item[data-v-33359776] {
|
|
2523
2523
|
appearance: none;
|
|
2524
2524
|
display: inline-flex;
|
|
2525
2525
|
flex: none;
|
|
@@ -2534,16 +2534,16 @@ button[data-v-2be0ffde] {
|
|
|
2534
2534
|
font: inherit;
|
|
2535
2535
|
cursor: default;
|
|
2536
2536
|
}
|
|
2537
|
-
.item[data-v-
|
|
2537
|
+
.item[data-v-33359776]:focus-visible {
|
|
2538
2538
|
outline: var(--ui-focus-width) solid var(--ui-focus-ring);
|
|
2539
2539
|
outline-offset: var(--ui-border-width);
|
|
2540
2540
|
}
|
|
2541
|
-
.item[data-v-
|
|
2541
|
+
.item[data-v-33359776]:disabled {
|
|
2542
2542
|
color: var(--ui-disabled-text);
|
|
2543
2543
|
}
|
|
2544
2544
|
|
|
2545
2545
|
/* A component that sets its display still honours the hidden attribute on its root. */
|
|
2546
|
-
[data-component~="ui-combobox"][hidden][data-v-
|
|
2546
|
+
[data-component~="ui-combobox"][hidden][data-v-33359776] {
|
|
2547
2547
|
display: none;
|
|
2548
2548
|
}
|
|
2549
2549
|
|
|
@@ -10097,6 +10097,15 @@ html[data-ui-input-modality="touch"]
|
|
|
10097
10097
|
.looma-editor .ProseMirror li > :is(ul, ol) {
|
|
10098
10098
|
margin-block: var(--ui-space-1) 0;
|
|
10099
10099
|
}
|
|
10100
|
+
|
|
10101
|
+
/* A held navigation modifier makes links actionable without interrupting editing. */
|
|
10102
|
+
[data-component~="ui-editor-surface"] .ProseMirror[contenteditable="true"] a[href] {
|
|
10103
|
+
cursor: text;
|
|
10104
|
+
}
|
|
10105
|
+
|
|
10106
|
+
[data-component~="ui-editor-surface"] .ProseMirror[data-link-navigation] a[href] {
|
|
10107
|
+
cursor: pointer;
|
|
10108
|
+
}
|
|
10100
10109
|
/**
|
|
10101
10110
|
* Looma editor styles (tokens-based).
|
|
10102
10111
|
* Tables, context menu, insert-table grid, slash menu. Use with ProseMirror/Tiptap content.
|
package/vue/editor/index.js
CHANGED
|
@@ -1822,6 +1822,7 @@ var LoomaEditor = defineComponent({
|
|
|
1822
1822
|
let dismissedFormattingSelection = null;
|
|
1823
1823
|
let heldFormattingSelection = null;
|
|
1824
1824
|
let formattingPopup = null;
|
|
1825
|
+
let linkPopup = null;
|
|
1825
1826
|
let heldPressTimer;
|
|
1826
1827
|
let heldPress = null;
|
|
1827
1828
|
const floatingFormattingMode = () => props.toolbarMode !== "sticky" && !(props.toolbarMode === "popover" && props.toolbarOpen) && !mobile.value;
|
|
@@ -2032,7 +2033,30 @@ var LoomaEditor = defineComponent({
|
|
|
2032
2033
|
"aria-multiline": "true",
|
|
2033
2034
|
"aria-label": props.label
|
|
2034
2035
|
},
|
|
2035
|
-
handleKeyDown: (_view, event) => onFormattingKeyDown(event)
|
|
2036
|
+
handleKeyDown: (_view, event) => onFormattingKeyDown(event),
|
|
2037
|
+
handleDOMEvents: { click: (view, event) => {
|
|
2038
|
+
if (!(event.target instanceof Element) || event.button !== 0) return false;
|
|
2039
|
+
const link = event.target.closest("a[href]");
|
|
2040
|
+
if (!link || !view.dom.contains(link)) return false;
|
|
2041
|
+
const href = validLinkHref(link.getAttribute("href") ?? "");
|
|
2042
|
+
if (!href) return false;
|
|
2043
|
+
if (isApplePlatform() ? event.metaKey : event.ctrlKey) {
|
|
2044
|
+
event.preventDefault();
|
|
2045
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
2046
|
+
return true;
|
|
2047
|
+
}
|
|
2048
|
+
dismissedFormattingSelection = null;
|
|
2049
|
+
requestAnimationFrame(() => {
|
|
2050
|
+
if (view.isDestroyed) return;
|
|
2051
|
+
editorStateVersion.value += 1;
|
|
2052
|
+
const instance = editor.value;
|
|
2053
|
+
if (instance?.isFocused && instance.state.selection.empty && instance.isActive("link") && !linkOpen.value) {
|
|
2054
|
+
linkPopup?.setProps({ getReferenceClientRect: () => link.getBoundingClientRect() });
|
|
2055
|
+
linkPopup?.show();
|
|
2056
|
+
}
|
|
2057
|
+
});
|
|
2058
|
+
return false;
|
|
2059
|
+
} }
|
|
2036
2060
|
},
|
|
2037
2061
|
onCreate: ({ editor: instance }) => {
|
|
2038
2062
|
emit("ready", instance);
|
|
@@ -2360,31 +2384,38 @@ var LoomaEditor = defineComponent({
|
|
|
2360
2384
|
h(Separator),
|
|
2361
2385
|
h(Cluster, {
|
|
2362
2386
|
gap: "xs",
|
|
2363
|
-
justify: "between"
|
|
2364
|
-
|
|
2387
|
+
justify: "between",
|
|
2388
|
+
wrap: "nowrap"
|
|
2389
|
+
}, () => [linkSelection?.existing ? h(Button, {
|
|
2365
2390
|
type: "button",
|
|
2366
2391
|
variant: "ghost",
|
|
2367
2392
|
tone: "danger",
|
|
2368
2393
|
size: "sm",
|
|
2369
2394
|
onClick: removeLink
|
|
2370
|
-
}, () => "Remove link") : null,
|
|
2395
|
+
}, () => "Remove link") : null, validLinkHref(linkHref.value) ? h(Button, {
|
|
2371
2396
|
as: "a",
|
|
2372
|
-
variant: "
|
|
2397
|
+
variant: "outline",
|
|
2398
|
+
tone: "accent",
|
|
2373
2399
|
size: "sm",
|
|
2374
2400
|
href: validLinkHref(linkHref.value),
|
|
2375
2401
|
target: "_blank",
|
|
2376
2402
|
rel: "noopener noreferrer"
|
|
2377
|
-
}, () => "
|
|
2403
|
+
}, () => "Open link") : null]),
|
|
2404
|
+
h(Cluster, {
|
|
2405
|
+
gap: "xs",
|
|
2406
|
+
justify: "end",
|
|
2407
|
+
wrap: "nowrap"
|
|
2408
|
+
}, () => [h(Button, {
|
|
2378
2409
|
type: "button",
|
|
2379
|
-
variant: "
|
|
2380
|
-
tone: "
|
|
2410
|
+
variant: "outline",
|
|
2411
|
+
tone: "accent",
|
|
2381
2412
|
size: "sm",
|
|
2382
2413
|
onClick: cancelLink
|
|
2383
2414
|
}, () => "Cancel"), h(Button, {
|
|
2384
2415
|
type: "submit",
|
|
2385
2416
|
variant: "solid",
|
|
2386
2417
|
size: "sm"
|
|
2387
|
-
}, () => "Save link")])
|
|
2418
|
+
}, () => "Save link")])
|
|
2388
2419
|
])]);
|
|
2389
2420
|
const renderLinkContext = (instance) => {
|
|
2390
2421
|
if (linkContextEditing.value) return renderLinkForm();
|
|
@@ -2428,7 +2459,10 @@ var LoomaEditor = defineComponent({
|
|
|
2428
2459
|
target: "_blank",
|
|
2429
2460
|
rel: "noopener noreferrer",
|
|
2430
2461
|
"aria-label": "Open link"
|
|
2431
|
-
}, () =>
|
|
2462
|
+
}, () => h(Cluster, {
|
|
2463
|
+
gap: "xs",
|
|
2464
|
+
wrap: "nowrap"
|
|
2465
|
+
}, () => [loomaIcon("external-link"), "Open link"])) : null,
|
|
2432
2466
|
safeHref ? h(Tooltip, { for: openId }, () => "Open link") : null,
|
|
2433
2467
|
h(IconButton, {
|
|
2434
2468
|
id: editId,
|
|
@@ -2787,12 +2821,13 @@ var LoomaEditor = defineComponent({
|
|
|
2787
2821
|
};
|
|
2788
2822
|
const onFormattingKeyDown = (event) => {
|
|
2789
2823
|
cancelHeldPress();
|
|
2790
|
-
if (event.key !== "Escape" || !
|
|
2824
|
+
if (event.key !== "Escape" || !(event.target instanceof Node) || !(root.value?.contains(event.target) || formattingPopup?.popper.contains(event.target) || linkPopup?.popper.contains(event.target)) || !(formatOpen.value || formattingPopup?.popper.style.visibility === "visible" || linkPopup?.popper.style.visibility === "visible")) return false;
|
|
2791
2825
|
const selection = editor.value?.state.selection;
|
|
2792
2826
|
dismissedFormattingSelection = selection instanceof TextSelection || selection instanceof AllSelection ? selection : null;
|
|
2793
2827
|
heldFormattingSelection = null;
|
|
2794
2828
|
formatOpen.value = false;
|
|
2795
2829
|
formattingPopup?.hide();
|
|
2830
|
+
linkPopup?.hide();
|
|
2796
2831
|
hideTool();
|
|
2797
2832
|
return true;
|
|
2798
2833
|
};
|
|
@@ -2877,7 +2912,17 @@ var LoomaEditor = defineComponent({
|
|
|
2877
2912
|
trigger: "programmatic"
|
|
2878
2913
|
});
|
|
2879
2914
|
};
|
|
2915
|
+
const onLinkNavigationModifier = (event) => {
|
|
2916
|
+
const dom = editor.value?.view.dom;
|
|
2917
|
+
const active = isApplePlatform() ? event.metaKey : event.ctrlKey;
|
|
2918
|
+
if (dom && dom.hasAttribute("data-link-navigation") !== active) dom.toggleAttribute("data-link-navigation", active);
|
|
2919
|
+
};
|
|
2920
|
+
const clearLinkNavigationModifier = () => editor.value?.view.dom.removeAttribute("data-link-navigation");
|
|
2880
2921
|
onMounted(() => {
|
|
2922
|
+
window.addEventListener("keydown", onLinkNavigationModifier);
|
|
2923
|
+
window.addEventListener("keyup", onLinkNavigationModifier);
|
|
2924
|
+
window.addEventListener("pointermove", onLinkNavigationModifier);
|
|
2925
|
+
window.addEventListener("blur", clearLinkNavigationModifier);
|
|
2881
2926
|
updateMobileViewport();
|
|
2882
2927
|
window.addEventListener("resize", onViewportChange);
|
|
2883
2928
|
window.addEventListener("scroll", onViewportChange, true);
|
|
@@ -2894,6 +2939,10 @@ var LoomaEditor = defineComponent({
|
|
|
2894
2939
|
root.value?.addEventListener("error", onImageError, true);
|
|
2895
2940
|
});
|
|
2896
2941
|
onBeforeUnmount(() => {
|
|
2942
|
+
window.removeEventListener("keydown", onLinkNavigationModifier);
|
|
2943
|
+
window.removeEventListener("keyup", onLinkNavigationModifier);
|
|
2944
|
+
window.removeEventListener("pointermove", onLinkNavigationModifier);
|
|
2945
|
+
window.removeEventListener("blur", clearLinkNavigationModifier);
|
|
2897
2946
|
window.removeEventListener("resize", onViewportChange);
|
|
2898
2947
|
window.removeEventListener("scroll", onViewportChange, true);
|
|
2899
2948
|
window.visualViewport?.removeEventListener("resize", onViewportChange);
|
|
@@ -3358,19 +3407,26 @@ var LoomaEditor = defineComponent({
|
|
|
3358
3407
|
}
|
|
3359
3408
|
}] } } : {}
|
|
3360
3409
|
}
|
|
3361
|
-
}, { default: () => props.toolbarMode === "contextual" ? h(Stack, { gap: "xs" }, () => [renderToolbar(instance, true), (linkContextEditing.value || instance.state.selection.empty && instance.isActive("link")) && !linkOpen.value ? renderLinkContextCard(instance) : null]) : renderToolbar(instance, true, props.toolbarMode === "popover") }) : null,
|
|
3362
|
-
instance && props.editable
|
|
3410
|
+
}, { default: () => props.toolbarMode === "contextual" ? h(Stack, { gap: "xs" }, () => [renderToolbar(instance, true), (linkContextEditing.value || instance.state.selection.empty && instance.isActive("link")) && !linkOpen.value && formattingSelectionActive(instance) ? renderLinkContextCard(instance) : null]) : renderToolbar(instance, true, props.toolbarMode === "popover") }) : null,
|
|
3411
|
+
instance && props.editable ? h(BubbleMenu, {
|
|
3363
3412
|
editor: instance,
|
|
3364
3413
|
pluginKey: "looma-link-context-menu",
|
|
3365
|
-
|
|
3414
|
+
updateDelay: 0,
|
|
3415
|
+
shouldShow: ({ editor: menuEditor, from, to }) => from === to && menuEditor.isActive("link") && !linkOpen.value && !dismissedFormattingSelection?.eq(menuEditor.state.selection) && Boolean(menuEditor.isFocused || linkContextEditing.value || linkPopup?.popper.contains(document.activeElement)) && !(props.toolbarMode === "contextual" && floatingFormattingMode() && formattingSelectionActive(menuEditor)),
|
|
3366
3416
|
tippyOptions: {
|
|
3417
|
+
onCreate: (popup) => {
|
|
3418
|
+
linkPopup = popup;
|
|
3419
|
+
},
|
|
3420
|
+
onDestroy: () => {
|
|
3421
|
+
linkPopup = null;
|
|
3422
|
+
},
|
|
3367
3423
|
appendTo: () => root.value?.closest("dialog[open], [popover]") ?? document.body,
|
|
3368
3424
|
onShow: () => announceOverlayOpen(root.value?.ownerDocument ?? document, root.value),
|
|
3369
3425
|
duration: 100,
|
|
3370
3426
|
maxWidth: Math.min(480, window.innerWidth - 24),
|
|
3371
|
-
placement: "
|
|
3427
|
+
placement: "top"
|
|
3372
3428
|
}
|
|
3373
|
-
}, { default: () => renderLinkContextCard(instance) }) : null,
|
|
3429
|
+
}, { default: () => props.toolbarMode === "contextual" && floatingFormattingMode() && formattingSelectionActive(instance) ? null : renderLinkContextCard(instance) }) : null,
|
|
3374
3430
|
instance && props.editable && !mobile.value && props.toolbarMode === "popover" && props.toolbarTriggerId ? h(Popover, {
|
|
3375
3431
|
class: "looma-editor__formatting-popover",
|
|
3376
3432
|
role: "region",
|