@panphora/clayjs 1.5.3 → 1.6.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/README.md +5 -3
- package/THIRD-PARTY-NOTICES.md +6 -0
- package/dist/clay.standalone.js +15041 -10657
- package/package.json +9 -4
- package/src/core/conflict-download.js +91 -0
- package/src/core/conflict-notice.js +720 -0
- package/src/core/conflict-presentation.js +301 -0
- package/src/core/save-conflict-notice.js +2 -192
- package/src/core/save-core.js +35 -2
- package/src/core/save-feedback.js +6 -0
- package/src/core/save.js +157 -3
- package/src/core/snapshot.js +21 -0
- package/src/core/stale-host-notice.js +21 -24
- package/src/core/unsaved-warning.js +64 -16
- package/src/lib/content-dom.js +4 -2
- package/src/lib/dirty-gate.js +37 -1
- package/src/lib/unsaved-state.js +55 -0
- package/src/loader-logic.js +26 -15
- package/src/loader.js +10 -3
- package/src/plugins/ai-edit.js +489 -179
- package/src/plugins/cms.js +12 -0
- package/src/plugins/indicator.js +35 -16
- package/src/plugins/quickcrop.js +103 -0
- package/src/plugins/richclay.js +21 -0
- package/src/plugins/source.js +13 -6
- package/src/plugins/wire.js +4 -0
- package/src/sync/conflict-revert.js +1138 -0
- package/src/sync/conflicts.js +159 -0
- package/src/sync/live-sync.js +130 -109
- package/src/sync/presence.js +42 -36
- package/src/sync/section-notice.js +53 -28
- package/src/ui/bevel-controls.js +277 -0
- package/src/ui/bevel-dialog.js +112 -0
- package/src/ui/bevel.js +247 -0
- package/src/ui/dialogs.js +63 -86
- package/src/ui/index.js +22 -11
- package/src/ui/modal.js +80 -387
- package/src/ui/skins/cms-toggle.js +15 -0
- package/src/ui/skins/cms.js +4 -0
- package/src/ui/skins/quickcrop.js +4 -0
- package/src/ui/skins/richclay.js +4 -0
- package/src/ui/toast.js +116 -401
- package/src/ui/vendor-skin.js +65 -0
- package/src/vendor/hyper-morph.vendor.js +4 -4
- package/src/vendor/quickcrop.vendor.js +14 -8
- package/src/vendor/richclay.vendor.js +22 -41
package/src/ui/modal.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { bevelButton, setShown } from "./bevel-controls.js";
|
|
2
|
+
import { set } from "../lib/hostile-css.js";
|
|
3
|
+
import { bevelDialog, dismissOf } from "./bevel-dialog.js";
|
|
4
|
+
|
|
1
5
|
/*
|
|
2
6
|
|
|
3
7
|
theModal
|
|
@@ -9,10 +13,14 @@
|
|
|
9
13
|
- user confirms
|
|
10
14
|
- everything about the modal resets
|
|
11
15
|
|
|
12
|
-
themodal.html = content;
|
|
16
|
+
themodal.html = content; // html, yes and no each take markup, or a node placed as it is
|
|
13
17
|
themodal.yes = content;
|
|
14
18
|
themodal.no = content;
|
|
15
19
|
|
|
20
|
+
themodal.closeHtml = "x"; // any non-empty value shows the corner close
|
|
21
|
+
themodal.title = content; // markup or a node: a header with the title (optional)
|
|
22
|
+
themodal.width = "440px"; // the panel's width (default 600px)
|
|
23
|
+
|
|
16
24
|
themodal.disableFocus = true;
|
|
17
25
|
themodal.disableScroll = true;
|
|
18
26
|
|
|
@@ -24,35 +32,11 @@
|
|
|
24
32
|
|
|
25
33
|
*/
|
|
26
34
|
|
|
27
|
-
/*
|
|
28
|
-
|
|
29
|
-
things you probably want to style
|
|
30
|
-
|
|
31
|
-
.micromodal {}
|
|
32
|
-
.micromodal .micromodal__container {}
|
|
33
|
-
.micromodal .micromodal__content {}
|
|
34
|
-
.micromodal .micromodal__heading {}
|
|
35
|
-
.micromodal .micromodal__input {}
|
|
36
|
-
.micromodal .micromodal__input:focus, .micromodal .micromodal__input:active {}
|
|
37
|
-
.micromodal .micromodal__buttons {}
|
|
38
|
-
.micromodal .micromodal__yes, .micromodal__no {}
|
|
39
|
-
.micromodal .micromodal__yes {}
|
|
40
|
-
.micromodal .micromodal__yes:focus, .micromodal__yes:hover {}
|
|
41
|
-
.micromodal .micromodal__no {}
|
|
42
|
-
.micromodal .micromodal__no:focus, .micromodal__no:hover {}
|
|
43
|
-
.micromodal .micromodal__close {}
|
|
44
|
-
.micromodal .micromodal__close:focus, .micromodal__close:hover {}
|
|
45
|
-
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
35
|
// MicroModal
|
|
54
36
|
// MIT License (c) 2017 Indrashish Ghosh
|
|
55
37
|
// MODIFIED: removed `this.activeElement.focus()` after modal is closed
|
|
38
|
+
// MODIFIED: takes the modal element itself, not an id, and adds no open class; the
|
|
39
|
+
// shell is created on open and removed on close, so nothing has to be looked up
|
|
56
40
|
|
|
57
41
|
const MicroModal = (() => {
|
|
58
42
|
'use strict'
|
|
@@ -86,7 +70,7 @@ const MicroModal = (() => {
|
|
|
86
70
|
awaitOpenAnimation = false,
|
|
87
71
|
debugMode = false
|
|
88
72
|
}) {
|
|
89
|
-
this.modal = document.getElementById(targetModal)
|
|
73
|
+
this.modal = typeof targetModal === 'string' ? document.getElementById(targetModal) : targetModal
|
|
90
74
|
|
|
91
75
|
this.config = { debugMode, disableScroll, openTrigger, closeTrigger, openClass, onShow, onClose, awaitCloseAnimation, awaitOpenAnimation, disableFocus }
|
|
92
76
|
|
|
@@ -105,7 +89,6 @@ const MicroModal = (() => {
|
|
|
105
89
|
showModal (event = null) {
|
|
106
90
|
this.activeElement = document.activeElement
|
|
107
91
|
this.modal.setAttribute('aria-hidden', 'false')
|
|
108
|
-
this.modal.classList.add(this.config.openClass)
|
|
109
92
|
this.scrollBehaviour('disable')
|
|
110
93
|
this.addEventListeners()
|
|
111
94
|
|
|
@@ -122,33 +105,13 @@ const MicroModal = (() => {
|
|
|
122
105
|
this.config.onShow(this.modal, this.activeElement, event)
|
|
123
106
|
}
|
|
124
107
|
|
|
108
|
+
// Runs on the stored element even after a live-sync morph removed it from the
|
|
109
|
+
// DOM, so onClose, the keydown listener and the scroll restore are never stranded.
|
|
125
110
|
closeModal (event = null) {
|
|
126
|
-
const modal = this.modal
|
|
127
111
|
this.modal.setAttribute('aria-hidden', 'true')
|
|
128
112
|
this.removeEventListeners()
|
|
129
113
|
this.scrollBehaviour('enable')
|
|
130
114
|
this.config.onClose(this.modal, this.activeElement, event)
|
|
131
|
-
|
|
132
|
-
if (this.config.awaitCloseAnimation) {
|
|
133
|
-
const openClass = this.config.openClass // <- old school ftw
|
|
134
|
-
this.modal.addEventListener('animationend', function handler () {
|
|
135
|
-
modal.classList.remove(openClass)
|
|
136
|
-
modal.removeEventListener('animationend', handler, false)
|
|
137
|
-
}, false)
|
|
138
|
-
} else {
|
|
139
|
-
modal.classList.remove(this.config.openClass)
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
closeModalById (targetModal) {
|
|
144
|
-
// Fall back to the stored modal reference when the node was removed from
|
|
145
|
-
// the DOM externally (e.g. a live-sync morph). Without this, getElementById
|
|
146
|
-
// returns null, closeModal() is skipped, and its cleanup never runs — the
|
|
147
|
-
// onClose callback, this.removeEventListeners() (which drops MicroModal's
|
|
148
|
-
// document keydown listener), and scroll restore are all stranded.
|
|
149
|
-
const modal = document.getElementById(targetModal)
|
|
150
|
-
if (modal) this.modal = modal
|
|
151
|
-
if (this.modal) this.closeModal()
|
|
152
115
|
}
|
|
153
116
|
|
|
154
117
|
scrollBehaviour (toggle) {
|
|
@@ -310,9 +273,9 @@ const MicroModal = (() => {
|
|
|
310
273
|
activeModal.showModal()
|
|
311
274
|
}
|
|
312
275
|
|
|
313
|
-
const close =
|
|
276
|
+
const close = () => {
|
|
314
277
|
if (!activeModal) return
|
|
315
|
-
|
|
278
|
+
activeModal.closeModal()
|
|
316
279
|
activeModal = null
|
|
317
280
|
}
|
|
318
281
|
|
|
@@ -323,310 +286,10 @@ const MicroModal = (() => {
|
|
|
323
286
|
|
|
324
287
|
// themodal.js
|
|
325
288
|
// MIT License (c) 2023 David Miranda
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
.
|
|
329
|
-
|
|
330
|
-
color: #fff;
|
|
331
|
-
font-family: var(--hyperclay-modal-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace);
|
|
332
|
-
font-size: var(--hyperclay-modal-font-size, 18px);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
.micromodal button:not(.custom-button) {
|
|
336
|
-
background: none;
|
|
337
|
-
color: inherit;
|
|
338
|
-
border: none;
|
|
339
|
-
padding: 0;
|
|
340
|
-
margin: 0;
|
|
341
|
-
width: auto;
|
|
342
|
-
overflow: visible;
|
|
343
|
-
font: inherit;
|
|
344
|
-
line-height: inherit;
|
|
345
|
-
text-transform: none;
|
|
346
|
-
text-align: center;
|
|
347
|
-
text-decoration: none;
|
|
348
|
-
cursor: pointer;
|
|
349
|
-
-webkit-appearance: none;
|
|
350
|
-
-moz-appearance: none;
|
|
351
|
-
appearance: none;
|
|
352
|
-
outline: 0;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
.micromodal .micromodal__hide {
|
|
356
|
-
display: none;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
.micromodal.is-open {
|
|
360
|
-
display: block;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
.micromodal__overlay {
|
|
364
|
-
position: fixed;
|
|
365
|
-
top: 0;
|
|
366
|
-
left: 0;
|
|
367
|
-
right: 0;
|
|
368
|
-
bottom: 0;
|
|
369
|
-
display: flex;
|
|
370
|
-
justify-content: center;
|
|
371
|
-
align-items: center;
|
|
372
|
-
background: rgba(0,0,0,.65);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
.micromodal__container {
|
|
376
|
-
position: relative;
|
|
377
|
-
width: 100%;
|
|
378
|
-
min-width: 0;
|
|
379
|
-
max-width: min(550px, calc(100vw - 2rem));
|
|
380
|
-
max-height: calc(100vh - 4rem);
|
|
381
|
-
max-height: calc(100dvh - 2rem);
|
|
382
|
-
box-sizing: border-box;
|
|
383
|
-
overflow: hidden;
|
|
384
|
-
border: 2px solid #FFFFFF;
|
|
385
|
-
background-color: #11131E;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
.micromodal__inner {
|
|
389
|
-
overflow-x: hidden;
|
|
390
|
-
overflow-y: auto;
|
|
391
|
-
/* Must subtract container's 4px border (2px top + 2px bottom) from max-height,
|
|
392
|
-
otherwise inner overflows past container since box-sizing: border-box
|
|
393
|
-
makes the container's content area smaller than its max-height */
|
|
394
|
-
max-height: calc(100dvh - 2rem - 4px);
|
|
395
|
-
padding: 26px 40px 40px 40px;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
@media (min-width: 640px) {
|
|
399
|
-
.micromodal .micromodal__inner {
|
|
400
|
-
padding: 52px 64px 60px 64px;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
.micromodal[aria-hidden="false"] .micromodal__overlay {
|
|
405
|
-
animation: microModalFadeIn .2s cubic-bezier(0.0, 0.0, 0.2, 1);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.micromodal[aria-hidden="false"] .micromodal__container {
|
|
409
|
-
animation: microModalSlideIn .2s cubic-bezier(0, 0, .2, 1);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.micromodal .micromodal__container,
|
|
413
|
-
.micromodal .micromodal__overlay {
|
|
414
|
-
will-change: transform;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
@keyframes microModalFadeIn {
|
|
418
|
-
from { opacity: 0; }
|
|
419
|
-
to { opacity: 1; }
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
@keyframes microModalSlideIn {
|
|
423
|
-
from { transform: translateY(15%); }
|
|
424
|
-
to { transform: translateY(0); }
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
.micromodal .micromodal__content {
|
|
428
|
-
margin-bottom: 14px;
|
|
429
|
-
overflow-wrap: anywhere;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
.micromodal .micromodal__heading {
|
|
433
|
-
display: flex;
|
|
434
|
-
flex-direction: column;
|
|
435
|
-
gap: 2px;
|
|
436
|
-
margin-bottom: 8px;
|
|
437
|
-
overflow-wrap: anywhere;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
.micromodal .micromodal__input {
|
|
441
|
-
width: min(calc(100vw - 100px), 420px);
|
|
442
|
-
padding: 6px 6px 7px;
|
|
443
|
-
font-size: var(--hyperclay-modal-input-font-size, 16px);
|
|
444
|
-
color: #000;
|
|
445
|
-
background: #fff;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
.micromodal .micromodal__input:focus, .micromodal .micromodal__input:active {
|
|
449
|
-
outline: 3px solid #6A73B6;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
.micromodal button.micromodal__yes {
|
|
453
|
-
display: flex;
|
|
454
|
-
justify-content: center;
|
|
455
|
-
align-items: center;
|
|
456
|
-
width: 100%;
|
|
457
|
-
height: 39px;
|
|
458
|
-
line-height: 0;
|
|
459
|
-
border: 3px solid;
|
|
460
|
-
border-top-color: #94BA6F;
|
|
461
|
-
border-left-color: #94BA6F;
|
|
462
|
-
border-bottom-color: #1A3004;
|
|
463
|
-
border-right-color: #1A3004;
|
|
464
|
-
background-color: #49870B;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
.micromodal button.micromodal__yes:focus,
|
|
468
|
-
.micromodal button.micromodal__yes:hover {
|
|
469
|
-
background-color: #549B0D;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
.micromodal button.micromodal__yes:active {
|
|
473
|
-
border-top-color: #1A3004;
|
|
474
|
-
border-left-color: #1A3004;
|
|
475
|
-
border-bottom-color: #94BA6F;
|
|
476
|
-
border-right-color: #94BA6F;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
.micromodal button.micromodal__secondary-btn {
|
|
480
|
-
display: flex;
|
|
481
|
-
justify-content: center;
|
|
482
|
-
align-items: center;
|
|
483
|
-
width: 100%;
|
|
484
|
-
height: 39px;
|
|
485
|
-
line-height: 0;
|
|
486
|
-
border: 3px solid;
|
|
487
|
-
border-top-color: #474C65;
|
|
488
|
-
border-left-color: #474C65;
|
|
489
|
-
border-bottom-color: #131725;
|
|
490
|
-
border-right-color: #131725;
|
|
491
|
-
background-color: #1D1F2F;
|
|
492
|
-
color: #E5E7EB;
|
|
493
|
-
font-family: inherit;
|
|
494
|
-
font-size: inherit;
|
|
495
|
-
font-weight: bold;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
.micromodal button.micromodal__secondary-btn:focus,
|
|
499
|
-
.micromodal button.micromodal__secondary-btn:hover {
|
|
500
|
-
background-color: #232639;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
.micromodal button.micromodal__secondary-btn:active {
|
|
504
|
-
border-top-color: #131725;
|
|
505
|
-
border-left-color: #131725;
|
|
506
|
-
border-bottom-color: #474C65;
|
|
507
|
-
border-right-color: #474C65;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
.micromodal:has(.snippet-code-block) .micromodal__content {
|
|
511
|
-
margin-bottom: 0;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
.micromodal .snippet-code-block {
|
|
515
|
-
background-color: #292E54;
|
|
516
|
-
padding: 1rem;
|
|
517
|
-
margin-bottom: 14px;
|
|
518
|
-
max-width: 420px;
|
|
519
|
-
overflow-x: auto;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
.micromodal .snippet-code-block pre {
|
|
523
|
-
color: white;
|
|
524
|
-
font-family: var(--hyperclay-modal-code-font-family, var(--hyperclay-modal-font-family, monospace));
|
|
525
|
-
font-size: 0.875rem;
|
|
526
|
-
white-space: nowrap;
|
|
527
|
-
margin: 0;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
.micromodal .snippet-warning {
|
|
531
|
-
padding: 0.75rem;
|
|
532
|
-
border: 2px solid #989742;
|
|
533
|
-
background-color: #1E1E11;
|
|
534
|
-
font-size: 0.875rem;
|
|
535
|
-
color: #FBF7B7;
|
|
536
|
-
max-width: 420px;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
.micromodal .snippet-link-box {
|
|
540
|
-
font-size: 16px;
|
|
541
|
-
margin-top: 0.75rem;
|
|
542
|
-
text-align: right;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
.micromodal .snippet-link-box a {
|
|
546
|
-
color: #F6F7F9;
|
|
547
|
-
text-decoration: none;
|
|
548
|
-
display: inline-flex;
|
|
549
|
-
align-items: center;
|
|
550
|
-
gap: 0.3rem;
|
|
551
|
-
padding: 0.35rem 0.45rem;
|
|
552
|
-
border: 1px solid #474C64;
|
|
553
|
-
line-height: 1;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
.micromodal .snippet-link-box a:hover {
|
|
557
|
-
color: #E5E7EB;
|
|
558
|
-
border-color: #75798B;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
.micromodal .snippet-link-box a svg {
|
|
562
|
-
width: 0.85rem;
|
|
563
|
-
height: 0.85rem;
|
|
564
|
-
flex-shrink: 0;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
.micromodal button.micromodal__close {
|
|
568
|
-
clip-path: polygon(0% 4%, 0% 0%, 100% 0%, 100% 100%, 94% 100%);
|
|
569
|
-
position: absolute;
|
|
570
|
-
top: -1px;
|
|
571
|
-
right: -1px;
|
|
572
|
-
width: 68px;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
.micromodal .micromodal__close-bg {
|
|
576
|
-
fill: #1D2032;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
.micromodal .micromodal__close:hover .micromodal__close-bg {
|
|
580
|
-
fill: #212543;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
.micromodal .micromodal__close-x {
|
|
584
|
-
fill: #fff;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
.micromodal .micromodal__tell {
|
|
588
|
-
max-width: 440px;
|
|
589
|
-
margin-bottom: 28px;
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
.micromodal .micromodal__tell > * + * {
|
|
593
|
-
margin-top: 20px;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
.micromodal .micromodal__tell-title {
|
|
597
|
-
font-size: var(--hyperclay-modal-title-font-size, 20px);
|
|
598
|
-
font-weight: bold;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
.micromodal .micromodal__tell-content {
|
|
602
|
-
font-size: var(--hyperclay-modal-font-size, 16px);
|
|
603
|
-
font-weight: normal;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
@media (min-width: 640px) {
|
|
607
|
-
.micromodal .micromodal__tell-title {
|
|
608
|
-
font-size: var(--hyperclay-modal-title-font-size, 22px);
|
|
609
|
-
}
|
|
610
|
-
.micromodal .micromodal__tell-content {
|
|
611
|
-
font-size: var(--hyperclay-modal-font-size, 18px);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
</style>`;
|
|
615
|
-
|
|
616
|
-
const modalHtml = `<div class="micromodal" id="micromodal" aria-hidden="true">
|
|
617
|
-
<div class="micromodal__overlay" tabindex="-1">
|
|
618
|
-
<form class="micromodal__container" role="dialog" aria-modal="true">
|
|
619
|
-
<div class="micromodal__inner">
|
|
620
|
-
<div class="micromodal__content"></div>
|
|
621
|
-
<div class="micromodal__buttons">
|
|
622
|
-
<button class="micromodal__no" type="button"></button>
|
|
623
|
-
<button class="micromodal__yes" type="submit"></button>
|
|
624
|
-
</div>
|
|
625
|
-
</div>
|
|
626
|
-
<button class="micromodal__close" type="button" aria-label="Close modal"></button>
|
|
627
|
-
</form>
|
|
628
|
-
</div>
|
|
629
|
-
</div>`;
|
|
289
|
+
//
|
|
290
|
+
// Drawn in Bevel (bevel-dialog.js): inline !important, no classes, no ids, so a
|
|
291
|
+
// page stylesheet cannot repaint it. What callers put in html, yes and no is theirs
|
|
292
|
+
// and goes in untouched.
|
|
630
293
|
|
|
631
294
|
const themodal = (() => {
|
|
632
295
|
let html = "";
|
|
@@ -634,6 +297,8 @@ const themodal = (() => {
|
|
|
634
297
|
let no = "";
|
|
635
298
|
let zIndex = "100";
|
|
636
299
|
let closeHtml = "";
|
|
300
|
+
let title = "";
|
|
301
|
+
let width = "";
|
|
637
302
|
|
|
638
303
|
let enableClickOutsideCloses = true;
|
|
639
304
|
let disableScroll = true;
|
|
@@ -671,10 +336,10 @@ const themodal = (() => {
|
|
|
671
336
|
// Singleton: only one modal on screen at a time. If one is still up (or
|
|
672
337
|
// left stale state behind, e.g. a live-sync morph removed its DOM), reject
|
|
673
338
|
// its promise and tear it down before opening the new one.
|
|
674
|
-
if (this.isShowing || document.querySelector('
|
|
339
|
+
if (this.isShowing || document.querySelector('[data-clay-modal]')) {
|
|
675
340
|
this._dismiss?.();
|
|
676
341
|
this._cleanupListeners?.();
|
|
677
|
-
document.querySelectorAll('
|
|
342
|
+
document.querySelectorAll('[data-clay-modal]').forEach(n => { dismissOf.get(n)?.(); n.remove(); });
|
|
678
343
|
this.isShowing = false;
|
|
679
344
|
document.body.style.overflow = '';
|
|
680
345
|
}
|
|
@@ -682,20 +347,33 @@ const themodal = (() => {
|
|
|
682
347
|
// Expose this modal's dismiss so a later open()/close can settle it.
|
|
683
348
|
this._dismiss = dismiss;
|
|
684
349
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
const modalOverlayElem =
|
|
688
|
-
const
|
|
689
|
-
const
|
|
690
|
-
const
|
|
691
|
-
const
|
|
692
|
-
const
|
|
350
|
+
const shell = bevelDialog({ zIndex, closable: !!closeHtml, titled: !!title, ...(width ? { width } : {}) });
|
|
351
|
+
const modalRootElem = shell.root;
|
|
352
|
+
const modalOverlayElem = shell.overlay;
|
|
353
|
+
const modalContainerElem = shell.panel;
|
|
354
|
+
const modalContentElem = shell.body;
|
|
355
|
+
const modalButtonsElem = shell.footer;
|
|
356
|
+
const modalCloseElem = shell.close;
|
|
357
|
+
const modalNoElem = bevelButton('');
|
|
358
|
+
const modalYesElem = bevelButton('', { variant: 'primary' });
|
|
359
|
+
modalYesElem.type = 'submit';
|
|
360
|
+
modalButtonsElem.append(modalNoElem, modalYesElem);
|
|
361
|
+
|
|
362
|
+
// Markup is parsed in; a node is placed as it is, listeners and all.
|
|
363
|
+
const place = (target, value) => {
|
|
364
|
+
if (value instanceof Node) target.append(value);
|
|
365
|
+
else target.innerHTML = value;
|
|
366
|
+
};
|
|
367
|
+
place(modalContentElem, html);
|
|
368
|
+
place(modalYesElem.firstChild, yes);
|
|
369
|
+
place(modalNoElem.firstChild, no);
|
|
370
|
+
if (title) place(shell.heading, title);
|
|
371
|
+
if (title) modalContainerElem.setAttribute("aria-label", shell.heading.textContent.trim());
|
|
372
|
+
// No body content (a confirm that is all title) means no empty band between header and footer.
|
|
373
|
+
setShown(modalContentElem, !(html === "" || html == null), "block");
|
|
374
|
+
if ((html === "" || html == null) && title) set(modalButtonsElem, "border-top", "0");
|
|
693
375
|
|
|
694
|
-
|
|
695
|
-
modalYesElem.innerHTML = yes;
|
|
696
|
-
modalNoElem.innerHTML = no;
|
|
697
|
-
modalOverlayElem.style.zIndex = zIndex;
|
|
698
|
-
modalCloseElem.innerHTML = closeHtml;
|
|
376
|
+
document.body.prepend(modalRootElem);
|
|
699
377
|
|
|
700
378
|
// MODIFIED so modal doesn't close if mousedown happened inside the modal
|
|
701
379
|
let mousedownOnBackdrop = false;
|
|
@@ -703,17 +381,17 @@ const themodal = (() => {
|
|
|
703
381
|
// MODIFIED so modal doesn't close if mousedown happened inside the modal
|
|
704
382
|
function handleMousedown(event) {
|
|
705
383
|
// Check if mousedown started on backdrop (overlay but not container)
|
|
706
|
-
mousedownOnBackdrop = event.target
|
|
707
|
-
!event.target
|
|
384
|
+
mousedownOnBackdrop = modalOverlayElem.contains(event.target) &&
|
|
385
|
+
!modalContainerElem.contains(event.target);
|
|
708
386
|
}
|
|
709
387
|
|
|
710
388
|
function handleClick(event) {
|
|
711
389
|
// Just close on no / close-button / backdrop; onClose runs dismiss().
|
|
712
|
-
if (event.target
|
|
713
|
-
MicroModal.close(
|
|
390
|
+
if (modalNoElem.contains(event.target) || modalCloseElem?.contains(event.target)) {
|
|
391
|
+
MicroModal.close();
|
|
714
392
|
// MODIFIED so modal doesn't close if mousedown happened inside the modal
|
|
715
|
-
} else if (enableClickOutsideCloses && mousedownOnBackdrop && !event.target
|
|
716
|
-
MicroModal.close(
|
|
393
|
+
} else if (enableClickOutsideCloses && mousedownOnBackdrop && !modalContainerElem.contains(event.target) && modalOverlayElem.contains(event.target)) {
|
|
394
|
+
MicroModal.close();
|
|
717
395
|
}
|
|
718
396
|
|
|
719
397
|
// Reset after handling
|
|
@@ -721,7 +399,7 @@ const themodal = (() => {
|
|
|
721
399
|
}
|
|
722
400
|
|
|
723
401
|
function handleSubmit(event) {
|
|
724
|
-
if (event.target
|
|
402
|
+
if (modalRootElem.contains(event.target)) {
|
|
725
403
|
event.preventDefault();
|
|
726
404
|
|
|
727
405
|
// Execute callbacks and check if any return false or throw errors
|
|
@@ -747,7 +425,7 @@ const themodal = (() => {
|
|
|
747
425
|
// scheduled their resolve, so mark settled to stop onClose rejecting.
|
|
748
426
|
if (shouldClose) {
|
|
749
427
|
settled = true;
|
|
750
|
-
MicroModal.close(
|
|
428
|
+
MicroModal.close();
|
|
751
429
|
}
|
|
752
430
|
}
|
|
753
431
|
}
|
|
@@ -765,14 +443,14 @@ const themodal = (() => {
|
|
|
765
443
|
};
|
|
766
444
|
|
|
767
445
|
function setButtonsVisibility () {
|
|
768
|
-
modalButtonsElem
|
|
769
|
-
modalYesElem
|
|
770
|
-
modalNoElem
|
|
446
|
+
setShown(modalButtonsElem, !!(yes || no), "flex");
|
|
447
|
+
setShown(modalYesElem, !!yes, "inline-flex");
|
|
448
|
+
setShown(modalNoElem, !!no, "inline-flex");
|
|
771
449
|
}
|
|
772
450
|
|
|
773
451
|
setButtonsVisibility();
|
|
774
452
|
|
|
775
|
-
MicroModal.show(
|
|
453
|
+
MicroModal.show(modalRootElem, {
|
|
776
454
|
disableScroll,
|
|
777
455
|
disableFocus: true, // we use our own
|
|
778
456
|
// reset everything on close
|
|
@@ -781,13 +459,15 @@ const themodal = (() => {
|
|
|
781
459
|
// (no / close / backdrop / Esc). No-op once already resolved.
|
|
782
460
|
dismiss();
|
|
783
461
|
|
|
784
|
-
|
|
462
|
+
modalRootElem.remove();
|
|
785
463
|
|
|
786
464
|
html = "";
|
|
787
465
|
yes = "";
|
|
788
466
|
no = "";
|
|
789
467
|
zIndex = "100";
|
|
790
468
|
closeHtml = "";
|
|
469
|
+
title = "";
|
|
470
|
+
width = "";
|
|
791
471
|
|
|
792
472
|
// reset to defaults
|
|
793
473
|
enableClickOutsideCloses = true;
|
|
@@ -814,14 +494,15 @@ const themodal = (() => {
|
|
|
814
494
|
myOnOpen.forEach(cb => cb());
|
|
815
495
|
|
|
816
496
|
if (!disableFocus) {
|
|
817
|
-
let firstInput =
|
|
497
|
+
let firstInput = modalContentElem.querySelector(":is(input,textarea,button):not([hidden])") ||
|
|
498
|
+
[modalYesElem, modalNoElem].find(button => !button.hidden);
|
|
818
499
|
firstInput?.focus();
|
|
819
500
|
firstInput?.setSelectionRange?.(-1, -1);
|
|
820
501
|
}
|
|
821
502
|
},
|
|
822
503
|
close() {
|
|
823
504
|
// onClose runs the dismiss/reject path; just trigger the close.
|
|
824
|
-
MicroModal.close(
|
|
505
|
+
MicroModal.close();
|
|
825
506
|
},
|
|
826
507
|
get html() {
|
|
827
508
|
return html;
|
|
@@ -835,6 +516,18 @@ const themodal = (() => {
|
|
|
835
516
|
set closeHtml(newVal) {
|
|
836
517
|
closeHtml = newVal;
|
|
837
518
|
},
|
|
519
|
+
get title() {
|
|
520
|
+
return title;
|
|
521
|
+
},
|
|
522
|
+
set title(newVal) {
|
|
523
|
+
title = newVal;
|
|
524
|
+
},
|
|
525
|
+
get width() {
|
|
526
|
+
return width;
|
|
527
|
+
},
|
|
528
|
+
set width(newVal) {
|
|
529
|
+
width = newVal;
|
|
530
|
+
},
|
|
838
531
|
get yes() {
|
|
839
532
|
return yes;
|
|
840
533
|
},
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// The CMS's "Edit content" toggle in Bevel's button face. HyperCMS pins the toggle's fill
|
|
2
|
+
// to an opaque neutral (#0a0a0a or #fafafa) and exposes --hcms-toggle-bg and
|
|
3
|
+
// --hcms-toggle-color for authors; on a dark page Bevel's dark bottom-right edge vanished
|
|
4
|
+
// into the near-black fill and the button read as pressed in. Hand-written, not
|
|
5
|
+
// generated: the generated CMS skin may only pin the vendor's --mirk-* tokens.
|
|
6
|
+
import { TOKENS } from "../bevel.js";
|
|
7
|
+
|
|
8
|
+
export const ROOTS = ["[data-hcms-toggle-host]"];
|
|
9
|
+
|
|
10
|
+
export const CSS = `@layer clay-skin{
|
|
11
|
+
[data-hcms-toggle-host]{--hcms-toggle-bg:${TOKENS.face} !important;--hcms-toggle-color:${TOKENS.ink} !important}
|
|
12
|
+
[data-hcms-toggle-host] :is(.hcms-toggle__main, .hcms-toggle__arrow){border-color:${TOKENS["edge-hi"]} ${TOKENS["edge-lo"]} ${TOKENS["edge-lo"]} ${TOKENS["edge-hi"]} !important}
|
|
13
|
+
[data-hcms-toggle-host] :is(.hcms-toggle__main, .hcms-toggle__arrow):hover:not(:active){--hcms-toggle-bg:color-mix(in srgb, ${TOKENS.face}, ${TOKENS["edge-hi"]} 45%) !important}
|
|
14
|
+
[data-hcms-toggle-host] :is(.hcms-toggle__main, .hcms-toggle__arrow):active{border-color:${TOKENS["edge-lo"]} ${TOKENS["edge-hi"]} ${TOKENS["edge-hi"]} ${TOKENS["edge-lo"]} !important}
|
|
15
|
+
}`;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// GENERATED from src/vendor/hypercms.vendor.js by scripts/build-vendor-skins.mjs. Run `npm run build:skins`.
|
|
2
|
+
export const SOURCE_SHA256 = "c7a060a8458cc2ac182145f9415a623bf3fdfe5d5cd2b1724ad7d89959266862";
|
|
3
|
+
export const ROOTS = [".hcms-shell"];
|
|
4
|
+
export const CSS = "@layer clay-skin{\n:is(.hcms-shell):not([data-theme]),:is(.hcms-shell):not([data-theme]) *{--mirk-canvas:light-dark(#FDF8F0, #0B0C13) !important;--mirk-bg:light-dark(#FFFCF6, #11131E) !important;--mirk-fg:light-dark(#2B241B, #ECEAF2) !important;--mirk-accent:light-dark(#F4ECDF, #1A1D2C) !important;--mirk-destructive:light-dark(#A83A2C, #FF5566) !important;--mirk-focus-color:light-dark(#8F6310, #D9A445) !important;--mirk-bevel-bg:light-dark(#F1E7D4, #22273E) !important;--mirk-bevel-fg:light-dark(#2B241B, #ECEAF2) !important;--mirk-bevel-tl:light-dark(#FFF9ED, #3C4260) !important;--mirk-bevel-br:light-dark(#D6C3A5, #1B2033) !important;--mirk-bevel-hover-bg:color-mix(in srgb, light-dark(#F1E7D4, #22273E), light-dark(#FFF9ED, #3C4260) 45%) !important;--mirk-pill-inner-top:light-dark(#FFF9ED, #3C4260) !important;--mirk-input-border:light-dark(#D8C8AF, #353B52) !important;--mirk-placeholder-color:light-dark(#9A8A70, #6A7090) !important;--mirk-ctrl-bg:light-dark(#6B5942, #8A90AB) !important;--mirk-toggle-bg:light-dark(#FCF8F1, #4A5275) !important;--mirk-toggle-hi:light-dark(#FFF9ED, #6C759A) !important;--mirk-toggle-lo:light-dark(#D6C3A5, #1B2033) !important;--mirk-mark-fg:light-dark(#2B241B, #ECEAF2) !important;--mirk-sortable-dot:light-dark(#D8C8AF, #353B52) !important;--mirk-sortable-shadow:light-dark(#D6C3A5, #1B2033) !important;--mirk-sortable-label:light-dark(#6B5942, #8A90AB) !important;--mirk-sortable-placeholder:light-dark(#9A8A70, #6A7090) !important;--mirk-slider-fill:light-dark(#F0E4CC, #3A2F17) !important;--mirk-slider-nub-bg:light-dark(#FCF8F1, #4A5275) !important;--mirk-slider-nub-hi:light-dark(#FFF9ED, #6C759A) !important;--mirk-slider-nub-lo:light-dark(#D6C3A5, #1B2033) !important;--mirk-chip-surface:light-dark(#FFFCF6, #11131E) !important;--mirk-chip-edge:light-dark(#D8C8AF, #353B52) !important;--mirk-chip-primary-bg:light-dark(#2B241B, #ECEAF2) !important;--mirk-chip-primary-fg:light-dark(#FDF8F0, #0B0C13) !important;--mirk-chip-alert:light-dark(#A83A2C, #FF5566) !important;--mirk-radius:0px !important;--mirk-focus-offset:2px !important}\n:is(.hcms-shell){font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace !important}\n.hcms-shell .mirk-chip__actions .mirk-chip__action--primary{--mirk-bevel-bg:var(--mirk-chip-primary-bg) !important;--mirk-bevel-fg:var(--mirk-chip-primary-fg) !important;--mirk-bevel-tl:color-mix(in srgb, var(--mirk-chip-primary-bg), white 24%) !important;--mirk-bevel-br:color-mix(in srgb, var(--mirk-chip-primary-bg), black 32%) !important;--mirk-bevel-hover-bg:color-mix(in srgb, var(--mirk-chip-primary-bg), white 10%) !important}\n}";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// GENERATED from src/vendor/quickcrop.vendor.js and bevel/integrations/quickcrop.css by scripts/build-vendor-skins.mjs. Run `npm run build:skins`.
|
|
2
|
+
export const SOURCE_SHA256 = "49c5be87a001dd2e8fef962ac8c0c933e079fb4be98ecf2e4e1ec850ed922c5a";
|
|
3
|
+
export const ROOTS = [".qc-stage",".qc-backdrop"];
|
|
4
|
+
export const CSS = "@layer clay-skin{\n:is(.qc-stage, .qc-backdrop),:is(.qc-stage, .qc-backdrop) *{--qc-surface:light-dark(#FFFCF6, #11131E) !important;--qc-text:light-dark(#2B241B, #ECEAF2) !important;--qc-border:light-dark(#D8C8AF, #353B52) !important;--qc-radius:0px !important;--qc-font:system-ui,-apple-system,\"Segoe UI\",sans-serif !important;--qc-surface-hover:light-dark(#F4ECDF, #1A1D2C) !important;--qc-text-hover:color-mix(in srgb, light-dark(#2B241B, #ECEAF2), light-dark(#FDF8F0, #0B0C13) 12%) !important;--qc-on-dark:light-dark(#FDF8F0, #0B0C13) !important;--qc-overlay:color-mix(in srgb, light-dark(#FDF8F0, #0B0C13) 70%, transparent) !important;--qc-dim:rgba(0,0,0,.55) !important;--qc-crop-line:#fff !important}\n.qc-stage{margin-inline:auto !important;inline-size:fit-content !important;background:light-dark(#F4ECDF, #1A1D2C) !important}\n.qc-stage img{display:block !important;max-inline-size:100% !important}\n.qc-backdrop{position:fixed !important;inset:0 !important;background:var(--qc-overlay) !important;display:grid !important;place-items:center !important;z-index:1000 !important;animation:qc-fade .15s ease !important}\n.qc-modal{background:var(--qc-surface) !important;border:1px solid var(--qc-border) !important;border-radius:var(--qc-radius) !important;padding:16px !important;max-width:92vw !important;font-family:var(--qc-font) !important}\n.qc-bar{display:flex !important;justify-content:flex-end !important;gap:10px !important;margin-top:12px !important}\n.qc-btn{font:inherit !important;font-family:var(--qc-font) !important;font-size:.85rem !important;padding:.3rem .75rem !important;border:1px solid var(--qc-border) !important;border-radius:6px !important;background:var(--qc-surface) !important;color:var(--qc-text) !important;cursor:pointer !important}\n.qc-btn:hover{background:var(--qc-surface-hover) !important}\n.qc-btn-primary{background:var(--qc-text) !important;border-color:var(--qc-text) !important;color:var(--qc-on-dark) !important;font-weight:600 !important}\n.qc-btn-primary:hover{background:var(--qc-text-hover) !important;border-color:var(--qc-text-hover) !important}\n.qc-stage{position:relative !important;line-height:0 !important;user-select:none !important;-webkit-user-select:none !important;touch-action:none !important}\n.qc-stage img{display:block !important;max-width:100% !important;pointer-events:none !important}\n.qc-dim{position:absolute !important;inset:0 !important;background:var(--qc-dim) !important;pointer-events:none !important}\n.qc-box{position:absolute !important;cursor:move !important;outline:1px solid var(--qc-crop-line) !important;background:linear-gradient(var(--qc-crop-line),var(--qc-crop-line)) 0 33.33%/100% 1px no-repeat,linear-gradient(var(--qc-crop-line),var(--qc-crop-line)) 0 66.66%/100% 1px no-repeat,linear-gradient(var(--qc-crop-line),var(--qc-crop-line)) 33.33% 0/1px 100% no-repeat,linear-gradient(var(--qc-crop-line),var(--qc-crop-line)) 66.66% 0/1px 100% no-repeat !important;background-blend-mode:overlay !important}\n.qc-handle{position:absolute !important;box-sizing:border-box !important;width:28px !important;height:28px !important;border:7px solid transparent !important;background:var(--qc-crop-line) !important;background-clip:padding-box !important;border-radius:9px !important}\n.qc-nw{left:-14px !important;top:-14px !important;cursor:nwse-resize !important}\n.qc-ne{right:-14px !important;top:-14px !important;cursor:nesw-resize !important}\n.qc-sw{left:-14px !important;bottom:-14px !important;cursor:nesw-resize !important}\n.qc-se{right:-14px !important;bottom:-14px !important;cursor:nwse-resize !important}\n.qc-mount{line-height:0 !important}\n.qc-stage img[hidden]{display:none !important}\n.qc-backdrop[hidden]{display:none !important}\n.qc-bar[hidden]{display:none !important}\n}";
|