@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/register.js
CHANGED
|
@@ -270,6 +270,10 @@ var elementStyles = import_el_base.css`
|
|
|
270
270
|
padding: 0 0.5rem;
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
+
.toolbar[hidden] {
|
|
274
|
+
display: none;
|
|
275
|
+
}
|
|
276
|
+
|
|
273
277
|
.tab-btn {
|
|
274
278
|
padding: 0.5rem 0.875rem;
|
|
275
279
|
border: none;
|
|
@@ -508,6 +512,31 @@ var elementStyles = import_el_base.css`
|
|
|
508
512
|
gap: 0.5rem;
|
|
509
513
|
}
|
|
510
514
|
|
|
515
|
+
.status-bar-start,
|
|
516
|
+
.status-bar-end {
|
|
517
|
+
display: flex;
|
|
518
|
+
align-items: center;
|
|
519
|
+
gap: 0.5rem;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/* Allow slotted light-DOM children to inherit font and alignment */
|
|
523
|
+
.status-bar ::slotted(*),
|
|
524
|
+
.status-bar-start ::slotted(*),
|
|
525
|
+
.status-bar-end ::slotted(*) {
|
|
526
|
+
font-size: inherit;
|
|
527
|
+
font-family: inherit;
|
|
528
|
+
vertical-align: middle;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/* When slot="bottom" is used, the slotted element fills the bar */
|
|
532
|
+
.status-bar > slot[name="bottom"]::slotted(*) {
|
|
533
|
+
display: flex;
|
|
534
|
+
align-items: center;
|
|
535
|
+
justify-content: space-between;
|
|
536
|
+
flex: 1;
|
|
537
|
+
gap: 0.5rem;
|
|
538
|
+
}
|
|
539
|
+
|
|
511
540
|
.attach-btn {
|
|
512
541
|
display: inline-flex;
|
|
513
542
|
align-items: center;
|
|
@@ -542,7 +571,6 @@ var elementStyles = import_el_base.css`
|
|
|
542
571
|
}
|
|
543
572
|
|
|
544
573
|
.status-bar-count {
|
|
545
|
-
margin-left: auto;
|
|
546
574
|
white-space: nowrap;
|
|
547
575
|
}
|
|
548
576
|
|
|
@@ -671,6 +699,52 @@ var elementStyles = import_el_base.css`
|
|
|
671
699
|
white-space: nowrap;
|
|
672
700
|
}
|
|
673
701
|
|
|
702
|
+
/* ── Attached files (local form mode) ────────────────────────────── */
|
|
703
|
+
|
|
704
|
+
.upload-attached-row {
|
|
705
|
+
display: flex;
|
|
706
|
+
align-items: center;
|
|
707
|
+
gap: 0.5rem;
|
|
708
|
+
padding: 0.375rem 0.75rem;
|
|
709
|
+
border-top: 1px solid var(--md-border);
|
|
710
|
+
font-size: 0.75rem;
|
|
711
|
+
color: var(--md-text-muted);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
.upload-attached-size {
|
|
715
|
+
white-space: nowrap;
|
|
716
|
+
color: var(--md-text-muted);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
.upload-remove-btn {
|
|
720
|
+
display: inline-flex;
|
|
721
|
+
align-items: center;
|
|
722
|
+
justify-content: center;
|
|
723
|
+
width: 1.25rem;
|
|
724
|
+
height: 1.25rem;
|
|
725
|
+
margin-left: auto;
|
|
726
|
+
border: none;
|
|
727
|
+
background: transparent;
|
|
728
|
+
color: var(--md-text-muted);
|
|
729
|
+
font-size: 0.85rem;
|
|
730
|
+
line-height: 1;
|
|
731
|
+
cursor: pointer;
|
|
732
|
+
border-radius: 50%;
|
|
733
|
+
transition:
|
|
734
|
+
color 150ms ease,
|
|
735
|
+
background 150ms ease;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
.upload-remove-btn:hover {
|
|
739
|
+
color: var(--md-color-error);
|
|
740
|
+
background: var(--md-bg-hover);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
.upload-remove-btn:focus-visible {
|
|
744
|
+
outline: 2px solid var(--md-accent);
|
|
745
|
+
outline-offset: 1px;
|
|
746
|
+
}
|
|
747
|
+
|
|
674
748
|
/* ── Resizable editor ──────────────────────────────────────────────── */
|
|
675
749
|
/* resize attribute mirrors the CSS resize property: vertical | horizontal | both */
|
|
676
750
|
:host([resize='vertical']) .editor {
|
|
@@ -1015,6 +1089,13 @@ var coreMarkdownStyles = import_markdown_body.css.replace(/@layer\s+components\s
|
|
|
1015
1089
|
var markdownBodySheet = import_el_base3.css`
|
|
1016
1090
|
${coreMarkdownStyles}
|
|
1017
1091
|
`;
|
|
1092
|
+
function formatFileSize(bytes) {
|
|
1093
|
+
if (bytes < 1024)
|
|
1094
|
+
return `${bytes} B`;
|
|
1095
|
+
if (bytes < 1024 * 1024)
|
|
1096
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1097
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1098
|
+
}
|
|
1018
1099
|
|
|
1019
1100
|
class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
1020
1101
|
static formAssociated = true;
|
|
@@ -1032,7 +1113,8 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1032
1113
|
debounce: { type: Number, reflect: true, default: 300 },
|
|
1033
1114
|
katexCssUrl: { type: String, reflect: true, attribute: "katex-css-url" },
|
|
1034
1115
|
mermaidSrc: { type: String, reflect: true, attribute: "mermaid-src" },
|
|
1035
|
-
resize: { type: String, reflect: true, default: "none" }
|
|
1116
|
+
resize: { type: String, reflect: true, default: "none" },
|
|
1117
|
+
noPreview: { type: Boolean, reflect: true, attribute: "no-preview" }
|
|
1036
1118
|
};
|
|
1037
1119
|
#internals;
|
|
1038
1120
|
#initialized = false;
|
|
@@ -1060,6 +1142,7 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1060
1142
|
#lastRenderedSource = null;
|
|
1061
1143
|
#katexCssInjected = false;
|
|
1062
1144
|
#uploadIdCounter = 0;
|
|
1145
|
+
#attachedFiles = [];
|
|
1063
1146
|
constructor() {
|
|
1064
1147
|
super();
|
|
1065
1148
|
this.#internals = this.attachInternals();
|
|
@@ -1123,15 +1206,28 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1123
1206
|
this.#renderPreview(ta.value);
|
|
1124
1207
|
}
|
|
1125
1208
|
}
|
|
1209
|
+
const noPreview = !!this.noPreview;
|
|
1210
|
+
const toolbar = this.shadowRoot.querySelector(".toolbar");
|
|
1211
|
+
if (noPreview) {
|
|
1212
|
+
toolbar?.setAttribute("hidden", "");
|
|
1213
|
+
if (this.#activeTab === "preview") {
|
|
1214
|
+
this.#activeTab = "write";
|
|
1215
|
+
this.#writeArea?.removeAttribute("hidden");
|
|
1216
|
+
this.#previewBody?.setAttribute("hidden", "");
|
|
1217
|
+
}
|
|
1218
|
+
} else {
|
|
1219
|
+
toolbar?.removeAttribute("hidden");
|
|
1220
|
+
}
|
|
1126
1221
|
this.#updateStatusBarNow();
|
|
1127
1222
|
}
|
|
1128
1223
|
render() {
|
|
1129
1224
|
const ph = this.placeholder ?? "Write markdown…";
|
|
1130
1225
|
const disabled = !!this.disabled;
|
|
1131
1226
|
const readonly = !!this.readonly;
|
|
1227
|
+
const noPreview = !!this.noPreview;
|
|
1132
1228
|
return `
|
|
1133
1229
|
<div class="editor">
|
|
1134
|
-
<div class="toolbar" role="tablist" aria-label="Editor mode">
|
|
1230
|
+
<div class="toolbar" role="tablist" aria-label="Editor mode" ${noPreview ? "hidden" : ""}>
|
|
1135
1231
|
<button
|
|
1136
1232
|
class="tab-btn"
|
|
1137
1233
|
id="tab-write"
|
|
@@ -1179,10 +1275,20 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1179
1275
|
></div>
|
|
1180
1276
|
|
|
1181
1277
|
<div class="status-bar">
|
|
1182
|
-
<
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1278
|
+
<slot name="bottom">
|
|
1279
|
+
<div class="status-bar-start">
|
|
1280
|
+
<slot name="bottom-start">
|
|
1281
|
+
<button class="attach-btn" type="button" aria-label="Attach files" ${disabled || readonly ? "disabled" : ""}>
|
|
1282
|
+
📎 Attach files
|
|
1283
|
+
</button>
|
|
1284
|
+
</slot>
|
|
1285
|
+
</div>
|
|
1286
|
+
<div class="status-bar-end">
|
|
1287
|
+
<slot name="bottom-end">
|
|
1288
|
+
<span class="status-bar-count" aria-live="polite"></span>
|
|
1289
|
+
</slot>
|
|
1290
|
+
</div>
|
|
1291
|
+
</slot>
|
|
1186
1292
|
<input
|
|
1187
1293
|
type="file"
|
|
1188
1294
|
class="file-input"
|
|
@@ -1233,7 +1339,7 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1233
1339
|
if (e.defaultPrevented)
|
|
1234
1340
|
return;
|
|
1235
1341
|
}
|
|
1236
|
-
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === "P") {
|
|
1342
|
+
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === "P" && !this.noPreview) {
|
|
1237
1343
|
e.preventDefault();
|
|
1238
1344
|
this.#switchTab(this.#activeTab === "write" ? "preview" : "write");
|
|
1239
1345
|
return;
|
|
@@ -1358,6 +1464,8 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1358
1464
|
#switchTab(tab) {
|
|
1359
1465
|
if (tab === this.#activeTab)
|
|
1360
1466
|
return;
|
|
1467
|
+
if (tab === "preview" && this.noPreview)
|
|
1468
|
+
return;
|
|
1361
1469
|
this.#activeTab = tab;
|
|
1362
1470
|
const writeBtns = this.shadowRoot.querySelectorAll(".tab-btn");
|
|
1363
1471
|
writeBtns.forEach((btn) => {
|
|
@@ -1467,15 +1575,28 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1467
1575
|
}, ms);
|
|
1468
1576
|
}
|
|
1469
1577
|
#syncFormValue() {
|
|
1470
|
-
this.#
|
|
1578
|
+
const text = this.#textarea?.value ?? "";
|
|
1579
|
+
if (this.#attachedFiles.length === 0) {
|
|
1580
|
+
this.#internals?.setFormValue(text);
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
const name = this.name || "markdown";
|
|
1584
|
+
const fd = new FormData;
|
|
1585
|
+
fd.append(name, text);
|
|
1586
|
+
for (const f of this.#attachedFiles) {
|
|
1587
|
+
fd.append(`${name}_files`, f, f.name);
|
|
1588
|
+
}
|
|
1589
|
+
this.#internals?.setFormValue(fd);
|
|
1471
1590
|
}
|
|
1472
1591
|
#startUpload(file) {
|
|
1473
1592
|
this.emit("upload-start", { file });
|
|
1474
1593
|
const id = `upload-${++this.#uploadIdCounter}`;
|
|
1475
1594
|
const uploadUrl = this.uploadUrl;
|
|
1476
1595
|
if (!uploadUrl) {
|
|
1477
|
-
this.
|
|
1478
|
-
this.#
|
|
1596
|
+
this.#attachedFiles.push(file);
|
|
1597
|
+
this.#addAttachedRow(file, this.#attachedFiles.length - 1, id);
|
|
1598
|
+
this.#syncFormValue();
|
|
1599
|
+
this.emit("upload-done", { file, url: "", markdown: "" });
|
|
1479
1600
|
return;
|
|
1480
1601
|
}
|
|
1481
1602
|
this.#addProgressRow(id, file.name);
|
|
@@ -1530,6 +1651,22 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1530
1651
|
this.#uploadList.appendChild(row);
|
|
1531
1652
|
setTimeout(() => row.remove(), 4000);
|
|
1532
1653
|
}
|
|
1654
|
+
#addAttachedRow(file, index, id) {
|
|
1655
|
+
if (!this.#uploadList)
|
|
1656
|
+
return;
|
|
1657
|
+
const row = document.createElement("div");
|
|
1658
|
+
row.className = "upload-attached-row";
|
|
1659
|
+
row.id = id;
|
|
1660
|
+
row.innerHTML = `
|
|
1661
|
+
<span class="upload-filename">${escapeHtmlStr(file.name)}</span>
|
|
1662
|
+
<span class="upload-attached-size">${formatFileSize(file.size)}</span>
|
|
1663
|
+
<button type="button" class="upload-remove-btn" data-attach-index="${index}" aria-label="Remove ${escapeHtmlStr(file.name)}">×</button>
|
|
1664
|
+
`;
|
|
1665
|
+
row.querySelector(".upload-remove-btn").addEventListener("click", () => {
|
|
1666
|
+
this.removeFile(index);
|
|
1667
|
+
});
|
|
1668
|
+
this.#uploadList.appendChild(row);
|
|
1669
|
+
}
|
|
1533
1670
|
#handleAutocompleteInput() {
|
|
1534
1671
|
const ta = this.#textarea;
|
|
1535
1672
|
if (!ta)
|
|
@@ -1735,6 +1872,25 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
|
|
|
1735
1872
|
this.#acSelectedIndex = list.length > 0 ? 0 : -1;
|
|
1736
1873
|
this.#updateDropdown();
|
|
1737
1874
|
}
|
|
1875
|
+
getFiles() {
|
|
1876
|
+
return [...this.#attachedFiles];
|
|
1877
|
+
}
|
|
1878
|
+
removeFile(index) {
|
|
1879
|
+
if (index < 0 || index >= this.#attachedFiles.length)
|
|
1880
|
+
return;
|
|
1881
|
+
this.#attachedFiles.splice(index, 1);
|
|
1882
|
+
this.#rebuildAttachedRows();
|
|
1883
|
+
this.#syncFormValue();
|
|
1884
|
+
}
|
|
1885
|
+
#rebuildAttachedRows() {
|
|
1886
|
+
if (!this.#uploadList)
|
|
1887
|
+
return;
|
|
1888
|
+
this.#uploadList.querySelectorAll(".upload-attached-row").forEach((r) => r.remove());
|
|
1889
|
+
this.#attachedFiles.forEach((file, i) => {
|
|
1890
|
+
const id = `upload-${++this.#uploadIdCounter}`;
|
|
1891
|
+
this.#addAttachedRow(file, i, id);
|
|
1892
|
+
});
|
|
1893
|
+
}
|
|
1738
1894
|
}
|
|
1739
1895
|
function escapeHtmlStr(s) {
|
|
1740
1896
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -1745,5 +1901,5 @@ if (!customElements.get("el-dm-markdown-input")) {
|
|
|
1745
1901
|
customElements.define("el-dm-markdown-input", ElDmMarkdownInput);
|
|
1746
1902
|
}
|
|
1747
1903
|
|
|
1748
|
-
//# debugId=
|
|
1904
|
+
//# debugId=5E28FBCFFD0322DF64756E2164756E21
|
|
1749
1905
|
//# sourceMappingURL=register.js.map
|