@innovastudio/contentbox 1.6.135 → 1.6.137

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
@@ -300,8 +300,10 @@ interface ContentBoxOptions {
300
300
  commandInfoCanvasMode?: any[];
301
301
  onStartRequest?: () => void;
302
302
 
303
- imageModel?: string;
304
303
  defaultImageGenerationProvider?: string;
304
+ imageModel?: string;
305
+ imageSize?: string;
306
+ imageGenerationModels?: any[];
305
307
 
306
308
  //-- Asset Manager
307
309
  listFilesUrl?: string;
@@ -378,6 +380,9 @@ declare class ContentBox {
378
380
  constructor(options: ContentBoxOptions);
379
381
 
380
382
  boxImage(url: string, err?: string): void;
383
+ selectAsset(url: string): void;
384
+ hideModal(modal?: HTMLElement): void;
385
+ closeAsset(): void;
381
386
  returnUrl(s: string): void;
382
387
  htmlCheck(): void;
383
388
  loadHtml(html: string): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@innovastudio/contentbox",
3
3
  "type": "module",
4
- "version": "1.6.135",
4
+ "version": "1.6.137",
5
5
  "description": "",
6
6
  "main": "public/contentbox/contentbox.esm.js",
7
7
  "types": "index.d.ts",
@@ -59,7 +59,7 @@
59
59
  "ws": "^8.13.0"
60
60
  },
61
61
  "dependencies": {
62
- "@innovastudio/contentbuilder": "^1.5.125",
62
+ "@innovastudio/contentbuilder": "^1.5.130",
63
63
  "js-beautify": "^1.14.0",
64
64
  "sortablejs": "^1.15.2"
65
65
  }
@@ -72087,6 +72087,11 @@ class DragDropImageUploader {
72087
72087
  }
72088
72088
  _onDragOver(e) {
72089
72089
  e.preventDefault();
72090
+
72091
+ // Only allow highlighting when dragging files (not snippets, etc.)
72092
+ if (!e.dataTransfer.types.includes('Files')) {
72093
+ return;
72094
+ }
72090
72095
  const img = this._getImageUnderCursor(e);
72091
72096
  if (img) {
72092
72097
  if (this.targetImage && this.targetImage !== img) {
@@ -73230,6 +73235,8 @@ class Image$1 {
73230
73235
  const util = this.builder.util;
73231
73236
  let isModule = dom.parentsHasAttribute(elm, 'data-html');
73232
73237
  if (isModule) {
73238
+ // Now this block is not used anymore, since direct image embed/change is disabled for modules (e.g. slider). See click(e) line 1577
73239
+
73233
73240
  if (this.imageTool) this.imageTool.style.display = '';
73234
73241
 
73235
73242
  // Extra: make image[data-image-embed] clickable/editable
@@ -73402,6 +73409,12 @@ class Image$1 {
73402
73409
  const util = this.builder.util;
73403
73410
  const dom = this.builder.dom;
73404
73411
  let elm = e.target;
73412
+ if (elm.closest('[data-html]')) {
73413
+ // Do not show imageTool if the image is inside a code block
73414
+ this.builder.activeImage = null;
73415
+ this.hideImageTool();
73416
+ return;
73417
+ }
73405
73418
 
73406
73419
  //Image
73407
73420
  if (elm.tagName.toLowerCase() === 'img') {
@@ -78586,19 +78599,19 @@ class RowTool {
78586
78599
  if (!rowtool) {
78587
78600
  let html = `<div class="is-tool is-row-tool" style="${!this.builder.rowTool && this.builder.rowTool !== '' ? 'display:none;' : ''}">
78588
78601
  <div title="${util.out('Move')}" role="button" tabindex="-1" class="row-handle" style="${this.builder.rowHandle ? '' : 'display:none;'}width:100%;cursor:move;text-align:center;"><svg class="is-icon-flex"><use xlink:href="#ion-move"></use></svg></div>
78589
- <button type="button" tabindex="-1" title="${util.out('More')}" class="row-more"><svg class="is-icon-flex" style="color:#fff;width:15px;height:15px;"><use xlink:href="#icon-dots2"></use></svg></button>
78602
+ <button type="button" tabindex="-1" title="${util.out('More')}" class="row-more"><svg class="is-icon-flex" style="width:15px;height:15px;"><use xlink:href="#icon-dots2"></use></svg></button>
78590
78603
  <button type="button" tabindex="-1" title="${util.out('Grid Editor')}" class="row-grideditor"><svg class="is-icon-flex"><use xlink:href="#ion-grid"></use></svg></button>
78591
- <button type="button" tabindex="-1" title="${util.out('Delete')}" class="row-remove"><svg class="is-icon-flex" style="color:#fff;width:15px;height:15px;"><use xlink:href="#icon-trash2"></use></svg></button>
78604
+ <button type="button" tabindex="-1" title="${util.out('Delete')}" class="row-remove"><svg class="is-icon-flex" style="width:15px;height:15px;"><use xlink:href="#icon-trash2"></use></svg></button>
78592
78605
  </div>
78593
78606
  <div class="is-tool is-col-tool">
78594
78607
  <button type="button" tabindex="-1" title="${util.out('Add')}" class="cell-add">
78595
- <svg class="is-icon-flex" style="color:#fff;width:15px;height:15px;"><use xlink:href="#icon-plus"></use></svg>
78608
+ <svg class="is-icon-flex" style="width:15px;height:15px;"><use xlink:href="#icon-plus"></use></svg>
78596
78609
  </button>
78597
78610
  <button type="button" tabindex="-1" title="${util.out('More')}" class="cell-more">
78598
- <svg class="is-icon-flex" style="color:#fff;width:15px;height:15px;"><use xlink:href="#icon-dots2"></use></svg>
78611
+ <svg class="is-icon-flex" style="width:15px;height:15px;"><use xlink:href="#icon-dots2"></use></svg>
78599
78612
  </button>
78600
78613
  <button type="button" tabindex="-1" title="${util.out('Delete')}" class="cell-remove">
78601
- <svg class="is-icon-flex" style="color:#fff;width:15px;height:15px;"><use xlink:href="#icon-trash2"></use></svg>
78614
+ <svg class="is-icon-flex" style="width:15px;height:15px;"><use xlink:href="#icon-trash2"></use></svg>
78602
78615
  </button>
78603
78616
  </div>
78604
78617
  `;
@@ -88300,7 +88313,7 @@ class Preferences {
88300
88313
  </select>
88301
88314
  </label>
88302
88315
 
88303
- ${this.builder.themes ? `
88316
+ ${this.builder.themes && this.builder.themes.length > 0 ? `
88304
88317
  <label style="${this.builder.isTouchSupport ? 'display:none;' : 'display:block;'}margin-top:10px;margin-bottom:5px;">
88305
88318
  ${util.out('Theme')}:&nbsp;
88306
88319
  ${htmlThemes}
@@ -109717,6 +109730,152 @@ class Dictation {
109717
109730
  };
109718
109731
  this.opts = Object.assign(this, defaults, opts);
109719
109732
  this.builder = builder;
109733
+ this.imageModels = [{
109734
+ id: 'fal-ai/nano-banana',
109735
+ // ok
109736
+ label: 'Nano Banana',
109737
+ sizes: [],
109738
+ // no size options
109739
+ output_format: 'jpeg'
109740
+ }, {
109741
+ id: 'fal-ai/imagen4/preview/fast',
109742
+ // ok
109743
+ label: 'Imagen 4 Preview Fast',
109744
+ sizes: ['1:1', '4:3', '16:9', '3:4', '9:16']
109745
+ }, {
109746
+ id: 'fal-ai/imagen4/preview',
109747
+ // ok
109748
+ label: 'Imagen 4 Preview',
109749
+ sizes: ['1:1', '4:3', '16:9', '3:4', '9:16']
109750
+ }, {
109751
+ id: 'fal-ai/imagen4/preview/ultra',
109752
+ // ok
109753
+ label: 'Imagen 4 Preview Ultra',
109754
+ sizes: ['1:1', '4:3', '16:9', '3:4', '9:16']
109755
+ }, {
109756
+ id: 'fal-ai/hidream-i1-fast',
109757
+ // ok
109758
+ label: 'HiDream-I1 Fast',
109759
+ // sizes: => uses defaultSizes
109760
+ output_format: 'jpeg'
109761
+ }, {
109762
+ id: 'fal-ai/hidream-i1-dev',
109763
+ // ok
109764
+ label: 'HiDream-I1 Dev',
109765
+ output_format: 'jpeg'
109766
+ }, {
109767
+ id: 'fal-ai/hidream-i1-full',
109768
+ // ok
109769
+ label: 'HiDream-I1 Full',
109770
+ output_format: 'jpeg'
109771
+ }, {
109772
+ id: 'bria/text-to-image/3.2',
109773
+ // ok
109774
+ label: 'Bria (3.2)',
109775
+ sizes: ['1:1', '3:2', '4:3', '5:4', '16:9', '2:3', '3:4', '4:5', '9:16']
109776
+ }, {
109777
+ id: 'fal-ai/recraft/v3/text-to-image',
109778
+ // ok
109779
+ label: 'Recraft V3'
109780
+ }, {
109781
+ id: 'fal-ai/flux-1/schnell',
109782
+ // ok
109783
+ label: 'FLUX.1 Schnell',
109784
+ output_format: 'jpeg'
109785
+ }, {
109786
+ id: 'fal-ai/flux/krea',
109787
+ // ok
109788
+ label: 'FLUX.1 Krea',
109789
+ output_format: 'jpeg'
109790
+ }, {
109791
+ id: 'fal-ai/flux-krea-lora',
109792
+ // ok
109793
+ label: 'FLUX.1 Krea Lora',
109794
+ output_format: 'jpeg'
109795
+ }, {
109796
+ id: 'fal-ai/flux-kontext-lora/text-to-image',
109797
+ // ok
109798
+ label: 'FLUX Kontext Lora',
109799
+ output_format: 'jpeg'
109800
+ }, {
109801
+ id: 'fal-ai/flux-pro/kontext/text-to-image',
109802
+ // ok
109803
+ label: 'FLUX.1 Kontext Pro',
109804
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16', '9:21'],
109805
+ size_param: 'aspect_ratio',
109806
+ output_format: 'jpeg'
109807
+ }, {
109808
+ id: 'fal-ai/flux-pro/kontext/max/text-to-image',
109809
+ // ok
109810
+ label: 'FLUX.1 Kontext Max',
109811
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16', '9:21'],
109812
+ size_param: 'aspect_ratio',
109813
+ output_format: 'jpeg'
109814
+ }, {
109815
+ id: 'fal-ai/flux-pro/v1.1-ultra',
109816
+ // ok
109817
+ label: 'FLUX 1.1 Pro Ultra',
109818
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16', '9:21'],
109819
+ size_param: 'aspect_ratio',
109820
+ output_format: 'jpeg'
109821
+ }, {
109822
+ id: 'fal-ai/bytedance/seedream/v4/text-to-image',
109823
+ // ok
109824
+ label: 'ByteDance Seedream 4.0'
109825
+ }, {
109826
+ id: 'fal-ai/wan/v2.2-5b/text-to-image',
109827
+ // ok
109828
+ label: 'Wan 2.2 5B',
109829
+ output_format: 'jpeg',
109830
+ output_param: 'image_format'
109831
+ }, {
109832
+ id: 'fal-ai/wan/v2.2-a14b/text-to-image',
109833
+ // ok
109834
+ label: 'Wan 2.2 14B'
109835
+ }, {
109836
+ id: 'fal-ai/qwen-image',
109837
+ // ok
109838
+ label: 'Qwen Image',
109839
+ output_format: 'jpeg'
109840
+ }, {
109841
+ id: 'fal-ai/ideogram/v3',
109842
+ // ok
109843
+ label: 'Ideogram V3'
109844
+ }, {
109845
+ id: 'fal-ai/minimax/image-01',
109846
+ // ok
109847
+ label: 'MiniMax Image-01',
109848
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16'],
109849
+ size_param: 'aspect_ratio'
109850
+ }, {
109851
+ id: 'fal-ai/playground-v25',
109852
+ // ok
109853
+ label: 'Playground v25',
109854
+ output_format: 'jpeg'
109855
+ }, {
109856
+ id: 'fal-ai/sana',
109857
+ // ok
109858
+ label: 'Sana Base',
109859
+ output_format: 'jpeg'
109860
+ }, {
109861
+ id: 'fal-ai/sana/sprint',
109862
+ // ok
109863
+ label: 'Sana Sprint',
109864
+ output_format: 'jpeg'
109865
+ }, {
109866
+ id: 'fal-ai/sana/v1.5/4.8b',
109867
+ // ok
109868
+ label: 'Sana v1.5 4.8B',
109869
+ output_format: 'jpeg'
109870
+ }, {
109871
+ id: 'fal-ai/sana/v1.5/1.6b',
109872
+ // ok
109873
+ label: 'Sana v1.5 1.6B',
109874
+ output_format: 'jpeg'
109875
+ }];
109876
+ if (this.builder.imageGenerationModels) {
109877
+ this.imageModels = this.builder.imageGenerationModels;
109878
+ }
109720
109879
  } // constructor
109721
109880
 
109722
109881
  renderPanel() {
@@ -110046,6 +110205,22 @@ class Dictation {
110046
110205
  </div>
110047
110206
  </label>
110048
110207
 
110208
+ <div class="div-image-generation-options" style="display:none">
110209
+ <div style="font-weight:500;margin:18px 0 0 0;">${util.out('Image Generation')}</div>
110210
+
110211
+ <label class="label-input-image-model" for="input_image_model" style="margin: 7px 0 0 0;display: flex;flex-direction: column;letter-spacing: 0;">
110212
+ <div style="width:100%"><span>${util.out('Model')}</span>:</div>
110213
+ <select id="inpImageModelSelect" style="margin-top: 3px"></select>
110214
+ </label>
110215
+
110216
+ <label class="label-input-image-size div-size-container" for="input_image_size" style="margin: 7px 0 0 0;display: flex;flex-direction: column;letter-spacing: 0;">
110217
+ <div style="width:100%"><span>${util.out('Image Size')}</span>:</div>
110218
+ <select id="inpImageSizeSelect" style="margin-top: 3px"></select>
110219
+ </label>
110220
+
110221
+ <input id="inpImageOutputFormat" type="hidden" />
110222
+ </div>
110223
+
110049
110224
  <div style="text-align:right;margin-top:25px;">
110050
110225
  <button title="${util.out('Ok')}" class="input-ok classic-primary" style="width:100%;">${util.out('Ok')}</button>
110051
110226
  </div>
@@ -110231,7 +110406,7 @@ class Dictation {
110231
110406
  }
110232
110407
  }
110233
110408
  let bImageGeneration = false;
110234
- if (this.builder.textToImageUrl) {
110409
+ if (this.builder.textToImageUrl || this.builder.generateMediaUrl_Fal) {
110235
110410
  bImageGeneration = true;
110236
110411
  }
110237
110412
  for (const key in commandInfo) {
@@ -110369,7 +110544,7 @@ class Dictation {
110369
110544
  const btnScopeOthers = this.modalCommand.querySelector('.scope-others');
110370
110545
  const btnScopeImage = this.modalCommand.querySelector('.scope-image');
110371
110546
  btnScopeBlock.disabled = true;
110372
- if (this.builder.textToImageUrl && !this.builder.hideImageGeneration) btnScopeImage.style.display = ''; // show generate image button
110547
+ if ((this.builder.textToImageUrl || this.builder.generateMediaUrl_Fal) && !this.builder.hideImageGeneration) btnScopeImage.style.display = ''; // show generate image button
110373
110548
 
110374
110549
  const assistModeBtns = modalCommand.querySelectorAll('.div-assistant-mode button');
110375
110550
  assistModeBtns.forEach(btn => {
@@ -110441,8 +110616,114 @@ class Dictation {
110441
110616
  }
110442
110617
  };
110443
110618
  this.initialStart = false; // for Safari
110619
+
110620
+ this.renderImageOptions();
110444
110621
  }
110622
+ renderImageOptions() {
110623
+ const modal = this.modalConfig;
110624
+ const util = this.builder.util;
110625
+ const divImageSettings = modal.querySelector('.div-image-generation-options');
110626
+ if (this.builder.generateMediaUrl_Fal) {
110627
+ divImageSettings.style.display = '';
110628
+ }
110629
+ const sizeDefs = {
110630
+ square_hd: util.out('Square HD'),
110631
+ square: util.out('Square'),
110632
+ landscape_4_3: util.out('Landscape 4x3'),
110633
+ landscape_16_9: util.out('Landscape 16x9'),
110634
+ portrait_4_3: util.out('Portrait 3x4'),
110635
+ portrait_16_9: util.out('Portrait 9x16'),
110636
+ '1:1': util.out('Square'),
110637
+ '3:2': util.out('Landscape 3x2'),
110638
+ '4:3': util.out('Landscape 4x3'),
110639
+ '5:4': util.out('Landscape 5x4'),
110640
+ '16:9': util.out('Landscape 16x9'),
110641
+ '2:3': util.out('Portrait 2x3'),
110642
+ '3:4': util.out('Portrait 3x4'),
110643
+ '4:5': util.out('Portrait 4x5'),
110644
+ '9:16': util.out('Portrait 9x16'),
110645
+ '21:9': util.out('Landscape 21:9'),
110646
+ '9:21': util.out('Landscape 9:21')
110647
+ };
110445
110648
 
110649
+ // Default set
110650
+ const defaultSizes = ['square', 'square_hd', 'landscape_4_3', 'landscape_16_9', 'portrait_4_3', 'portrait_16_9'];
110651
+
110652
+ // Models
110653
+ let models = this.imageModels;
110654
+
110655
+ // Default selections
110656
+ const defaultModelId = this.builder.imageModel || 'fal-ai/flux-1/schnell';
110657
+ const defaultSize = this.builder.imageSize || 'landscape_4_3';
110658
+
110659
+ // Helper: return available sizes for a model
110660
+ function getSizesForModel(modelId) {
110661
+ const model = models.find(m => m.id === modelId);
110662
+ if (!model) return defaultSizes;
110663
+
110664
+ // if sizes explicitly empty array → means no size options
110665
+ if (Array.isArray(model.sizes) && model.sizes.length === 0) {
110666
+ return null;
110667
+ }
110668
+ return model.sizes || defaultSizes;
110669
+ }
110670
+
110671
+ // Elements
110672
+ const modelSelect = modal.querySelector('#inpImageModelSelect');
110673
+ const sizeSelect = modal.querySelector('#inpImageSizeSelect');
110674
+ const sizeContainer = sizeSelect.closest('.div-size-container') || sizeSelect; // wrap div if you have one
110675
+ const outputFormatField = modal.querySelector('#inpImageOutputFormat'); // hidden input
110676
+
110677
+ // Populate model select
110678
+ models.forEach(m => {
110679
+ const option = document.createElement('option');
110680
+ option.value = m.id;
110681
+ option.textContent = m.label;
110682
+ modelSelect.appendChild(option);
110683
+ });
110684
+
110685
+ // Populate sizes when model changes
110686
+ const renderSizes = (modelId, keepSelected = true) => {
110687
+ const model = models.find(m => m.id === modelId);
110688
+ const prevValue = sizeSelect.value;
110689
+ sizeSelect.innerHTML = ''; // clear
110690
+
110691
+ const sizes = getSizesForModel(modelId);
110692
+ // Handle size visibility
110693
+ if (!sizes) {
110694
+ sizeContainer.style.display = 'none';
110695
+ } else {
110696
+ sizeContainer.style.display = 'flex';
110697
+ sizes.forEach(s => {
110698
+ const option = document.createElement('option');
110699
+ option.value = s;
110700
+ option.textContent = sizeDefs[s] || s;
110701
+ sizeSelect.appendChild(option);
110702
+ });
110703
+
110704
+ // Try to restore previous size selection
110705
+ if (keepSelected && sizes.includes(prevValue)) {
110706
+ sizeSelect.value = prevValue;
110707
+ } else if (sizes.includes(defaultSize)) {
110708
+ sizeSelect.value = defaultSize;
110709
+ } else {
110710
+ sizeSelect.value = sizes[0];
110711
+ }
110712
+ }
110713
+
110714
+ // Handle output_format if present
110715
+ if (outputFormatField && model) {
110716
+ outputFormatField.value = model.output_format || '';
110717
+ }
110718
+ };
110719
+ modelSelect.addEventListener('change', e => {
110720
+ renderSizes(e.target.value);
110721
+ });
110722
+
110723
+ // Trigger initial render with defaults
110724
+ modelSelect.value = defaultModelId;
110725
+ renderSizes(defaultModelId, false);
110726
+ }
110446
110727
  resetConfig() {
110447
110728
  const tempSlider = this.modalConfig.querySelector('.temperature-slider');
110448
110729
  const valTemp = this.modalConfig.querySelector('.val-temp');
@@ -119041,6 +119322,7 @@ class ContentBuilder {
119041
119322
  let defaults = {
119042
119323
  page: '',
119043
119324
  container: '.is-container',
119325
+ siteToken: '',
119044
119326
  row: '',
119045
119327
  cols: [],
119046
119328
  colequal: [],
@@ -120450,6 +120732,7 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
120450
120732
  const builders = this.doc.querySelectorAll(this.opts.container);
120451
120733
  Array.prototype.forEach.call(builders, builder => {
120452
120734
  builder.classList.add('is-container');
120735
+ if (this.siteToken) builder.setAttribute('data-site-token', this.siteToken);
120453
120736
 
120454
120737
  // Check if preview
120455
120738
  if (this.dom.hasClass(builder, 'preview')) this.preview = true;
@@ -121216,7 +121499,9 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
121216
121499
 
121217
121500
  if (!this.dom.getSelected()) {
121218
121501
  let inputFocused = document.activeElement.tagName.toLowerCase() === 'input';
121219
- let insideEditable = this.doc.activeElement && this.doc.activeElement.closest('[contenteditable]');
121502
+
121503
+ // let insideEditable = this.doc.activeElement && this.doc.activeElement.closest('[contenteditable]');
121504
+ let insideEditable = target.closest('[contenteditable]');
121220
121505
 
121221
121506
  // if(!document.querySelector('.is-modal.active')) { // Additional (to prevent lost focus)
121222
121507
  let openedModal = document.querySelector('.is-modal.active:not(.is-modal-content)');
@@ -121360,6 +121645,7 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
121360
121645
  window.selectImage = this.selectImage.bind(this);
121361
121646
  window.selectVideo = this.selectVideo.bind(this);
121362
121647
  window.selectAsset = this.selectAsset.bind(this);
121648
+ window.closeAsset = this.closeAsset.bind(this);
121363
121649
  window.assetType = this.assetType.bind(this);
121364
121650
  window.hideModal = this.hideModal.bind(this);
121365
121651
  window.generateImage = this.generateImage.bind(this);
@@ -123865,6 +124151,20 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
123865
124151
  this.util._hideModal(modal); // this _hideModal will also trigger cancelCallback defined by showModal. This is done by programmatically click the overlay.
123866
124152
  }
123867
124153
 
124154
+ closeAsset() {
124155
+ let modal = document.querySelector('.is-modal.videoselect.active');
124156
+ if (modal) this.hideModal(modal);
124157
+ modal = document.querySelector('.is-modal.imageselect.active');
124158
+ if (modal) this.hideModal(modal);
124159
+ modal = document.querySelector('.is-modal.fileselect.active');
124160
+ if (modal) this.hideModal(modal);
124161
+ modal = document.querySelector('.is-modal.audioselect.active');
124162
+ if (modal) this.hideModal(modal);
124163
+ modal = document.querySelector('.is-modal.mediaselect.active');
124164
+ if (modal) this.hideModal(modal);
124165
+ modal = document.querySelector('.is-modal.otherselect.active');
124166
+ if (modal) this.hideModal(modal);
124167
+ }
123868
124168
  draggable(selector) {
123869
124169
  new Draggable$2({
123870
124170
  selector: selector
@@ -124476,7 +124776,8 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
124476
124776
  async waitingResultFal(jsonBody, requestId) {
124477
124777
  jsonBody.request_id = requestId;
124478
124778
  const getResultEndpoint = (model, requestId) => {
124479
- let endpoint = `https://queue.fal.run/${model}/requests/${requestId}`;
124779
+ let endpoint = 'https://queue.fal.run/{MODEL}/requests/{REQUEST_ID}';
124780
+ endpoint = endpoint.replace('{REQUEST_ID}', requestId);
124480
124781
  let firstTwoParts = model.split('/').slice(0, 2).join('/');
124481
124782
  endpoint = endpoint.replace('{MODEL}', firstTwoParts);
124482
124783
  return endpoint;
@@ -124527,16 +124828,56 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
124527
124828
  }
124528
124829
 
124529
124830
  async generateImage_Fal(prompt, callback) {
124831
+ const modal = this.dictation.modalConfig;
124832
+
124833
+ // Construct inputs: model, prompt, size, output format
124834
+ const inpImageModelSelect = modal.querySelector('#inpImageModelSelect');
124835
+ const inpImageSizeSelect = modal.querySelector('#inpImageSizeSelect');
124836
+ const outputFormatField = modal.querySelector('#inpImageOutputFormat');
124837
+ const modelId = inpImageModelSelect.value;
124838
+ const modelDef = this.dictation.imageModels.find(m => m.id === modelId) || {};
124839
+
124840
+ // Build options dynamically
124841
+ let options = {};
124842
+
124843
+ // Handle size/aspect_ratio if model has sizes
124844
+ if (modelDef && modelDef.sizes !== undefined) {
124845
+ if (modelDef.sizes !== null && modelDef.sizes.length !== 0) {
124846
+ const sizeParam = modelDef.size_param || 'image_size'; // default
124847
+ const imageSize = inpImageSizeSelect.value;
124848
+ options[sizeParam] = imageSize;
124849
+ }
124850
+ // if sizes = [] => no size options => exclude size.
124851
+ } else {
124852
+ // if sizes not defined, use default set
124853
+ const imageSize = inpImageSizeSelect.value;
124854
+ options['image_size'] = imageSize;
124855
+ }
124856
+
124857
+ // Handle output_format if present
124858
+ const outputFormat = outputFormatField.value;
124859
+ if (outputFormat) {
124860
+ const outputParam = modelDef.output_param || 'output_format'; // default
124861
+ options[outputParam] = outputFormat;
124862
+ }
124863
+ // if output_format not defined, exclude output_format.
124864
+
124530
124865
  this.controller = new AbortController();
124531
124866
  this.signal = this.controller.signal;
124532
- let model = this.imageModel || 'flux-schnell';
124533
- let jsonBody = {};
124534
- jsonBody.model = model;
124535
- jsonBody.customData = this.customData;
124536
- jsonBody.endpoint = `https://queue.fal.run/${model}`;
124537
- jsonBody.payload = {
124538
- prompt
124867
+ let jsonBody = {
124868
+ model: modelId,
124869
+ customData: this.customData,
124870
+ endpoint: `https://queue.fal.run/${modelId}`,
124871
+ payload: {
124872
+ prompt,
124873
+ ...options
124874
+ }
124539
124875
  };
124876
+
124877
+ // console.log(jsonBody);
124878
+ // this.dictation.finish();
124879
+ // return;
124880
+
124540
124881
  let url = this.generateMediaUrl_Fal;
124541
124882
  let headers = {
124542
124883
  ...this.headers,
@@ -124555,14 +124896,15 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
124555
124896
  }
124556
124897
  let requestId = result.request_id;
124557
124898
  const getStatusEndpoint = (model, requestId) => {
124558
- let endpoint = `https://queue.fal.run/${model}/requests/${requestId}`;
124899
+ let endpoint = 'https://queue.fal.run/{MODEL}/requests/{REQUEST_ID}/status';
124900
+ endpoint = endpoint.replace('{REQUEST_ID}', requestId);
124559
124901
  let firstTwoParts = model.split('/').slice(0, 2).join('/');
124560
124902
  endpoint = endpoint.replace('{MODEL}', firstTwoParts);
124561
124903
  return endpoint;
124562
124904
  };
124563
- const statusEndpoint = getStatusEndpoint(model, requestId);
124905
+ const statusEndpoint = getStatusEndpoint(modelId, requestId);
124564
124906
  let inputCheckStatus = {
124565
- model,
124907
+ model: modelId,
124566
124908
  endpoint: statusEndpoint,
124567
124909
  request_id: requestId
124568
124910
  // customData: this.customData
@@ -160759,6 +161101,8 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
160759
161101
  imageScheduler: this.settings.imageScheduler,
160760
161102
  imageAutoUpscale: this.settings.imageAutoUpscale,
160761
161103
  defaultImageGenerationProvider: this.settings.defaultImageGenerationProvider,
161104
+ imageSize: this.settings.imageSize,
161105
+ imageGenerationModels: this.settings.imageGenerationModels,
160762
161106
  generateMediaUrl_Fal: this.settings.generateMediaUrl_Fal,
160763
161107
  checkRequestStatusUrl_Fal: this.settings.checkRequestStatusUrl_Fal,
160764
161108
  getResultUrl_Fal: this.settings.getResultUrl_Fal,
@@ -164124,6 +164468,14 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
164124
164468
  this.editor.hideModal(modal);
164125
164469
  }
164126
164470
 
164471
+ selectAsset(url) {
164472
+ this.editor.selectAsset(url);
164473
+ }
164474
+
164475
+ closeAsset() {
164476
+ this.editor.closeAsset();
164477
+ }
164478
+
164127
164479
  refreshModule() {
164128
164480
  this.box.refreshModule();
164129
164481
  }