@duskmoon-dev/el-markdown-input 1.1.2 → 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 CHANGED
@@ -521,6 +521,31 @@ var elementStyles = import_el_base.css`
521
521
  gap: 0.5rem;
522
522
  }
523
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
+
524
549
  .attach-btn {
525
550
  display: inline-flex;
526
551
  align-items: center;
@@ -555,7 +580,6 @@ var elementStyles = import_el_base.css`
555
580
  }
556
581
 
557
582
  .status-bar-count {
558
- margin-left: auto;
559
583
  white-space: nowrap;
560
584
  }
561
585
 
@@ -684,6 +708,52 @@ var elementStyles = import_el_base.css`
684
708
  white-space: nowrap;
685
709
  }
686
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
+
687
757
  /* ── Resizable editor ──────────────────────────────────────────────── */
688
758
  /* resize attribute mirrors the CSS resize property: vertical | horizontal | both */
689
759
  :host([resize='vertical']) .editor {
@@ -1028,6 +1098,13 @@ var coreMarkdownStyles = import_markdown_body.css.replace(/@layer\s+components\s
1028
1098
  var markdownBodySheet = import_el_base3.css`
1029
1099
  ${coreMarkdownStyles}
1030
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
+ }
1031
1108
 
1032
1109
  class ElDmMarkdownInput extends import_el_base2.BaseElement {
1033
1110
  static formAssociated = true;
@@ -1074,6 +1151,7 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
1074
1151
  #lastRenderedSource = null;
1075
1152
  #katexCssInjected = false;
1076
1153
  #uploadIdCounter = 0;
1154
+ #attachedFiles = [];
1077
1155
  constructor() {
1078
1156
  super();
1079
1157
  this.#internals = this.attachInternals();
@@ -1206,10 +1284,20 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
1206
1284
  ></div>
1207
1285
 
1208
1286
  <div class="status-bar">
1209
- <button class="attach-btn" type="button" aria-label="Attach files" ${disabled || readonly ? "disabled" : ""}>
1210
- &#128206; Attach files
1211
- </button>
1212
- <span class="status-bar-count" aria-live="polite"></span>
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
+ &#128206; 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>
1213
1301
  <input
1214
1302
  type="file"
1215
1303
  class="file-input"
@@ -1496,15 +1584,28 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
1496
1584
  }, ms);
1497
1585
  }
1498
1586
  #syncFormValue() {
1499
- this.#internals?.setFormValue(this.#textarea?.value ?? "");
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);
1500
1599
  }
1501
1600
  #startUpload(file) {
1502
1601
  this.emit("upload-start", { file });
1503
1602
  const id = `upload-${++this.#uploadIdCounter}`;
1504
1603
  const uploadUrl = this.uploadUrl;
1505
1604
  if (!uploadUrl) {
1506
- this.emit("upload-error", { file, error: "no upload-url set" });
1507
- this.#showUploadError(file, "no upload-url set");
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: "" });
1508
1609
  return;
1509
1610
  }
1510
1611
  this.#addProgressRow(id, file.name);
@@ -1559,6 +1660,22 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
1559
1660
  this.#uploadList.appendChild(row);
1560
1661
  setTimeout(() => row.remove(), 4000);
1561
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)}">&#215;</button>
1673
+ `;
1674
+ row.querySelector(".upload-remove-btn").addEventListener("click", () => {
1675
+ this.removeFile(index);
1676
+ });
1677
+ this.#uploadList.appendChild(row);
1678
+ }
1562
1679
  #handleAutocompleteInput() {
1563
1680
  const ta = this.#textarea;
1564
1681
  if (!ta)
@@ -1764,6 +1881,25 @@ class ElDmMarkdownInput extends import_el_base2.BaseElement {
1764
1881
  this.#acSelectedIndex = list.length > 0 ? 0 : -1;
1765
1882
  this.#updateDropdown();
1766
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
+ }
1767
1903
  }
1768
1904
  function escapeHtmlStr(s) {
1769
1905
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
@@ -1794,5 +1930,5 @@ var MarkdownInputHook = {
1794
1930
  }
1795
1931
  };
1796
1932
 
1797
- //# debugId=0AA7B81A718D612564756E2164756E21
1933
+ //# debugId=FC4F4846FEEC843664756E2164756E21
1798
1934
  //# sourceMappingURL=index.js.map