@duskmoon-dev/el-markdown-input 1.1.1 → 1.1.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/cjs/index.js +168 -12
- package/dist/cjs/index.js.map +4 -4
- package/dist/cjs/register.js +168 -12
- package/dist/cjs/register.js.map +4 -4
- package/dist/esm/index.js +168 -12
- package/dist/esm/index.js.map +4 -4
- package/dist/esm/register.js +168 -12
- package/dist/esm/register.js.map +4 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/css.d.ts.map +1 -1
- package/dist/types/element.d.ts +11 -0
- package/dist/types/element.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -279,6 +279,10 @@ var elementStyles = import_el_base.css`
|
|
|
279
279
|
padding: 0 0.5rem;
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
+
.toolbar[hidden] {
|
|
283
|
+
display: none;
|
|
284
|
+
}
|
|
285
|
+
|
|
282
286
|
.tab-btn {
|
|
283
287
|
padding: 0.5rem 0.875rem;
|
|
284
288
|
border: none;
|
|
@@ -517,6 +521,31 @@ var elementStyles = import_el_base.css`
|
|
|
517
521
|
gap: 0.5rem;
|
|
518
522
|
}
|
|
519
523
|
|
|
524
|
+
.status-bar-start,
|
|
525
|
+
.status-bar-end {
|
|
526
|
+
display: flex;
|
|
527
|
+
align-items: center;
|
|
528
|
+
gap: 0.5rem;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/* Allow slotted light-DOM children to inherit font and alignment */
|
|
532
|
+
.status-bar ::slotted(*),
|
|
533
|
+
.status-bar-start ::slotted(*),
|
|
534
|
+
.status-bar-end ::slotted(*) {
|
|
535
|
+
font-size: inherit;
|
|
536
|
+
font-family: inherit;
|
|
537
|
+
vertical-align: middle;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/* When slot="bottom" is used, the slotted element fills the bar */
|
|
541
|
+
.status-bar > slot[name="bottom"]::slotted(*) {
|
|
542
|
+
display: flex;
|
|
543
|
+
align-items: center;
|
|
544
|
+
justify-content: space-between;
|
|
545
|
+
flex: 1;
|
|
546
|
+
gap: 0.5rem;
|
|
547
|
+
}
|
|
548
|
+
|
|
520
549
|
.attach-btn {
|
|
521
550
|
display: inline-flex;
|
|
522
551
|
align-items: center;
|
|
@@ -551,7 +580,6 @@ var elementStyles = import_el_base.css`
|
|
|
551
580
|
}
|
|
552
581
|
|
|
553
582
|
.status-bar-count {
|
|
554
|
-
margin-left: auto;
|
|
555
583
|
white-space: nowrap;
|
|
556
584
|
}
|
|
557
585
|
|
|
@@ -680,6 +708,52 @@ var elementStyles = import_el_base.css`
|
|
|
680
708
|
white-space: nowrap;
|
|
681
709
|
}
|
|
682
710
|
|
|
711
|
+
/* ── Attached files (local form mode) ────────────────────────────── */
|
|
712
|
+
|
|
713
|
+
.upload-attached-row {
|
|
714
|
+
display: flex;
|
|
715
|
+
align-items: center;
|
|
716
|
+
gap: 0.5rem;
|
|
717
|
+
padding: 0.375rem 0.75rem;
|
|
718
|
+
border-top: 1px solid var(--md-border);
|
|
719
|
+
font-size: 0.75rem;
|
|
720
|
+
color: var(--md-text-muted);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
.upload-attached-size {
|
|
724
|
+
white-space: nowrap;
|
|
725
|
+
color: var(--md-text-muted);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
.upload-remove-btn {
|
|
729
|
+
display: inline-flex;
|
|
730
|
+
align-items: center;
|
|
731
|
+
justify-content: center;
|
|
732
|
+
width: 1.25rem;
|
|
733
|
+
height: 1.25rem;
|
|
734
|
+
margin-left: auto;
|
|
735
|
+
border: none;
|
|
736
|
+
background: transparent;
|
|
737
|
+
color: var(--md-text-muted);
|
|
738
|
+
font-size: 0.85rem;
|
|
739
|
+
line-height: 1;
|
|
740
|
+
cursor: pointer;
|
|
741
|
+
border-radius: 50%;
|
|
742
|
+
transition:
|
|
743
|
+
color 150ms ease,
|
|
744
|
+
background 150ms ease;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.upload-remove-btn:hover {
|
|
748
|
+
color: var(--md-color-error);
|
|
749
|
+
background: var(--md-bg-hover);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
.upload-remove-btn:focus-visible {
|
|
753
|
+
outline: 2px solid var(--md-accent);
|
|
754
|
+
outline-offset: 1px;
|
|
755
|
+
}
|
|
756
|
+
|
|
683
757
|
/* ── Resizable editor ──────────────────────────────────────────────── */
|
|
684
758
|
/* resize attribute mirrors the CSS resize property: vertical | horizontal | both */
|
|
685
759
|
:host([resize='vertical']) .editor {
|
|
@@ -1024,6 +1098,13 @@ var coreMarkdownStyles = import_markdown_body.css.replace(/@layer\s+components\s
|
|
|
1024
1098
|
var markdownBodySheet = import_el_base3.css`
|
|
1025
1099
|
${coreMarkdownStyles}
|
|
1026
1100
|
`;
|
|
1101
|
+
function formatFileSize(bytes) {
|
|
1102
|
+
if (bytes < 1024)
|
|
1103
|
+
return `${bytes} B`;
|
|
1104
|
+
if (bytes < 1024 * 1024)
|
|
1105
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1106
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1107
|
+
}
|
|
1027
1108
|
|
|
1028
1109
|
class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
1029
1110
|
static formAssociated = true;
|
|
@@ -1041,7 +1122,8 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1041
1122
|
debounce: { type: Number, reflect: true, default: 300 },
|
|
1042
1123
|
katexCssUrl: { type: String, reflect: true, attribute: "katex-css-url" },
|
|
1043
1124
|
mermaidSrc: { type: String, reflect: true, attribute: "mermaid-src" },
|
|
1044
|
-
resize: { type: String, reflect: true, default: "none" }
|
|
1125
|
+
resize: { type: String, reflect: true, default: "none" },
|
|
1126
|
+
noPreview: { type: Boolean, reflect: true, attribute: "no-preview" }
|
|
1045
1127
|
};
|
|
1046
1128
|
#internals;
|
|
1047
1129
|
#initialized = false;
|
|
@@ -1069,6 +1151,7 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1069
1151
|
#lastRenderedSource = null;
|
|
1070
1152
|
#katexCssInjected = false;
|
|
1071
1153
|
#uploadIdCounter = 0;
|
|
1154
|
+
#attachedFiles = [];
|
|
1072
1155
|
constructor() {
|
|
1073
1156
|
super();
|
|
1074
1157
|
this.#internals = this.attachInternals();
|
|
@@ -1132,15 +1215,28 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1132
1215
|
this.#renderPreview(ta.value);
|
|
1133
1216
|
}
|
|
1134
1217
|
}
|
|
1218
|
+
const noPreview = !!this.noPreview;
|
|
1219
|
+
const toolbar = this.shadowRoot.querySelector(".toolbar");
|
|
1220
|
+
if (noPreview) {
|
|
1221
|
+
toolbar?.setAttribute("hidden", "");
|
|
1222
|
+
if (this.#activeTab === "preview") {
|
|
1223
|
+
this.#activeTab = "write";
|
|
1224
|
+
this.#writeArea?.removeAttribute("hidden");
|
|
1225
|
+
this.#previewBody?.setAttribute("hidden", "");
|
|
1226
|
+
}
|
|
1227
|
+
} else {
|
|
1228
|
+
toolbar?.removeAttribute("hidden");
|
|
1229
|
+
}
|
|
1135
1230
|
this.#updateStatusBarNow();
|
|
1136
1231
|
}
|
|
1137
1232
|
render() {
|
|
1138
1233
|
const ph = this.placeholder ?? "Write markdown…";
|
|
1139
1234
|
const disabled = !!this.disabled;
|
|
1140
1235
|
const readonly = !!this.readonly;
|
|
1236
|
+
const noPreview = !!this.noPreview;
|
|
1141
1237
|
return `
|
|
1142
1238
|
<div class="editor">
|
|
1143
|
-
<div class="toolbar" role="tablist" aria-label="Editor mode">
|
|
1239
|
+
<div class="toolbar" role="tablist" aria-label="Editor mode" ${noPreview ? "hidden" : ""}>
|
|
1144
1240
|
<button
|
|
1145
1241
|
class="tab-btn"
|
|
1146
1242
|
id="tab-write"
|
|
@@ -1188,10 +1284,20 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1188
1284
|
></div>
|
|
1189
1285
|
|
|
1190
1286
|
<div class="status-bar">
|
|
1191
|
-
<
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1287
|
+
<slot name="bottom">
|
|
1288
|
+
<div class="status-bar-start">
|
|
1289
|
+
<slot name="bottom-start">
|
|
1290
|
+
<button class="attach-btn" type="button" aria-label="Attach files" ${disabled || readonly ? "disabled" : ""}>
|
|
1291
|
+
📎 Attach files
|
|
1292
|
+
</button>
|
|
1293
|
+
</slot>
|
|
1294
|
+
</div>
|
|
1295
|
+
<div class="status-bar-end">
|
|
1296
|
+
<slot name="bottom-end">
|
|
1297
|
+
<span class="status-bar-count" aria-live="polite"></span>
|
|
1298
|
+
</slot>
|
|
1299
|
+
</div>
|
|
1300
|
+
</slot>
|
|
1195
1301
|
<input
|
|
1196
1302
|
type="file"
|
|
1197
1303
|
class="file-input"
|
|
@@ -1242,7 +1348,7 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1242
1348
|
if (e.defaultPrevented)
|
|
1243
1349
|
return;
|
|
1244
1350
|
}
|
|
1245
|
-
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === "P") {
|
|
1351
|
+
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === "P" && !this.noPreview) {
|
|
1246
1352
|
e.preventDefault();
|
|
1247
1353
|
this.#switchTab(this.#activeTab === "write" ? "preview" : "write");
|
|
1248
1354
|
return;
|
|
@@ -1367,6 +1473,8 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1367
1473
|
#switchTab(tab) {
|
|
1368
1474
|
if (tab === this.#activeTab)
|
|
1369
1475
|
return;
|
|
1476
|
+
if (tab === "preview" && this.noPreview)
|
|
1477
|
+
return;
|
|
1370
1478
|
this.#activeTab = tab;
|
|
1371
1479
|
const writeBtns = this.shadowRoot.querySelectorAll(".tab-btn");
|
|
1372
1480
|
writeBtns.forEach((btn) => {
|
|
@@ -1476,15 +1584,28 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1476
1584
|
}, ms);
|
|
1477
1585
|
}
|
|
1478
1586
|
#syncFormValue() {
|
|
1479
|
-
this.#
|
|
1587
|
+
const text = this.#textarea?.value ?? "";
|
|
1588
|
+
if (this.#attachedFiles.length === 0) {
|
|
1589
|
+
this.#internals?.setFormValue(text);
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
const name = this.name || "markdown";
|
|
1593
|
+
const fd = new FormData;
|
|
1594
|
+
fd.append(name, text);
|
|
1595
|
+
for (const f of this.#attachedFiles) {
|
|
1596
|
+
fd.append(`${name}_files`, f, f.name);
|
|
1597
|
+
}
|
|
1598
|
+
this.#internals?.setFormValue(fd);
|
|
1480
1599
|
}
|
|
1481
1600
|
#startUpload(file) {
|
|
1482
1601
|
this.emit("upload-start", { file });
|
|
1483
1602
|
const id = `upload-${++this.#uploadIdCounter}`;
|
|
1484
1603
|
const uploadUrl = this.uploadUrl;
|
|
1485
1604
|
if (!uploadUrl) {
|
|
1486
|
-
this.
|
|
1487
|
-
this.#
|
|
1605
|
+
this.#attachedFiles.push(file);
|
|
1606
|
+
this.#addAttachedRow(file, this.#attachedFiles.length - 1, id);
|
|
1607
|
+
this.#syncFormValue();
|
|
1608
|
+
this.emit("upload-done", { file, url: "", markdown: "" });
|
|
1488
1609
|
return;
|
|
1489
1610
|
}
|
|
1490
1611
|
this.#addProgressRow(id, file.name);
|
|
@@ -1539,6 +1660,22 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1539
1660
|
this.#uploadList.appendChild(row);
|
|
1540
1661
|
setTimeout(() => row.remove(), 4000);
|
|
1541
1662
|
}
|
|
1663
|
+
#addAttachedRow(file, index, id) {
|
|
1664
|
+
if (!this.#uploadList)
|
|
1665
|
+
return;
|
|
1666
|
+
const row = document.createElement("div");
|
|
1667
|
+
row.className = "upload-attached-row";
|
|
1668
|
+
row.id = id;
|
|
1669
|
+
row.innerHTML = `
|
|
1670
|
+
<span class="upload-filename">${escapeHtmlStr(file.name)}</span>
|
|
1671
|
+
<span class="upload-attached-size">${formatFileSize(file.size)}</span>
|
|
1672
|
+
<button type="button" class="upload-remove-btn" data-attach-index="${index}" aria-label="Remove ${escapeHtmlStr(file.name)}">×</button>
|
|
1673
|
+
`;
|
|
1674
|
+
row.querySelector(".upload-remove-btn").addEventListener("click", () => {
|
|
1675
|
+
this.removeFile(index);
|
|
1676
|
+
});
|
|
1677
|
+
this.#uploadList.appendChild(row);
|
|
1678
|
+
}
|
|
1542
1679
|
#handleAutocompleteInput() {
|
|
1543
1680
|
const ta = this.#textarea;
|
|
1544
1681
|
if (!ta)
|
|
@@ -1744,6 +1881,25 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1744
1881
|
this.#acSelectedIndex = list.length > 0 ? 0 : -1;
|
|
1745
1882
|
this.#updateDropdown();
|
|
1746
1883
|
}
|
|
1884
|
+
getFiles() {
|
|
1885
|
+
return [...this.#attachedFiles];
|
|
1886
|
+
}
|
|
1887
|
+
removeFile(index) {
|
|
1888
|
+
if (index < 0 || index >= this.#attachedFiles.length)
|
|
1889
|
+
return;
|
|
1890
|
+
this.#attachedFiles.splice(index, 1);
|
|
1891
|
+
this.#rebuildAttachedRows();
|
|
1892
|
+
this.#syncFormValue();
|
|
1893
|
+
}
|
|
1894
|
+
#rebuildAttachedRows() {
|
|
1895
|
+
if (!this.#uploadList)
|
|
1896
|
+
return;
|
|
1897
|
+
this.#uploadList.querySelectorAll(".upload-attached-row").forEach((r) => r.remove());
|
|
1898
|
+
this.#attachedFiles.forEach((file, i) => {
|
|
1899
|
+
const id = `upload-${++this.#uploadIdCounter}`;
|
|
1900
|
+
this.#addAttachedRow(file, i, id);
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1747
1903
|
}
|
|
1748
1904
|
function escapeHtmlStr(s) {
|
|
1749
1905
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -1774,5 +1930,5 @@ var MarkdownInputHook = {
|
|
|
1774
1930
|
}
|
|
1775
1931
|
};
|
|
1776
1932
|
|
|
1777
|
-
//# debugId=
|
|
1933
|
+
//# debugId=FC4F4846FEEC843664756E2164756E21
|
|
1778
1934
|
//# sourceMappingURL=index.js.map
|