@phuong-tran-redoc/document-engine-angular 0.1.5 → 0.1.6

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/README.md CHANGED
@@ -206,6 +206,12 @@ the contract.** It lists every token the library reads
206
206
  hardcodes a colour.
207
207
  - `--de-editor-min-height` (default `12rem`) sets the editing surface's floor; alternatively give the
208
208
  `document-engine-editor` element a real height and the surface fills it.
209
+ - **The editing surface does not scroll internally — it grows, and the page scrolls.** `0.1.5` briefly
210
+ made it a scroll container; that was reverted in `0.1.6` because the selection bubble menu is an
211
+ absolutely-positioned descendant of it, so the scroller became the panel's clip rect and a dropdown
212
+ opening upward lost its top options to the clip. If you need a fixed-height box that scrolls its
213
+ content, put `overflow: auto` on **your own** wrapper around `document-engine-editor`, never on
214
+ `.tiptap-editor`.
209
215
  - Prose and editing-affordance styles are **opt-in** subpaths (`styles/editor-content`,
210
216
  `styles/editor-interaction`), so the baseline can never impose a look on your documents.
211
217
 
@@ -3733,6 +3733,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
3733
3733
  args: [ToggleOptionDirective, { descendants: true }]
3734
3734
  }] } });
3735
3735
 
3736
+ /**
3737
+ * Normalize what a user typed into the border-width field into a valid CSS length.
3738
+ *
3739
+ * The field is a free-text input, and `border-width: 3` is not a valid declaration —
3740
+ * the browser drops it silently, so typing a bare number used to do nothing at all
3741
+ * with no feedback. A bare number is the single most likely thing to type, and in a
3742
+ * length context it conventionally means pixels, so it is completed to `px`.
3743
+ *
3744
+ * Anything already carrying a unit is left alone (only the unit is lower-cased).
3745
+ *
3746
+ * The two failure modes are deliberately NOT the same value, because the command this
3747
+ * feeds reads `null` as "clear this field" and `undefined` as "leave it alone":
3748
+ *
3749
+ * - an **empty** field is a real instruction to clear the width, so it returns `null`;
3750
+ * - **unusable** input (`abc`, `-2px`, `50%`) returns `undefined`, so a typo leaves the
3751
+ * width the cell already had instead of wiping it. Collapsing the two would mean a
3752
+ * user with a working `1px` border who mistypes `3 pixels` loses it on Save with no
3753
+ * message — the field is free text, so mistyping it is the expected case, not a rare one.
3754
+ *
3755
+ * @returns a valid CSS border-width; `null` to clear it; `undefined` to leave it alone.
3756
+ */
3757
+ function normalizeBorderWidth(input) {
3758
+ const value = (input ?? '').trim();
3759
+ if (!value)
3760
+ return null;
3761
+ // `thin | medium | thick` are valid border-width keywords in their own right.
3762
+ if (/^(thin|medium|thick)$/i.test(value))
3763
+ return value.toLowerCase();
3764
+ // A bare number — the case this helper exists for. Border widths cannot be
3765
+ // negative, so a signed value is rejected rather than quietly clamped.
3766
+ if (/^\d+(\.\d+)?$/.test(value))
3767
+ return `${parseFloat(value)}px`;
3768
+ // Already a length. Units per CSS Values 4; `%` is not valid for border-width.
3769
+ const withUnit = /^(\d+(?:\.\d+)?)\s*(px|em|rem|pt|pc|in|cm|mm|q|ch|ex|vh|vw|vmin|vmax)$/i.exec(value);
3770
+ if (withUnit)
3771
+ return `${parseFloat(withUnit[1])}${withUnit[2].toLowerCase()}`;
3772
+ // Not a border-width at all — leave whatever the cell already has untouched.
3773
+ return undefined;
3774
+ }
3775
+
3736
3776
  /**
3737
3777
  * Cell style view for table bubble menu
3738
3778
  * Allows styling individual table cells (borders, background, alignment)
@@ -3834,10 +3874,14 @@ class TableCellStyleViewComponent {
3834
3874
  this.cdr.markForCheck();
3835
3875
  }
3836
3876
  onSave() {
3877
+ // See `normalizeBorderWidth`: a bare number is completed to `px` so the field does
3878
+ // not silently do nothing, and unusable input yields `undefined` so the command
3879
+ // leaves the width the cell already has rather than clearing it.
3880
+ const width = normalizeBorderWidth(this.borderWidth);
3837
3881
  this.editor
3838
3882
  ?.chain()
3839
3883
  .focus()
3840
- .setCellBorder({ style: this.borderStyle, color: this.borderColor, width: this.borderWidth })
3884
+ .setCellBorder({ style: this.borderStyle, color: this.borderColor, width })
3841
3885
  .setCellBackgroundColor(this.backgroundColor)
3842
3886
  .setCellTextAlign(this.textAlign)
3843
3887
  .setCellVerticalAlign(this.vAlign)
@@ -3902,6 +3946,7 @@ class TableCellStyleViewComponent {
3902
3946
  <button
3903
3947
  #borderColorTrigger
3904
3948
  type="button"
3949
+ data-testid="border-color-trigger"
3905
3950
  class="table-cell-style-view__color-swatch"
3906
3951
  [style.background-color]="borderColor || 'transparent'"
3907
3952
  (click)="toggleColorPicker('border')"
@@ -3955,6 +4000,7 @@ class TableCellStyleViewComponent {
3955
4000
  <button
3956
4001
  #bgColorTrigger
3957
4002
  type="button"
4003
+ data-testid="background-color-trigger"
3958
4004
  class="table-cell-style-view__color-swatch"
3959
4005
  [style.background-color]="backgroundColor || 'transparent'"
3960
4006
  (click)="toggleColorPicker('bg')"
@@ -4095,6 +4141,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
4095
4141
  <button
4096
4142
  #borderColorTrigger
4097
4143
  type="button"
4144
+ data-testid="border-color-trigger"
4098
4145
  class="table-cell-style-view__color-swatch"
4099
4146
  [style.background-color]="borderColor || 'transparent'"
4100
4147
  (click)="toggleColorPicker('border')"
@@ -4148,6 +4195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
4148
4195
  <button
4149
4196
  #bgColorTrigger
4150
4197
  type="button"
4198
+ data-testid="background-color-trigger"
4151
4199
  class="table-cell-style-view__color-swatch"
4152
4200
  [style.background-color]="backgroundColor || 'transparent'"
4153
4201
  (click)="toggleColorPicker('bg')"
@@ -4631,7 +4679,7 @@ class TableMainViewComponent {
4631
4679
  </document-engine-select>
4632
4680
 
4633
4681
  <!-- Cell actions -->
4634
- <document-engine-select [(value)]="cellAction" (valueChange)="handleCellAction($event)" labelMode="static">
4682
+ <document-engine-select data-testid="cell-actions" [(value)]="cellAction" (valueChange)="handleCellAction($event)" labelMode="static">
4635
4683
  <document-engine-icon documentEngineSelectLabel name="table_merge_cell"></document-engine-icon>
4636
4684
 
4637
4685
  <button documentEngineSelectOption data-testid="merge-cells" value="merge" [disabled]="!canMerge">
@@ -4693,7 +4741,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
4693
4741
  </document-engine-select>
4694
4742
 
4695
4743
  <!-- Cell actions -->
4696
- <document-engine-select [(value)]="cellAction" (valueChange)="handleCellAction($event)" labelMode="static">
4744
+ <document-engine-select data-testid="cell-actions" [(value)]="cellAction" (valueChange)="handleCellAction($event)" labelMode="static">
4697
4745
  <document-engine-icon documentEngineSelectLabel name="table_merge_cell"></document-engine-icon>
4698
4746
 
4699
4747
  <button documentEngineSelectOption data-testid="merge-cells" value="merge" [disabled]="!canMerge">
@@ -4829,10 +4877,14 @@ class TableStyleViewComponent {
4829
4877
  const editor = this.editor;
4830
4878
  if (!editor)
4831
4879
  return;
4880
+ // Complete a bare number to `px` before it reaches the command; `border-width: 3`
4881
+ // is invalid CSS and would be dropped without any feedback. `undefined` here means
4882
+ // the input was not a width at all, and the command leaves the current one alone.
4883
+ const width = normalizeBorderWidth(this.borderWidth);
4832
4884
  editor
4833
4885
  .chain()
4834
4886
  .focus()
4835
- .setTableBorder({ style: this.borderStyle, color: this.borderColor, width: this.borderWidth })
4887
+ .setTableBorder({ style: this.borderStyle, color: this.borderColor, width })
4836
4888
  .setTableBackgroundColor(this.tableBg)
4837
4889
  .run();
4838
4890
  this.cancel();
@@ -4896,6 +4948,7 @@ class TableStyleViewComponent {
4896
4948
  <button
4897
4949
  #borderColorTrigger
4898
4950
  type="button"
4951
+ data-testid="border-color-trigger"
4899
4952
  class="table-style-view__color-swatch"
4900
4953
  [style.background-color]="borderColor || 'transparent'"
4901
4954
  (click)="toggleColorPicker('border')"
@@ -4949,6 +5002,7 @@ class TableStyleViewComponent {
4949
5002
  <button
4950
5003
  #bgColorTrigger
4951
5004
  type="button"
5005
+ data-testid="background-color-trigger"
4952
5006
  class="table-style-view__color-swatch"
4953
5007
  [style.background-color]="tableBg || 'transparent'"
4954
5008
  (click)="toggleColorPicker('bg')"
@@ -5053,6 +5107,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
5053
5107
  <button
5054
5108
  #borderColorTrigger
5055
5109
  type="button"
5110
+ data-testid="border-color-trigger"
5056
5111
  class="table-style-view__color-swatch"
5057
5112
  [style.background-color]="borderColor || 'transparent'"
5058
5113
  (click)="toggleColorPicker('border')"
@@ -5106,6 +5161,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
5106
5161
  <button
5107
5162
  #bgColorTrigger
5108
5163
  type="button"
5164
+ data-testid="background-color-trigger"
5109
5165
  class="table-style-view__color-swatch"
5110
5166
  [style.background-color]="tableBg || 'transparent'"
5111
5167
  (click)="toggleColorPicker('bg')"