@innovastudio/contentbuilder 1.5.218 → 1.5.219

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/index.d.ts CHANGED
@@ -587,6 +587,12 @@ declare class ContentBuilder {
587
587
 
588
588
  generateImage(prompt: string, callback?: () => void): void;
589
589
  openFilePicker(type?: string, callback?: () => void): void;
590
+ /** Is an asset manager configured for this type of file? */
591
+ hasFilePicker(type?: string): boolean;
592
+ /** Upload a file from the user's computer; the callback gets its URL. */
593
+ openFileUpload(type?: string, callback?: (url: string) => void): void;
594
+ /** Select and upload buttons for a URL field in a plugin's settings, in the editor's own order. Select is included only where an asset manager is configured. */
595
+ createFileButtons(type?: string, callback?: (url: string) => void): HTMLButtonElement[];
590
596
  openColorPicker(
591
597
  currentColor: string,
592
598
  callback: (color: string) => void,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@innovastudio/contentbuilder",
4
- "version": "1.5.218",
4
+ "version": "1.5.219",
5
5
  "description": "",
6
6
  "main": "public/contentbuilder/contentbuilder.esm.js",
7
7
  "types": "index.d.ts",
@@ -29563,7 +29563,7 @@ class Image$1 {
29563
29563
  <label class="label-checkbox">
29564
29564
  <input class="input-newwindow" id="__input_newwindow2" type="checkbox" /> ${util.out('Open new window')}
29565
29565
  </label>
29566
- <label class="label-checkbox" id="lblImageLinkOpenLightbox" style="${this.builder.useLightbox ? '' : 'display:none'}">
29566
+ <label class="label-checkbox mt-1" id="lblImageLinkOpenLightbox" style="${this.builder.useLightbox ? '' : 'display:none'}">
29567
29567
  <input class="input-openlightbox" id="__input_openlightbox2" type="checkbox" /> ${util.out('Open in a lightbox (for image, video or Youtube)')}
29568
29568
  </label>
29569
29569
  </div>
@@ -46273,7 +46273,16 @@ class ColorPickerKelir {
46273
46273
  }
46274
46274
 
46275
46275
  // Close the picker on scroll — it's positioned once, so scrolling detaches it.
46276
- const hideOnScroll = () => {
46276
+ //
46277
+ // The page moving under the picker is the only scroll that counts. A text
46278
+ // input scrolls its own content whenever the caret passes the edge — on
46279
+ // paste, on Delete, on Cmd+Left/Right — and that is a scroll event too,
46280
+ // which a capture listener on window receives even though it does not
46281
+ // bubble. Without this guard the picker closed while its own hex field
46282
+ // was being edited.
46283
+ const hideOnScroll = e => {
46284
+ const target = e && e.target;
46285
+ if (target && target.nodeType === 1 && popPicker.contains(target)) return;
46277
46286
  this.builder.util.hidePop(popPicker);
46278
46287
  window.removeEventListener('scroll', hideOnScroll, true);
46279
46288
  if (this.builder.win && this.builder.win !== window) this.builder.win.removeEventListener('scroll', hideOnScroll, true);
@@ -92847,6 +92856,90 @@ class ContentBuilder {
92847
92856
  openFilePicker(type, callback) {
92848
92857
  this.openAssetSelect(type, callback);
92849
92858
  }
92859
+
92860
+ /**
92861
+ * Is an asset manager reachable for this type of file? Mirrors the branches
92862
+ * openAsset() takes: either a picker page (filePicker / imageSelect / ...)
92863
+ * or the host's own onXSelectClick handler.
92864
+ */
92865
+ hasFilePicker(type) {
92866
+ if (type === 'media') return !!(this.onMediaSelectClick || this.onImageSelectClick || this.mediaSelect || this.imageSelect);
92867
+ if (type === 'video') return !!(this.onVideoSelectClick || this.videoSelect);
92868
+ if (type === 'audio') return !!(this.onAudioSelectClick || this.audioSelect);
92869
+ if (type === 'all') return !!(this.onFileSelectClick || this.fileSelect);
92870
+ return !!(this.onImageSelectClick || this.imageSelect);
92871
+ }
92872
+
92873
+ /**
92874
+ * Upload a file from the user's computer and hand its URL to `callback`.
92875
+ *
92876
+ * The per-type upload handler always exists — a builder configured without
92877
+ * one gets the data-URL fallback — so this is available whatever the host
92878
+ * set up. The URL comes back through returnUrl(), the same path the image
92879
+ * tool's upload button uses.
92880
+ */
92881
+ openFileUpload(type, callback) {
92882
+ const accept = type === 'video' ? 'video/*' : type === 'audio' ? 'audio/*' : type === 'media' ? 'image/*,video/*' : type === 'all' ? '*' : 'image/*';
92883
+ const handler = type === 'video' ? this.onVideoUpload : type === 'audio' ? this.onAudioUpload : type === 'media' ? this.onMediaUpload : type === 'all' ? this.onFileUpload : this.onImageUpload;
92884
+ if (!handler) return;
92885
+ const inpFile = document.createElement('input');
92886
+ inpFile.type = 'file';
92887
+ inpFile.accept = accept;
92888
+ inpFile.style.display = 'none';
92889
+ document.body.appendChild(inpFile);
92890
+ inpFile.addEventListener('change', async e => {
92891
+ if (!e.target.files || !e.target.files.length) {
92892
+ inpFile.remove();
92893
+ return;
92894
+ }
92895
+ this.onAssetUpload = url => {
92896
+ if (callback) callback(url);
92897
+ };
92898
+ await handler(e);
92899
+ inpFile.remove();
92900
+ });
92901
+ inpFile.click();
92902
+ }
92903
+
92904
+ /**
92905
+ * The file controls for a URL field in a plugin's settings: select from the
92906
+ * asset manager, and upload from the computer.
92907
+ *
92908
+ * Returns the buttons to append next to the input, in the order and with the
92909
+ * icons the editor's own image dialog uses — select first, upload last, and
92910
+ * select only where an asset manager is configured. A plugin appends what it
92911
+ * gets rather than deciding, so a builder without an asset manager never
92912
+ * shows a button that cannot open one.
92913
+ *
92914
+ * const [ ...buttons ] = builder.createFileButtons('media', (url) => {...});
92915
+ * row.append(input, ...buttons);
92916
+ *
92917
+ * `type` may be a function for a field whose kind follows another control
92918
+ * (a Media Type select, say) — it is then read on each click.
92919
+ */
92920
+ createFileButtons(type, callback) {
92921
+ const out = s => this.util.out(s);
92922
+ const fileType = () => typeof type === 'function' ? type() : type;
92923
+ const button = (label, icon, onClick) => {
92924
+ const btn = document.createElement('button');
92925
+ btn.type = 'button';
92926
+ btn.className = 'cbx-iconbtn';
92927
+ btn.title = label;
92928
+ btn.setAttribute('aria-label', label);
92929
+ btn.innerHTML = `<svg aria-hidden="true"><use xlink:href="#${icon}"></use></svg>`;
92930
+ btn.addEventListener('click', e => {
92931
+ e.preventDefault();
92932
+ onClick(btn);
92933
+ });
92934
+ return btn;
92935
+ };
92936
+ const buttons = [];
92937
+ if (this.hasFilePicker(fileType())) {
92938
+ buttons.push(button(out('Select'), 'icon-folder', btn => this.openFilePicker(fileType(), callback, btn)));
92939
+ }
92940
+ buttons.push(button(out('Upload'), 'icon-upload', () => this.openFileUpload(fileType(), callback)));
92941
+ return buttons;
92942
+ }
92850
92943
  openAssetSelect(targetAssetType, callback, defaultValue) {
92851
92944
  const inpUrl = document.createElement('input');
92852
92945