codexly-ui 0.12.36 → 0.12.37

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.
@@ -9020,6 +9020,12 @@ class ClxEditorComponent {
9020
9020
  * plug in its own picker (e.g. an ERP's product/variant image browser) without this library
9021
9021
  * needing to know about that app's catalog backend. Resolve to undefined/null to cancel. */
9022
9022
  imagePicker = input(undefined, ...(ngDevMode ? [{ debugName: "imagePicker" }] : /* istanbul ignore next */ []));
9023
+ /** Adds an extra toolbar button (only rendered when provided) that inserts a raw HTML block at
9024
+ * the cursor — e.g. an ERP's "poster" template resolved against a chosen product/variant, where
9025
+ * the result is a whole <table> block, not a single <img>, so imagePicker's fixed <img>-only
9026
+ * output doesn't fit. The returned html is inserted as-is via insertHTML, no sanitization beyond
9027
+ * what insertHTML/_sanitizePaste already does for pasted content. */
9028
+ blockPicker = input(undefined, ...(ngDevMode ? [{ debugName: "blockPicker" }] : /* istanbul ignore next */ []));
9023
9029
  // ── View ─────────────────────────────────────────────────────────────────
9024
9030
  _bodyEl;
9025
9031
  _sourceEl;
@@ -9238,6 +9244,20 @@ class ClxEditorComponent {
9238
9244
  const ref = this._modal.open(ClxEditorImageModalComponent, { size: 'sm' });
9239
9245
  ref.afterClosed().then((result) => insert(result));
9240
9246
  }
9247
+ _openBlockPicker() {
9248
+ const picker = this.blockPicker();
9249
+ if (!picker)
9250
+ return;
9251
+ picker.fn().then(result => {
9252
+ if (!result?.html)
9253
+ return;
9254
+ this._restoreRange();
9255
+ this._bodyEl.nativeElement.focus();
9256
+ document.execCommand('insertHTML', false, result.html);
9257
+ this._emitChange();
9258
+ this._tick.update(v => v + 1);
9259
+ });
9260
+ }
9241
9261
  // ── Range save/restore ────────────────────────────────────────────────────
9242
9262
  _saveRange() {
9243
9263
  const sel = window.getSelection();
@@ -9356,7 +9376,7 @@ class ClxEditorComponent {
9356
9376
  this._cdr.markForCheck();
9357
9377
  }
9358
9378
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9359
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxEditorComponent, isStandalone: true, selector: "clx-editor", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, statusMessage: { classPropertyName: "statusMessage", publicName: "statusMessage", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, imagePicker: { classPropertyName: "imagePicker", publicName: "imagePicker", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "flex flex-col gap-1.5" }, providers: [
9379
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxEditorComponent, isStandalone: true, selector: "clx-editor", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, statusMessage: { classPropertyName: "statusMessage", publicName: "statusMessage", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, imagePicker: { classPropertyName: "imagePicker", publicName: "imagePicker", isSignal: true, isRequired: false, transformFunction: null }, blockPicker: { classPropertyName: "blockPicker", publicName: "blockPicker", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "flex flex-col gap-1.5" }, providers: [
9360
9380
  {
9361
9381
  provide: NG_VALUE_ACCESSOR,
9362
9382
  useExisting: forwardRef(() => ClxEditorComponent),
@@ -9462,6 +9482,25 @@ class ClxEditorComponent {
9462
9482
  </button>
9463
9483
 
9464
9484
  <div class="clx-editor-divider mx-1"></div>
9485
+
9486
+ <!-- Custom HTML block insert (e.g. an ERP's "insert poster" flow) -->
9487
+ @if (blockPicker(); as picker) {
9488
+ <button
9489
+ clx-button
9490
+ type="button"
9491
+ variant="ghost"
9492
+ [color]="_color()"
9493
+ size="xs"
9494
+ shape="rounded"
9495
+ [icon]="picker.icon"
9496
+ [iconOnly]="true"
9497
+ [title]="picker.title"
9498
+ (mousedown)="_saveRange()"
9499
+ (click)="_openBlockPicker()">
9500
+ </button>
9501
+
9502
+ <div class="clx-editor-divider mx-1"></div>
9503
+ }
9465
9504
  }
9466
9505
 
9467
9506
  <!-- HTML source toggle -->
@@ -9649,6 +9688,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
9649
9688
  </button>
9650
9689
 
9651
9690
  <div class="clx-editor-divider mx-1"></div>
9691
+
9692
+ <!-- Custom HTML block insert (e.g. an ERP's "insert poster" flow) -->
9693
+ @if (blockPicker(); as picker) {
9694
+ <button
9695
+ clx-button
9696
+ type="button"
9697
+ variant="ghost"
9698
+ [color]="_color()"
9699
+ size="xs"
9700
+ shape="rounded"
9701
+ [icon]="picker.icon"
9702
+ [iconOnly]="true"
9703
+ [title]="picker.title"
9704
+ (mousedown)="_saveRange()"
9705
+ (click)="_openBlockPicker()">
9706
+ </button>
9707
+
9708
+ <div class="clx-editor-divider mx-1"></div>
9709
+ }
9652
9710
  }
9653
9711
 
9654
9712
  <!-- HTML source toggle -->
@@ -9727,7 +9785,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
9727
9785
  <p [class]="_sizeCfg().hint + ' text-gray-400'">{{ hint() }}</p>
9728
9786
  }
9729
9787
  `, host: { class: 'flex flex-col gap-1.5' }, styles: [".clx-editor-body:empty:before{content:attr(data-placeholder);color:#9ca3af;pointer-events:none}.clx-editor-body:focus{outline:none}.clx-editor-body p{margin:0 0 .4em}.clx-editor-body p:last-child{margin-bottom:0}.clx-editor-body h1{font-size:1.5em;font-weight:700;margin:.5em 0}.clx-editor-body h2{font-size:1.25em;font-weight:600;margin:.5em 0}.clx-editor-body h3{font-size:1.1em;font-weight:600;margin:.5em 0}.clx-editor-body ul,.clx-editor-body ol{padding-left:1.5em;margin:.35em 0}.clx-editor-body li{margin:.1em 0}.clx-editor-body blockquote{border-left:3px solid #e2e8f0;padding-left:.75em;color:#64748b;margin:.4em 0}.clx-editor-body code{background:#f1f5f9;border-radius:3px;padding:.1em .3em;font-size:.875em;font-family:ui-monospace,monospace}.clx-editor-body a{color:#6366f1;text-decoration:underline}.clx-editor-body hr{border:none;border-top:1px solid #e2e8f0;margin:.6em 0}.clx-editor-color-btn{position:relative;overflow:hidden}.clx-editor-color-btn input[type=color]{position:absolute;inset:0;opacity:0;width:100%;height:100%;cursor:pointer;border:none;padding:0}.clx-editor-toolbar-select clx-select .flex.flex-col{gap:0!important}.clx-editor-source{width:100%;resize:none;border:none;outline:none;background:#0f172a;color:#e2e8f0;font-family:ui-monospace,Cascadia Code,Fira Code,monospace;font-size:.8125rem;line-height:1.6;padding:1rem;tab-size:2}\n"] }]
9730
- }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], statusMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusMessage", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], imagePicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "imagePicker", required: false }] }], _bodyEl: [{
9788
+ }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], statusMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusMessage", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], imagePicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "imagePicker", required: false }] }], blockPicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "blockPicker", required: false }] }], _bodyEl: [{
9731
9789
  type: ViewChild,
9732
9790
  args: ['bodyEl', { static: false }]
9733
9791
  }], _sourceEl: [{