@innovastudio/contentbuilder 1.5.127 → 1.5.129

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
@@ -214,8 +214,10 @@ interface ContentBuilderOptions {
214
214
  commandInfoCanvasMode?: any[];
215
215
  onStartRequest?: () => void;
216
216
 
217
- imageModel?: string;
218
217
  defaultImageGenerationProvider?: string;
218
+ imageModel?: string;
219
+ imageSize?: string;
220
+ imageGenerationModels?: any[];
219
221
 
220
222
  //-- Asset Manager
221
223
  listFilesUrl?: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@innovastudio/contentbuilder",
3
3
  "type": "module",
4
- "version": "1.5.127",
4
+ "version": "1.5.129",
5
5
  "description": "",
6
6
  "main": "public/contentbuilder/contentbuilder.esm.js",
7
7
  "types": "index.d.ts",
@@ -83219,6 +83219,152 @@ class Dictation {
83219
83219
  };
83220
83220
  this.opts = Object.assign(this, defaults, opts);
83221
83221
  this.builder = builder;
83222
+ this.imageModels = [{
83223
+ id: 'fal-ai/nano-banana',
83224
+ // ok
83225
+ label: 'Nano Banana',
83226
+ sizes: [],
83227
+ // no size options
83228
+ output_format: 'jpeg'
83229
+ }, {
83230
+ id: 'fal-ai/imagen4/preview/fast',
83231
+ // ok
83232
+ label: 'Imagen 4 Preview Fast',
83233
+ sizes: ['1:1', '4:3', '16:9', '3:4', '9:16']
83234
+ }, {
83235
+ id: 'fal-ai/imagen4/preview',
83236
+ // ok
83237
+ label: 'Imagen 4 Preview',
83238
+ sizes: ['1:1', '4:3', '16:9', '3:4', '9:16']
83239
+ }, {
83240
+ id: 'fal-ai/imagen4/preview/ultra',
83241
+ // ok
83242
+ label: 'Imagen 4 Preview Ultra',
83243
+ sizes: ['1:1', '4:3', '16:9', '3:4', '9:16']
83244
+ }, {
83245
+ id: 'fal-ai/hidream-i1-fast',
83246
+ // ok
83247
+ label: 'HiDream-I1 Fast',
83248
+ // sizes: => uses defaultSizes
83249
+ output_format: 'jpeg'
83250
+ }, {
83251
+ id: 'fal-ai/hidream-i1-dev',
83252
+ // ok
83253
+ label: 'HiDream-I1 Dev',
83254
+ output_format: 'jpeg'
83255
+ }, {
83256
+ id: 'fal-ai/hidream-i1-full',
83257
+ // ok
83258
+ label: 'HiDream-I1 Full',
83259
+ output_format: 'jpeg'
83260
+ }, {
83261
+ id: 'bria/text-to-image/3.2',
83262
+ // ok
83263
+ label: 'Bria (3.2)',
83264
+ sizes: ['1:1', '3:2', '4:3', '5:4', '16:9', '2:3', '3:4', '4:5', '9:16']
83265
+ }, {
83266
+ id: 'fal-ai/recraft/v3/text-to-image',
83267
+ // ok
83268
+ label: 'Recraft V3'
83269
+ }, {
83270
+ id: 'fal-ai/flux-1/schnell',
83271
+ // ok
83272
+ label: 'FLUX.1 Schnell',
83273
+ output_format: 'jpeg'
83274
+ }, {
83275
+ id: 'fal-ai/flux/krea',
83276
+ // ok
83277
+ label: 'FLUX.1 Krea',
83278
+ output_format: 'jpeg'
83279
+ }, {
83280
+ id: 'fal-ai/flux-krea-lora',
83281
+ // ok
83282
+ label: 'FLUX.1 Krea Lora',
83283
+ output_format: 'jpeg'
83284
+ }, {
83285
+ id: 'fal-ai/flux-kontext-lora/text-to-image',
83286
+ // ok
83287
+ label: 'FLUX Kontext Lora',
83288
+ output_format: 'jpeg'
83289
+ }, {
83290
+ id: 'fal-ai/flux-pro/kontext/text-to-image',
83291
+ // ok
83292
+ label: 'FLUX.1 Kontext Pro',
83293
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16', '9:21'],
83294
+ size_param: 'aspect_ratio',
83295
+ output_format: 'jpeg'
83296
+ }, {
83297
+ id: 'fal-ai/flux-pro/kontext/max/text-to-image',
83298
+ // ok
83299
+ label: 'FLUX.1 Kontext Max',
83300
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16', '9:21'],
83301
+ size_param: 'aspect_ratio',
83302
+ output_format: 'jpeg'
83303
+ }, {
83304
+ id: 'fal-ai/flux-pro/v1.1-ultra',
83305
+ // ok
83306
+ label: 'FLUX 1.1 Pro Ultra',
83307
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16', '9:21'],
83308
+ size_param: 'aspect_ratio',
83309
+ output_format: 'jpeg'
83310
+ }, {
83311
+ id: 'fal-ai/bytedance/seedream/v4/text-to-image',
83312
+ // ok
83313
+ label: 'ByteDance Seedream 4.0'
83314
+ }, {
83315
+ id: 'fal-ai/wan/v2.2-5b/text-to-image',
83316
+ // ok
83317
+ label: 'Wan 2.2 5B',
83318
+ output_format: 'jpeg',
83319
+ output_param: 'image_format'
83320
+ }, {
83321
+ id: 'fal-ai/wan/v2.2-a14b/text-to-image',
83322
+ // ok
83323
+ label: 'Wan 2.2 14B'
83324
+ }, {
83325
+ id: 'fal-ai/qwen-image',
83326
+ // ok
83327
+ label: 'Qwen Image',
83328
+ output_format: 'jpeg'
83329
+ }, {
83330
+ id: 'fal-ai/ideogram/v3',
83331
+ // ok
83332
+ label: 'Ideogram V3'
83333
+ }, {
83334
+ id: 'fal-ai/minimax/image-01',
83335
+ // ok
83336
+ label: 'MiniMax Image-01',
83337
+ sizes: ['21:9', '16:9', '4:3', '3:2', '1:1', '2:3', '3:4', '9:16'],
83338
+ size_param: 'aspect_ratio'
83339
+ }, {
83340
+ id: 'fal-ai/playground-v25',
83341
+ // ok
83342
+ label: 'Playground v25',
83343
+ output_format: 'jpeg'
83344
+ }, {
83345
+ id: 'fal-ai/sana',
83346
+ // ok
83347
+ label: 'Sana Base',
83348
+ output_format: 'jpeg'
83349
+ }, {
83350
+ id: 'fal-ai/sana/sprint',
83351
+ // ok
83352
+ label: 'Sana Sprint',
83353
+ output_format: 'jpeg'
83354
+ }, {
83355
+ id: 'fal-ai/sana/v1.5/4.8b',
83356
+ // ok
83357
+ label: 'Sana v1.5 4.8B',
83358
+ output_format: 'jpeg'
83359
+ }, {
83360
+ id: 'fal-ai/sana/v1.5/1.6b',
83361
+ // ok
83362
+ label: 'Sana v1.5 1.6B',
83363
+ output_format: 'jpeg'
83364
+ }];
83365
+ if (this.builder.imageGenerationModels) {
83366
+ this.imageModels = this.builder.imageGenerationModels;
83367
+ }
83222
83368
  } // constructor
83223
83369
 
83224
83370
  renderPanel() {
@@ -83548,6 +83694,22 @@ class Dictation {
83548
83694
  </div>
83549
83695
  </label>
83550
83696
 
83697
+ <div class="div-image-generation-options" style="display:none">
83698
+ <div style="font-weight:500;margin:18px 0 0 0;">${util.out('Image Generation')}</div>
83699
+
83700
+ <label class="label-input-image-model" for="input_image_model" style="margin: 7px 0 0 0;display: flex;flex-direction: column;letter-spacing: 0;">
83701
+ <div style="width:100%"><span>${util.out('Model')}</span>:</div>
83702
+ <select id="inpImageModelSelect" style="margin-top: 3px"></select>
83703
+ </label>
83704
+
83705
+ <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;">
83706
+ <div style="width:100%"><span>${util.out('Image Size')}</span>:</div>
83707
+ <select id="inpImageSizeSelect" style="margin-top: 3px"></select>
83708
+ </label>
83709
+
83710
+ <input id="inpImageOutputFormat" type="hidden" />
83711
+ </div>
83712
+
83551
83713
  <div style="text-align:right;margin-top:25px;">
83552
83714
  <button title="${util.out('Ok')}" class="input-ok classic-primary" style="width:100%;">${util.out('Ok')}</button>
83553
83715
  </div>
@@ -83943,8 +84105,114 @@ class Dictation {
83943
84105
  }
83944
84106
  };
83945
84107
  this.initialStart = false; // for Safari
84108
+
84109
+ this.renderImageOptions();
83946
84110
  }
84111
+ renderImageOptions() {
84112
+ const modal = this.modalConfig;
84113
+ const util = this.builder.util;
84114
+ const divImageSettings = modal.querySelector('.div-image-generation-options');
84115
+ if (this.builder.generateMediaUrl_Fal) {
84116
+ divImageSettings.style.display = '';
84117
+ }
84118
+ const sizeDefs = {
84119
+ square_hd: util.out('Square HD'),
84120
+ square: util.out('Square'),
84121
+ landscape_4_3: util.out('Landscape 4x3'),
84122
+ landscape_16_9: util.out('Landscape 16x9'),
84123
+ portrait_4_3: util.out('Portrait 3x4'),
84124
+ portrait_16_9: util.out('Portrait 9x16'),
84125
+ '1:1': util.out('Square'),
84126
+ '3:2': util.out('Landscape 3x2'),
84127
+ '4:3': util.out('Landscape 4x3'),
84128
+ '5:4': util.out('Landscape 5x4'),
84129
+ '16:9': util.out('Landscape 16x9'),
84130
+ '2:3': util.out('Portrait 2x3'),
84131
+ '3:4': util.out('Portrait 3x4'),
84132
+ '4:5': util.out('Portrait 4x5'),
84133
+ '9:16': util.out('Portrait 9x16'),
84134
+ '21:9': util.out('Landscape 21:9'),
84135
+ '9:21': util.out('Landscape 9:21')
84136
+ };
84137
+
84138
+ // Default set
84139
+ const defaultSizes = ['square', 'square_hd', 'landscape_4_3', 'landscape_16_9', 'portrait_4_3', 'portrait_16_9'];
84140
+
84141
+ // Models
84142
+ let models = this.imageModels;
84143
+
84144
+ // Default selections
84145
+ const defaultModelId = this.builder.imageModel || 'fal-ai/flux-1/schnell';
84146
+ const defaultSize = this.builder.imageSize || 'landscape_4_3';
84147
+
84148
+ // Helper: return available sizes for a model
84149
+ function getSizesForModel(modelId) {
84150
+ const model = models.find(m => m.id === modelId);
84151
+ if (!model) return defaultSizes;
84152
+
84153
+ // if sizes explicitly empty array → means no size options
84154
+ if (Array.isArray(model.sizes) && model.sizes.length === 0) {
84155
+ return null;
84156
+ }
84157
+ return model.sizes || defaultSizes;
84158
+ }
83947
84159
 
84160
+ // Elements
84161
+ const modelSelect = modal.querySelector('#inpImageModelSelect');
84162
+ const sizeSelect = modal.querySelector('#inpImageSizeSelect');
84163
+ const sizeContainer = sizeSelect.closest('.div-size-container') || sizeSelect; // wrap div if you have one
84164
+ const outputFormatField = modal.querySelector('#inpImageOutputFormat'); // hidden input
84165
+
84166
+ // Populate model select
84167
+ models.forEach(m => {
84168
+ const option = document.createElement('option');
84169
+ option.value = m.id;
84170
+ option.textContent = m.label;
84171
+ modelSelect.appendChild(option);
84172
+ });
84173
+
84174
+ // Populate sizes when model changes
84175
+ const renderSizes = (modelId, keepSelected = true) => {
84176
+ const model = models.find(m => m.id === modelId);
84177
+ const prevValue = sizeSelect.value;
84178
+ sizeSelect.innerHTML = ''; // clear
84179
+
84180
+ const sizes = getSizesForModel(modelId);
84181
+ // Handle size visibility
84182
+ if (!sizes) {
84183
+ sizeContainer.style.display = 'none';
84184
+ } else {
84185
+ sizeContainer.style.display = 'flex';
84186
+ sizes.forEach(s => {
84187
+ const option = document.createElement('option');
84188
+ option.value = s;
84189
+ option.textContent = sizeDefs[s] || s;
84190
+ sizeSelect.appendChild(option);
84191
+ });
84192
+
84193
+ // Try to restore previous size selection
84194
+ if (keepSelected && sizes.includes(prevValue)) {
84195
+ sizeSelect.value = prevValue;
84196
+ } else if (sizes.includes(defaultSize)) {
84197
+ sizeSelect.value = defaultSize;
84198
+ } else {
84199
+ sizeSelect.value = sizes[0];
84200
+ }
84201
+ }
84202
+
84203
+ // Handle output_format if present
84204
+ if (outputFormatField && model) {
84205
+ outputFormatField.value = model.output_format || '';
84206
+ }
84207
+ };
84208
+ modelSelect.addEventListener('change', e => {
84209
+ renderSizes(e.target.value);
84210
+ });
84211
+
84212
+ // Trigger initial render with defaults
84213
+ modelSelect.value = defaultModelId;
84214
+ renderSizes(defaultModelId, false);
84215
+ }
83948
84216
  resetConfig() {
83949
84217
  const tempSlider = this.modalConfig.querySelector('.temperature-slider');
83950
84218
  const valTemp = this.modalConfig.querySelector('.val-temp');
@@ -94718,7 +94986,9 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
94718
94986
 
94719
94987
  if (!this.dom.getSelected()) {
94720
94988
  let inputFocused = document.activeElement.tagName.toLowerCase() === 'input';
94721
- let insideEditable = this.doc.activeElement && this.doc.activeElement.closest('[contenteditable]');
94989
+
94990
+ // let insideEditable = this.doc.activeElement && this.doc.activeElement.closest('[contenteditable]');
94991
+ let insideEditable = target.closest('[contenteditable]');
94722
94992
 
94723
94993
  // if(!document.querySelector('.is-modal.active')) { // Additional (to prevent lost focus)
94724
94994
  let openedModal = document.querySelector('.is-modal.active:not(.is-modal-content)');
@@ -98045,16 +98315,56 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
98045
98315
  }
98046
98316
 
98047
98317
  async generateImage_Fal(prompt, callback) {
98318
+ const modal = this.dictation.modalConfig;
98319
+
98320
+ // Construct inputs: model, prompt, size, output format
98321
+ const inpImageModelSelect = modal.querySelector('#inpImageModelSelect');
98322
+ const inpImageSizeSelect = modal.querySelector('#inpImageSizeSelect');
98323
+ const outputFormatField = modal.querySelector('#inpImageOutputFormat');
98324
+ const modelId = inpImageModelSelect.value;
98325
+ const modelDef = this.dictation.imageModels.find(m => m.id === modelId) || {};
98326
+
98327
+ // Build options dynamically
98328
+ let options = {};
98329
+
98330
+ // Handle size/aspect_ratio if model has sizes
98331
+ if (modelDef && modelDef.sizes !== undefined) {
98332
+ if (modelDef.sizes !== null && modelDef.sizes.length !== 0) {
98333
+ const sizeParam = modelDef.size_param || 'image_size'; // default
98334
+ const imageSize = inpImageSizeSelect.value;
98335
+ options[sizeParam] = imageSize;
98336
+ }
98337
+ // if sizes = [] => no size options => exclude size.
98338
+ } else {
98339
+ // if sizes not defined, use default set
98340
+ const imageSize = inpImageSizeSelect.value;
98341
+ options['image_size'] = imageSize;
98342
+ }
98343
+
98344
+ // Handle output_format if present
98345
+ const outputFormat = outputFormatField.value;
98346
+ if (outputFormat) {
98347
+ const outputParam = modelDef.output_param || 'output_format'; // default
98348
+ options[outputParam] = outputFormat;
98349
+ }
98350
+ // if output_format not defined, exclude output_format.
98351
+
98048
98352
  this.controller = new AbortController();
98049
98353
  this.signal = this.controller.signal;
98050
- let model = this.imageModel || 'flux-schnell';
98051
- let jsonBody = {};
98052
- jsonBody.model = model;
98053
- jsonBody.customData = this.customData;
98054
- jsonBody.endpoint = `https://queue.fal.run/${model}`;
98055
- jsonBody.payload = {
98056
- prompt
98354
+ let jsonBody = {
98355
+ model: modelId,
98356
+ customData: this.customData,
98357
+ endpoint: `https://queue.fal.run/${modelId}`,
98358
+ payload: {
98359
+ prompt,
98360
+ ...options
98361
+ }
98057
98362
  };
98363
+
98364
+ // console.log(jsonBody);
98365
+ // this.dictation.finish();
98366
+ // return;
98367
+
98058
98368
  let url = this.generateMediaUrl_Fal;
98059
98369
  let headers = {
98060
98370
  ...this.headers,
@@ -98079,9 +98389,9 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
98079
98389
  endpoint = endpoint.replace('{MODEL}', firstTwoParts);
98080
98390
  return endpoint;
98081
98391
  };
98082
- const statusEndpoint = getStatusEndpoint(model, requestId);
98392
+ const statusEndpoint = getStatusEndpoint(modelId, requestId);
98083
98393
  let inputCheckStatus = {
98084
- model,
98394
+ model: modelId,
98085
98395
  endpoint: statusEndpoint,
98086
98396
  request_id: requestId
98087
98397
  // customData: this.customData