@innovastudio/contentbuilder 1.5.156 → 1.5.158

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
@@ -331,5 +331,11 @@ declare class ContentBuilder {
331
331
 
332
332
  generateImage(prompt: string, callback?: () => void): void;
333
333
  openFilePicker(type?: string, callback?: () => void): void;
334
+ openColorPicker(
335
+ currentColor: string,
336
+ callback: (color: string) => void,
337
+ btn?: HTMLElement
338
+ ): void;
339
+ openIconPicker(callback: (iconHtml: string) => void): void;
334
340
  }
335
341
  export default ContentBuilder;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@innovastudio/contentbuilder",
3
3
  "type": "module",
4
- "version": "1.5.156",
4
+ "version": "1.5.158",
5
5
  "description": "",
6
6
  "main": "public/contentbuilder/contentbuilder.esm.js",
7
7
  "types": "index.d.ts",
@@ -3974,7 +3974,9 @@ button:focus-visible {
3974
3974
  box-shadow: none;
3975
3975
  }
3976
3976
  #_cbhtml input[type=text],
3977
- .is-ui input[type=text] {
3977
+ #_cbhtml input[type=number],
3978
+ .is-ui input[type=text],
3979
+ .is-ui input[type=number] {
3978
3980
  width: 100%;
3979
3981
  height: 43px;
3980
3982
  box-sizing: border-box;
@@ -3992,14 +3994,20 @@ button:focus-visible {
3992
3994
  background-color: #f6f6f6;
3993
3995
  }
3994
3996
  #_cbhtml input[type=text]:focus,
3995
- .is-ui input[type=text]:focus {
3997
+ #_cbhtml input[type=number]:focus,
3998
+ .is-ui input[type=text]:focus,
3999
+ .is-ui input[type=number]:focus {
3996
4000
  outline: #3e93f7 2px solid;
3997
4001
  outline-offset: -2px;
3998
4002
  box-shadow: none;
3999
4003
  }
4000
4004
  #_cbhtml input[type=text] [type=checkbox], #_cbhtml input[type=text] [type=radio],
4005
+ #_cbhtml input[type=number] [type=checkbox],
4006
+ #_cbhtml input[type=number] [type=radio],
4001
4007
  .is-ui input[type=text] [type=checkbox],
4002
- .is-ui input[type=text] [type=radio] {
4008
+ .is-ui input[type=text] [type=radio],
4009
+ .is-ui input[type=number] [type=checkbox],
4010
+ .is-ui input[type=number] [type=radio] {
4003
4011
  position: relative;
4004
4012
  opacity: 1;
4005
4013
  margin-top: 0;
@@ -14481,6 +14481,8 @@ class HtmlUtil {
14481
14481
  }
14482
14482
  util.clearControls(); // NEW
14483
14483
 
14484
+ // Re-init plugins
14485
+ if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize();
14484
14486
  this.builder.hideModal(modal);
14485
14487
  }
14486
14488
  viewHtmlExternal() {
@@ -15910,7 +15912,7 @@ const prepareSvgIcons = builder => {
15910
15912
  <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15911
15913
  <path d="M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2"></path>
15912
15914
  </symbol>
15913
- <symbol id="icon-folder" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15915
+ <symbol id="icon-folder" viewBox="0 0 24 24" stroke-width="1.4" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15914
15916
  <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15915
15917
  <path d="M11 19h-6a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2h4l3 3h7a2 2 0 0 1 2 2v2.5"></path>
15916
15918
  <path d="M18 18m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0"></path>
@@ -52601,6 +52603,10 @@ class Element$1 {
52601
52603
 
52602
52604
  // Set contentEditable FALSE on special elements
52603
52605
 
52606
+ const plugins = col.querySelectorAll('[data-cb-type]'); // plugins
52607
+ Array.prototype.forEach.call(plugins, plugin => {
52608
+ plugin.contentEditable = false;
52609
+ });
52604
52610
  let sociallinks = col.querySelectorAll('.is-social');
52605
52611
  Array.prototype.forEach.call(sociallinks, sociallink => {
52606
52612
  sociallink.contentEditable = false;
@@ -97178,6 +97184,143 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
97178
97184
  fromViewToActual(html) {
97179
97185
  return this.htmlutil.fromViewToActual(html);
97180
97186
  }
97187
+ openColorPicker(currentColor, callback, btn) {
97188
+ this.colorPicker.open(callback, currentColor, () => {}, btn);
97189
+ }
97190
+ openIconPicker(callback) {
97191
+ let iconModal = this.builderStuff.querySelector('.is-modal.iconselect');
97192
+ if (!iconModal) {
97193
+ // Create modal with search input and event listeners once
97194
+ let html = `
97195
+ <style>
97196
+ .is-modal.iconselect .icon-search-wrapper {
97197
+ position: sticky;
97198
+ top: 0;
97199
+ background: white;
97200
+ padding: 20px;
97201
+ border-bottom: 1px solid #ddd;
97202
+ z-index: 10;
97203
+ }
97204
+ .is-modal.iconselect .icon-search {
97205
+ width: 100%;
97206
+ padding: 10px 15px;
97207
+ font-size: 16px;
97208
+ border: 1px solid #ccc;
97209
+ border-radius: 4px;
97210
+ box-sizing: border-box;
97211
+ }
97212
+ .is-modal.iconselect .icon-search:focus {
97213
+ outline: none;
97214
+ border-color: #007bff;
97215
+ }
97216
+ .is-modal.iconselect .icon-list {
97217
+ display: flex;
97218
+ gap: 10px;
97219
+ flex-flow: wrap;
97220
+ padding: 20px;
97221
+ }
97222
+ .is-modal.iconselect .icon-list > button {
97223
+ display: flex !important;
97224
+ width: 80px !important;
97225
+ height: 80px !important;
97226
+ flex: none;
97227
+ font-size: 30px !important;
97228
+ box-shadow: none !important;
97229
+ align-items: center;
97230
+ justify-content: center;
97231
+ }
97232
+ .is-modal.iconselect .icon-list > button.hidden {
97233
+ display: none !important;
97234
+ }
97235
+ .is-modal.iconselect .no-results {
97236
+ padding: 40px 20px;
97237
+ text-align: center;
97238
+ color: #666;
97239
+ display: none;
97240
+ }
97241
+ .is-modal.iconselect .no-results.show {
97242
+ display: block;
97243
+ }
97244
+ </style>
97245
+ <div class="is-modal iconselect" tabindex="-1" role="dialog" aria-modal="true" aria-hidden="true">
97246
+ <div class="is-modal-content scroll" style="width: 90vw; max-width: 908px; height: 70vh; min-height: 525px; padding: 0;">
97247
+ <div style="height: 100%; overflow-y: auto; display: flex; flex-direction: column;">
97248
+ <div class="icon-search-wrapper">
97249
+ <input type="text" class="icon-search" placeholder="Search icons... (e.g., alarm, wrench)" />
97250
+ </div>
97251
+ <div class="icon-list"></div>
97252
+ <div class="no-results">No icons found matching your search.</div>
97253
+ </div>
97254
+ </div>
97255
+ </div>
97256
+ `;
97257
+ this.dom.appendHtml(this.builderStuff, html);
97258
+ iconModal = this.builderStuff.querySelector('.is-modal.iconselect');
97259
+ this.iconModal = iconModal;
97260
+ const iconList = this.builderStuff.querySelector('.icon-list');
97261
+ const searchInput = this.builderStuff.querySelector('.icon-search');
97262
+ const noResults = this.builderStuff.querySelector('.no-results');
97263
+ iconList.innerHTML = this.rte.getIcons2() + this.rte.getIcons();
97264
+ let icons = iconList.querySelectorAll('button');
97265
+
97266
+ // Add click handlers for icons
97267
+ icons.forEach(icon => {
97268
+ icon.addEventListener('click', () => {
97269
+ // Get the current callback from the modal's data
97270
+ const currentCallback = iconModal._currentCallback;
97271
+ if (currentCallback) {
97272
+ currentCallback(icon.innerHTML);
97273
+ }
97274
+ this.util.hideModal(iconModal);
97275
+ });
97276
+ });
97277
+
97278
+ // Add search/filter functionality
97279
+ searchInput.addEventListener('input', e => {
97280
+ const searchTerm = e.target.value.toLowerCase().trim();
97281
+ let visibleCount = 0;
97282
+ icons.forEach(icon => {
97283
+ const iconElement = icon.querySelector('i');
97284
+ if (!iconElement) return;
97285
+
97286
+ // Get class names from the icon
97287
+ const iconClasses = iconElement.className.toLowerCase();
97288
+
97289
+ // Check if search term matches any part of the icon classes
97290
+ if (searchTerm === '' || iconClasses.includes(searchTerm)) {
97291
+ icon.classList.remove('hidden');
97292
+ visibleCount++;
97293
+ } else {
97294
+ icon.classList.add('hidden');
97295
+ }
97296
+ });
97297
+
97298
+ // Show/hide no results message
97299
+ if (visibleCount === 0 && searchTerm !== '') {
97300
+ noResults.classList.add('show');
97301
+ } else {
97302
+ noResults.classList.remove('show');
97303
+ }
97304
+ });
97305
+
97306
+ // Clear search when modal is opened
97307
+ iconModal.addEventListener('modalshow', () => {
97308
+ searchInput.value = '';
97309
+ searchInput.dispatchEvent(new Event('input'));
97310
+ });
97311
+ }
97312
+
97313
+ // Store the current callback and reset search
97314
+ iconModal._currentCallback = callback;
97315
+ const searchInput = iconModal.querySelector('.icon-search');
97316
+ if (searchInput) {
97317
+ searchInput.value = '';
97318
+ searchInput.dispatchEvent(new Event('input'));
97319
+ // Focus search input after a brief delay to ensure modal is visible
97320
+ setTimeout(() => searchInput.focus(), 100);
97321
+ }
97322
+ this.util.showModal(iconModal);
97323
+ }
97181
97324
  colorpicker(onPick, defaultcolor) {
97182
97325
  // return new ColorPicker({
97183
97326
  // onPick: onPick,