@innovastudio/contentbox 1.6.136 → 1.6.138

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;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@innovastudio/contentbox",
3
3
  "type": "module",
4
- "version": "1.6.136",
4
+ "version": "1.6.138",
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.126",
62
+ "@innovastudio/contentbuilder": "^1.5.131",
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}
@@ -97362,14 +97375,14 @@ class Rte {
97362
97375
  if (btnLink) btnLink.style.display = '';
97363
97376
  if (btnSymbol) btnSymbol.style.display = '';
97364
97377
  if (!customcode && !noedit && !_protected || subblock) {
97365
- if ((elm.tagName.toLowerCase() === 'img' || dom.hasClass(elm, 'is-social') || dom.hasClass(elm, 'is-rounded-button-medium') || dom.hasClass(elm, 'cell-active')) && !dom.getSelected()) {
97378
+ if ((dom.hasClass(elm, 'is-social') || dom.hasClass(elm, 'is-rounded-button-medium') || dom.hasClass(elm, 'cell-active')) && !dom.getSelected()) {
97366
97379
  if (this.elementRteTool.style.display === 'none' || this.elementRteTool.style.display === '') {
97367
97380
  this.elementRteTool.style.display = 'flex';
97368
97381
  this.rteTool.style.display = 'none';
97369
97382
  this.showAlignButtons();
97370
97383
  this.positionToolbar();
97371
97384
  }
97372
- } else if (dom.hasClass(elm, 'spacer') || elm.tagName.toLowerCase() === 'video' || dom.hasClass(elm, 'ovl') || col.getAttribute('data-html') && !subblock) {
97385
+ } else if (elm.tagName.toLowerCase() === 'img' || dom.hasClass(elm, 'spacer') || elm.tagName.toLowerCase() === 'video' || dom.hasClass(elm, 'ovl') || col.getAttribute('data-html') && !subblock) {
97373
97386
  //|| col===elm
97374
97387
 
97375
97388
  if (this.elementRteTool.style.display === 'none' || this.elementRteTool.style.display === '') {
@@ -109717,6 +109730,147 @@ 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
+ label: 'Nano Banana',
109736
+ sizes: [],
109737
+ // no size options
109738
+ output_format: 'jpeg'
109739
+ }, {
109740
+ id: 'fal-ai/imagen4/preview/fast',
109741
+ label: 'Imagen 4 Preview Fast',
109742
+ sizes: ['1:1', '4:3', '16:9', '3:4', '9:16']
109743
+ }, {
109744
+ id: 'fal-ai/imagen4/preview',
109745
+ label: 'Imagen 4 Preview',
109746
+ sizes: ['1:1', '4:3', '16:9', '3:4', '9:16']
109747
+ }, {
109748
+ id: 'fal-ai/imagen4/preview/ultra',
109749
+ label: 'Imagen 4 Preview Ultra',
109750
+ sizes: ['1:1', '4:3', '16:9', '3:4', '9:16']
109751
+ }, {
109752
+ id: 'fal-ai/flux-1/schnell',
109753
+ label: 'FLUX.1 Schnell',
109754
+ // sizes: => uses defaultSizes
109755
+ output_format: 'jpeg'
109756
+ },
109757
+ // Krea
109758
+ {
109759
+ id: 'fal-ai/flux/krea',
109760
+ label: 'FLUX.1 Krea',
109761
+ output_format: 'jpeg'
109762
+ },
109763
+ // {
109764
+ // id: 'fal-ai/flux-krea-lora',
109765
+ // label: 'FLUX.1 Krea Lora',
109766
+ // output_format: 'jpeg'
109767
+ // },
109768
+ // Kontext
109769
+ {
109770
+ id: 'fal-ai/flux-kontext-lora/text-to-image',
109771
+ label: 'FLUX.1 Kontext Lora',
109772
+ output_format: 'jpeg'
109773
+ }, {
109774
+ id: 'fal-ai/flux-pro/kontext/text-to-image',
109775
+ label: 'FLUX.1 Kontext Pro',
109776
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16', '9:21'],
109777
+ size_param: 'aspect_ratio',
109778
+ // aspect_ratio
109779
+ output_format: 'jpeg'
109780
+ }, {
109781
+ id: 'fal-ai/flux-pro/kontext/max/text-to-image',
109782
+ label: 'FLUX.1 Kontext Max',
109783
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16', '9:21'],
109784
+ size_param: 'aspect_ratio',
109785
+ // aspect_ratio
109786
+ output_format: 'jpeg'
109787
+ },
109788
+ // Pro
109789
+ {
109790
+ id: 'fal-ai/flux-pro/new',
109791
+ label: 'FLUX.1 Pro',
109792
+ // new, fast
109793
+ output_format: 'jpeg'
109794
+ }, {
109795
+ id: 'fal-ai/flux-pro/v1.1',
109796
+ label: 'FLUX1.1 Pro',
109797
+ output_format: 'jpeg'
109798
+ }, {
109799
+ id: 'fal-ai/flux-pro/v1.1-ultra',
109800
+ label: 'FLUX1.1 Pro Ultra',
109801
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16', '9:21'],
109802
+ size_param: 'aspect_ratio',
109803
+ // aspect_ratio
109804
+ output_format: 'jpeg'
109805
+ }, {
109806
+ id: 'fal-ai/bytedance/seedream/v4/text-to-image',
109807
+ label: 'ByteDance Seedream 4.0'
109808
+ }, {
109809
+ id: 'fal-ai/wan/v2.2-5b/text-to-image',
109810
+ label: 'Wan 2.2 5B',
109811
+ output_format: 'jpeg',
109812
+ output_param: 'image_format'
109813
+ }, {
109814
+ id: 'fal-ai/wan/v2.2-a14b/text-to-image',
109815
+ label: 'Wan 2.2 14B'
109816
+ }, {
109817
+ id: 'fal-ai/qwen-image',
109818
+ label: 'Qwen Image',
109819
+ output_format: 'jpeg'
109820
+ }, {
109821
+ id: 'fal-ai/hidream-i1-fast',
109822
+ label: 'HiDream-I1 Fast',
109823
+ output_format: 'jpeg'
109824
+ }, {
109825
+ id: 'fal-ai/hidream-i1-dev',
109826
+ label: 'HiDream-I1 Dev',
109827
+ output_format: 'jpeg'
109828
+ }, {
109829
+ id: 'fal-ai/hidream-i1-full',
109830
+ label: 'HiDream-I1 Full',
109831
+ output_format: 'jpeg'
109832
+ }, {
109833
+ id: 'bria/text-to-image/3.2',
109834
+ // new
109835
+ label: 'Bria (3.2)',
109836
+ sizes: ['1:1', '3:2', '4:3', '5:4', '16:9', '2:3', '3:4', '4:5', '9:16']
109837
+ }, {
109838
+ id: 'fal-ai/recraft/v3/text-to-image',
109839
+ label: 'Recraft V3'
109840
+ }, {
109841
+ id: 'fal-ai/ideogram/v3',
109842
+ label: 'Ideogram V3'
109843
+ }, {
109844
+ id: 'fal-ai/minimax/image-01',
109845
+ // new
109846
+ label: 'MiniMax Image-01',
109847
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16'],
109848
+ size_param: 'aspect_ratio' // aspect_ratio
109849
+ }, {
109850
+ id: 'fal-ai/playground-v25',
109851
+ // new
109852
+ label: 'Playground v25',
109853
+ output_format: 'jpeg'
109854
+ }, {
109855
+ id: 'fal-ai/sana',
109856
+ label: 'Sana Base',
109857
+ output_format: 'jpeg'
109858
+ }, {
109859
+ id: 'fal-ai/sana/sprint',
109860
+ label: 'Sana Sprint',
109861
+ output_format: 'jpeg'
109862
+ }, {
109863
+ id: 'fal-ai/sana/v1.5/4.8b',
109864
+ label: 'Sana v1.5 4.8B',
109865
+ output_format: 'jpeg'
109866
+ }, {
109867
+ id: 'fal-ai/sana/v1.5/1.6b',
109868
+ label: 'Sana v1.5 1.6B',
109869
+ output_format: 'jpeg'
109870
+ }];
109871
+ if (this.builder.imageGenerationModels) {
109872
+ this.imageModels = this.builder.imageGenerationModels;
109873
+ }
109720
109874
  } // constructor
109721
109875
 
109722
109876
  renderPanel() {
@@ -110046,6 +110200,22 @@ class Dictation {
110046
110200
  </div>
110047
110201
  </label>
110048
110202
 
110203
+ <div class="div-image-generation-options" style="display:none">
110204
+ <div style="font-weight:500;margin:18px 0 0 0;">${util.out('Image Generation')}</div>
110205
+
110206
+ <label class="label-input-image-model" for="input_image_model" style="margin: 7px 0 0 0;display: flex;flex-direction: column;letter-spacing: 0;">
110207
+ <div style="width:100%"><span>${util.out('Model')}</span>:</div>
110208
+ <select id="inpImageModelSelect" style="margin-top: 3px"></select>
110209
+ </label>
110210
+
110211
+ <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;">
110212
+ <div style="width:100%"><span>${util.out('Image Size')}</span>:</div>
110213
+ <select id="inpImageSizeSelect" style="margin-top: 3px"></select>
110214
+ </label>
110215
+
110216
+ <input id="inpImageOutputFormat" type="hidden" />
110217
+ </div>
110218
+
110049
110219
  <div style="text-align:right;margin-top:25px;">
110050
110220
  <button title="${util.out('Ok')}" class="input-ok classic-primary" style="width:100%;">${util.out('Ok')}</button>
110051
110221
  </div>
@@ -110231,7 +110401,7 @@ class Dictation {
110231
110401
  }
110232
110402
  }
110233
110403
  let bImageGeneration = false;
110234
- if (this.builder.textToImageUrl) {
110404
+ if (this.builder.textToImageUrl || this.builder.generateMediaUrl_Fal) {
110235
110405
  bImageGeneration = true;
110236
110406
  }
110237
110407
  for (const key in commandInfo) {
@@ -110369,7 +110539,7 @@ class Dictation {
110369
110539
  const btnScopeOthers = this.modalCommand.querySelector('.scope-others');
110370
110540
  const btnScopeImage = this.modalCommand.querySelector('.scope-image');
110371
110541
  btnScopeBlock.disabled = true;
110372
- if (this.builder.textToImageUrl && !this.builder.hideImageGeneration) btnScopeImage.style.display = ''; // show generate image button
110542
+ if ((this.builder.textToImageUrl || this.builder.generateMediaUrl_Fal) && !this.builder.hideImageGeneration) btnScopeImage.style.display = ''; // show generate image button
110373
110543
 
110374
110544
  const assistModeBtns = modalCommand.querySelectorAll('.div-assistant-mode button');
110375
110545
  assistModeBtns.forEach(btn => {
@@ -110441,8 +110611,114 @@ class Dictation {
110441
110611
  }
110442
110612
  };
110443
110613
  this.initialStart = false; // for Safari
110614
+
110615
+ this.renderImageOptions();
110444
110616
  }
110617
+ renderImageOptions() {
110618
+ const modal = this.modalConfig;
110619
+ const util = this.builder.util;
110620
+ const divImageSettings = modal.querySelector('.div-image-generation-options');
110621
+ if (this.builder.generateMediaUrl_Fal) {
110622
+ divImageSettings.style.display = '';
110623
+ }
110624
+ const sizeDefs = {
110625
+ square_hd: util.out('Square HD'),
110626
+ square: util.out('Square'),
110627
+ landscape_4_3: util.out('Landscape 4x3'),
110628
+ landscape_16_9: util.out('Landscape 16x9'),
110629
+ portrait_4_3: util.out('Portrait 3x4'),
110630
+ portrait_16_9: util.out('Portrait 9x16'),
110631
+ '1:1': util.out('Square'),
110632
+ '3:2': util.out('Landscape 3x2'),
110633
+ '4:3': util.out('Landscape 4x3'),
110634
+ '5:4': util.out('Landscape 5x4'),
110635
+ '16:9': util.out('Landscape 16x9'),
110636
+ '2:3': util.out('Portrait 2x3'),
110637
+ '3:4': util.out('Portrait 3x4'),
110638
+ '4:5': util.out('Portrait 4x5'),
110639
+ '9:16': util.out('Portrait 9x16'),
110640
+ '21:9': util.out('Landscape 21:9'),
110641
+ '9:21': util.out('Landscape 9:21')
110642
+ };
110445
110643
 
110644
+ // Default set
110645
+ const defaultSizes = ['square', 'square_hd', 'landscape_4_3', 'landscape_16_9', 'portrait_4_3', 'portrait_16_9'];
110646
+
110647
+ // Models
110648
+ let models = this.imageModels;
110649
+
110650
+ // Default selections
110651
+ const defaultModelId = this.builder.imageModel || 'fal-ai/flux-1/schnell';
110652
+ const defaultSize = this.builder.imageSize || 'landscape_4_3';
110653
+
110654
+ // Helper: return available sizes for a model
110655
+ function getSizesForModel(modelId) {
110656
+ const model = models.find(m => m.id === modelId);
110657
+ if (!model) return defaultSizes;
110658
+
110659
+ // if sizes explicitly empty array → means no size options
110660
+ if (Array.isArray(model.sizes) && model.sizes.length === 0) {
110661
+ return null;
110662
+ }
110663
+ return model.sizes || defaultSizes;
110664
+ }
110665
+
110666
+ // Elements
110667
+ const modelSelect = modal.querySelector('#inpImageModelSelect');
110668
+ const sizeSelect = modal.querySelector('#inpImageSizeSelect');
110669
+ const sizeContainer = sizeSelect.closest('.div-size-container') || sizeSelect; // wrap div if you have one
110670
+ const outputFormatField = modal.querySelector('#inpImageOutputFormat'); // hidden input
110671
+
110672
+ // Populate model select
110673
+ models.forEach(m => {
110674
+ const option = document.createElement('option');
110675
+ option.value = m.id;
110676
+ option.textContent = m.label;
110677
+ modelSelect.appendChild(option);
110678
+ });
110679
+
110680
+ // Populate sizes when model changes
110681
+ const renderSizes = (modelId, keepSelected = true) => {
110682
+ const model = models.find(m => m.id === modelId);
110683
+ const prevValue = sizeSelect.value;
110684
+ sizeSelect.innerHTML = ''; // clear
110685
+
110686
+ const sizes = getSizesForModel(modelId);
110687
+ // Handle size visibility
110688
+ if (!sizes) {
110689
+ sizeContainer.style.display = 'none';
110690
+ } else {
110691
+ sizeContainer.style.display = 'flex';
110692
+ sizes.forEach(s => {
110693
+ const option = document.createElement('option');
110694
+ option.value = s;
110695
+ option.textContent = sizeDefs[s] || s;
110696
+ sizeSelect.appendChild(option);
110697
+ });
110698
+
110699
+ // Try to restore previous size selection
110700
+ if (keepSelected && sizes.includes(prevValue)) {
110701
+ sizeSelect.value = prevValue;
110702
+ } else if (sizes.includes(defaultSize)) {
110703
+ sizeSelect.value = defaultSize;
110704
+ } else {
110705
+ sizeSelect.value = sizes[0];
110706
+ }
110707
+ }
110708
+
110709
+ // Handle output_format if present
110710
+ if (outputFormatField && model) {
110711
+ outputFormatField.value = model.output_format || '';
110712
+ }
110713
+ };
110714
+ modelSelect.addEventListener('change', e => {
110715
+ renderSizes(e.target.value);
110716
+ });
110717
+
110718
+ // Trigger initial render with defaults
110719
+ modelSelect.value = defaultModelId;
110720
+ renderSizes(defaultModelId, false);
110721
+ }
110446
110722
  resetConfig() {
110447
110723
  const tempSlider = this.modalConfig.querySelector('.temperature-slider');
110448
110724
  const valTemp = this.modalConfig.querySelector('.val-temp');
@@ -119041,6 +119317,7 @@ class ContentBuilder {
119041
119317
  let defaults = {
119042
119318
  page: '',
119043
119319
  container: '.is-container',
119320
+ siteToken: '',
119044
119321
  row: '',
119045
119322
  cols: [],
119046
119323
  colequal: [],
@@ -120450,6 +120727,7 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
120450
120727
  const builders = this.doc.querySelectorAll(this.opts.container);
120451
120728
  Array.prototype.forEach.call(builders, builder => {
120452
120729
  builder.classList.add('is-container');
120730
+ if (this.siteToken) builder.setAttribute('data-site-token', this.siteToken);
120453
120731
 
120454
120732
  // Check if preview
120455
120733
  if (this.dom.hasClass(builder, 'preview')) this.preview = true;
@@ -121210,13 +121488,28 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
121210
121488
  }
121211
121489
  }
121212
121490
  */
121213
-
121491
+ const clickedElementEditable = target.closest('[contenteditable]');
121492
+ let insideEditable = this.doc.activeElement && this.doc.activeElement.closest('[contenteditable]') && this.doc.activeElement.closest('.is-builder');
121493
+ if (insideEditable && !clickedElementEditable) {
121494
+ this.saveSelection();
121495
+ const selection = this.dom.getSelection();
121496
+ if (selection && !selection.isCollapsed) {
121497
+ // Only if there is text selected (not caret selection)
121498
+ const col = this.doc.activeElement.closest('[contenteditable]');
121499
+ if (col) {
121500
+ // this.handleCellClick(col, e);
121501
+ this.activateColumnAndRte(col);
121502
+ }
121503
+ }
121504
+ }
121214
121505
  if (!(a || p || b || c || d || f || g || h || i || j || o || isSpecialElement || clrPicker) || rowClicked && !i || containerClicked) {
121215
121506
  // Click anywhere but is not inside builder area, modal, popup, tool or rte, then clear row/column (cell) selection
121216
121507
 
121217
121508
  if (!this.dom.getSelected()) {
121218
121509
  let inputFocused = document.activeElement.tagName.toLowerCase() === 'input';
121219
- let insideEditable = this.doc.activeElement && this.doc.activeElement.closest('[contenteditable]');
121510
+
121511
+ // let insideEditable = this.doc.activeElement && this.doc.activeElement.closest('[contenteditable]');
121512
+ let insideEditable = target.closest('[contenteditable]');
121220
121513
 
121221
121514
  // if(!document.querySelector('.is-modal.active')) { // Additional (to prevent lost focus)
121222
121515
  let openedModal = document.querySelector('.is-modal.active:not(.is-modal-content)');
@@ -124491,7 +124784,8 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
124491
124784
  async waitingResultFal(jsonBody, requestId) {
124492
124785
  jsonBody.request_id = requestId;
124493
124786
  const getResultEndpoint = (model, requestId) => {
124494
- let endpoint = `https://queue.fal.run/${model}/requests/${requestId}`;
124787
+ let endpoint = 'https://queue.fal.run/{MODEL}/requests/{REQUEST_ID}';
124788
+ endpoint = endpoint.replace('{REQUEST_ID}', requestId);
124495
124789
  let firstTwoParts = model.split('/').slice(0, 2).join('/');
124496
124790
  endpoint = endpoint.replace('{MODEL}', firstTwoParts);
124497
124791
  return endpoint;
@@ -124542,16 +124836,56 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
124542
124836
  }
124543
124837
 
124544
124838
  async generateImage_Fal(prompt, callback) {
124839
+ const modal = this.dictation.modalConfig;
124840
+
124841
+ // Construct inputs: model, prompt, size, output format
124842
+ const inpImageModelSelect = modal.querySelector('#inpImageModelSelect');
124843
+ const inpImageSizeSelect = modal.querySelector('#inpImageSizeSelect');
124844
+ const outputFormatField = modal.querySelector('#inpImageOutputFormat');
124845
+ const modelId = inpImageModelSelect.value;
124846
+ const modelDef = this.dictation.imageModels.find(m => m.id === modelId) || {};
124847
+
124848
+ // Build options dynamically
124849
+ let options = {};
124850
+
124851
+ // Handle size/aspect_ratio if model has sizes
124852
+ if (modelDef && modelDef.sizes !== undefined) {
124853
+ if (modelDef.sizes !== null && modelDef.sizes.length !== 0) {
124854
+ const sizeParam = modelDef.size_param || 'image_size'; // default
124855
+ const imageSize = inpImageSizeSelect.value;
124856
+ options[sizeParam] = imageSize;
124857
+ }
124858
+ // if sizes = [] => no size options => exclude size.
124859
+ } else {
124860
+ // if sizes not defined, use default set
124861
+ const imageSize = inpImageSizeSelect.value;
124862
+ options['image_size'] = imageSize;
124863
+ }
124864
+
124865
+ // Handle output_format if present
124866
+ const outputFormat = outputFormatField.value;
124867
+ if (outputFormat) {
124868
+ const outputParam = modelDef.output_param || 'output_format'; // default
124869
+ options[outputParam] = outputFormat;
124870
+ }
124871
+ // if output_format not defined, exclude output_format.
124872
+
124545
124873
  this.controller = new AbortController();
124546
124874
  this.signal = this.controller.signal;
124547
- let model = this.imageModel || 'flux-schnell';
124548
- let jsonBody = {};
124549
- jsonBody.model = model;
124550
- jsonBody.customData = this.customData;
124551
- jsonBody.endpoint = `https://queue.fal.run/${model}`;
124552
- jsonBody.payload = {
124553
- prompt
124875
+ let jsonBody = {
124876
+ model: modelId,
124877
+ customData: this.customData,
124878
+ endpoint: `https://queue.fal.run/${modelId}`,
124879
+ payload: {
124880
+ prompt,
124881
+ ...options
124882
+ }
124554
124883
  };
124884
+
124885
+ // console.log(jsonBody);
124886
+ // this.dictation.finish();
124887
+ // return;
124888
+
124555
124889
  let url = this.generateMediaUrl_Fal;
124556
124890
  let headers = {
124557
124891
  ...this.headers,
@@ -124570,14 +124904,15 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
124570
124904
  }
124571
124905
  let requestId = result.request_id;
124572
124906
  const getStatusEndpoint = (model, requestId) => {
124573
- let endpoint = `https://queue.fal.run/${model}/requests/${requestId}`;
124907
+ let endpoint = 'https://queue.fal.run/{MODEL}/requests/{REQUEST_ID}/status';
124908
+ endpoint = endpoint.replace('{REQUEST_ID}', requestId);
124574
124909
  let firstTwoParts = model.split('/').slice(0, 2).join('/');
124575
124910
  endpoint = endpoint.replace('{MODEL}', firstTwoParts);
124576
124911
  return endpoint;
124577
124912
  };
124578
- const statusEndpoint = getStatusEndpoint(model, requestId);
124913
+ const statusEndpoint = getStatusEndpoint(modelId, requestId);
124579
124914
  let inputCheckStatus = {
124580
- model,
124915
+ model: modelId,
124581
124916
  endpoint: statusEndpoint,
124582
124917
  request_id: requestId
124583
124918
  // customData: this.customData
@@ -124865,6 +125200,32 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
124865
125200
  }
124866
125201
  }
124867
125202
  }
125203
+ activateColumnAndRte(col) {
125204
+ const util = this.util;
125205
+ util.clearActiveCell();
125206
+ this.activeCol = col;
125207
+ col.classList.add('cell-active');
125208
+ let row = col.parentNode;
125209
+ row.classList.add('row-active');
125210
+ const builders = this.doc.querySelectorAll(this.opts.container);
125211
+ builders.forEach(builder => {
125212
+ builder.classList.remove('builder-active');
125213
+ });
125214
+ row.parentNode.classList.add('builder-active');
125215
+ this.doc.body.classList.add('content-edit');
125216
+ if (row.childElementCount - 2 === 1) ; else {
125217
+ row.classList.add('row-outline');
125218
+ }
125219
+
125220
+ // Call onContentClick to indicate click on editable content (eg. for plugin usage)
125221
+ // if(this.opts.onContentClick) this.opts.onContentClick(e);
125222
+
125223
+ this.colTool.click(col);
125224
+ // this.elmTool.click(col, e);
125225
+ this.activeElement = col;
125226
+ this.inspectedElement = col;
125227
+ if (!this.controlPanel) this.rte.click(col);
125228
+ }
124868
125229
  handleCellClick(col, e) {
124869
125230
  if (this.cleanEditing) {
124870
125231
  col.parentNode.querySelector('.is-row-tool').style.display = '';
@@ -160774,6 +161135,8 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
160774
161135
  imageScheduler: this.settings.imageScheduler,
160775
161136
  imageAutoUpscale: this.settings.imageAutoUpscale,
160776
161137
  defaultImageGenerationProvider: this.settings.defaultImageGenerationProvider,
161138
+ imageSize: this.settings.imageSize,
161139
+ imageGenerationModels: this.settings.imageGenerationModels,
160777
161140
  generateMediaUrl_Fal: this.settings.generateMediaUrl_Fal,
160778
161141
  checkRequestStatusUrl_Fal: this.settings.checkRequestStatusUrl_Fal,
160779
161142
  getResultUrl_Fal: this.settings.getResultUrl_Fal,