Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion docs/guides/migration.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ for each option it deselected and reporting the shortened value to the form cont

### 18. Component review (20.3.0)

Ten components went through a full review in 20.3.0: notification-center, popover, search-expandable, select, split-button, title, toast, tooltip, tree and tree-select. Each review closed the members that were never part of the component's contract, moved inputs to signals where that was the point of it, and fixed the behavior it uncovered along the way. Only the changes that reach a consumer are listed here.
Components went through a full review in 20.3.0, in two waves. The first covered notification-center, popover, search-expandable, select, split-button, title, toast, tooltip, tree and tree-select; the second is the one each subsection below belongs to. Each review closed the members that were never part of the component's contract, moved inputs to signals where that was the point of it, and fixed the behavior it uncovered along the way. Only the changes that reach a consumer are listed here.

Every schematic named below runs automatically:

Expand Down Expand Up @@ -1093,6 +1093,30 @@ A `<kbq-split-button>` with no projected button no longer throws outside dev mod

Reported by `split-button-optional-disabled`.

#### Splitter

Every input on the splitter and its gutter was an accessor with coercion in the setter, which is why the automated signal migration skipped all thirteen. They are signal inputs now, with `booleanAttribute` and `numberAttribute` doing the coercion.

`KbqGutterGhostDirective` went the other way. Its `visible`, `x`, `y`, `direction` and `size` were `@Input()` in name only: the splitter renders `<kbq-gutter-ghost>` with no bindings and drives them imperatively during a drag, outside the Angular zone. They are plain properties now, so a template binding on them stops compiling — there was never a supported way to place the ghost yourself.

| Pattern | Manual migration |
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| `.hideGutters` / `.direction` / `.disabled` / `.useGhost` / `.gutterSize` | Read as calls — rewritten for you |
| `.isDragging` / `.isVertical` | Read as calls — rewritten for you |
| `gutter.direction` / `.order` / `.size` / `.isVertical` / `.dragged` | Read as calls — rewritten for you |
| `.resizing` | Removed — it was dead and always `false`; use `isDragging()` |
| `.elementRef` / `.changeDetectorRef` / `.areas` / `.areaRefs` / `.gutters` / `.ghost` | Closed layout bookkeeping |

**`hideGutters`, `disabled` and `useGhost` are `booleanAttribute` inputs now.** A valueless attribute means `true`; `coerceBooleanProperty` treated the empty string as `false`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaking change does not exist — coerceBooleanProperty('') already returned true.

// @angular/cdk/fesm2022/coercion.mjs
coerceBooleanProperty = (v) => v != null && `${v}` !== 'false';   // ''  -> true
// @angular/core
booleanAttribute      = (v) => typeof v === 'boolean' ? v : (v != null && v !== 'false');  // '' -> true

A static attribute with no value reaches a non-signal @Input as '', so <kbq-splitter disabled hideGutters useGhost> resolved to true on the base commit too. The two helpers agree on every input this component accepts ('', 'false', 'true', null, undefined, 0).

The claim is repeated in four places — here, migration.ru.md:1114, splitter-signals/README.md:41-42, and data.ts:97 (the per-project ng update summary). A consumer with <kbq-splitter useGhost> reads it, concludes the ghost used to be off, and "fixes" working markup to [useGhost]="false". The new valueless attributes spec asserts true and would have passed on the base commit, so it documents the false claim rather than guarding a change.

Two more inaccuracies in the same section:

  • :1038 — "the second is the one each subsection below belongs to", but three of the four #### subsections under section 18 are Search expandable, Split button and Title, all named in the first-wave list in the same sentence. Only Splitter is second-wave, and the sentence gets wronger with every component appended.
  • :1098 — "the automated signal migration skipped all thirteen. They are signal inputs now". 13 = 5 splitter + 3 gutter + 5 ghost, but the ghost's five became plain properties, which the very next paragraph says. Only eight became signal inputs — and two of the thirteen (direction on the splitter and on the gutter) had no coercion in their setter either.


**A `gutterSize` that is not a positive number falls back to the default 6** instead of keeping whatever the previous value happened to be. The old setter read its own getter, so an invalid value silently preserved the last valid one.

**The gutter lays itself out reactively** instead of once in `ngOnInit`, so changing `direction` after init re-applies the layout — and clears the dimension the other direction owns, which used to stay behind as a stale `width` or `height`.

**A splitter area unsubscribes from `gutterPositionChange` when it is destroyed.** An area removed from a long-lived splitter used to keep emitting `sizeChange` for every later drag.

Handled by `splitter-signals`: the reads and the `dragged` write are rewritten, the rest is reported.

#### Title

`kbq-title` measures its host and opens a tooltip when the text is truncated. The review kept that surface — the `kbq-title` input and the tooltip it opens — and closed the measurement machinery behind it.
Expand Down
26 changes: 25 additions & 1 deletion docs/guides/migration.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ ng g @koobiq/components:list-tree-multiple-input --project <your project>

### 18. Ревью компонентов (20.3.0)

В 20.3.0 полное ревью прошли десять компонентов: notification-center, popover, search-expandable, select, split-button, title, toast, tooltip, tree и tree-select. Каждое ревью закрывало члены, которые никогда не были частью контракта компонента, переводило входы на сигналы там, где в этом и был его смысл, и попутно исправляло найденные ошибки поведения. Ниже перечислено только то, что доходит до потребителя.
В 20.3.0 полное ревью прошло в две волны. В первую вошли notification-center, popover, search-expandable, select, split-button, title, toast, tooltip, tree и tree-select; ко второй относится каждый из подразделов ниже. Каждое ревью закрывало члены, которые никогда не были частью контракта компонента, переводило входы на сигналы там, где в этом и был его смысл, и попутно исправляло найденные ошибки поведения. Ниже перечислено только то, что доходит до потребителя.

Все схематики, названные ниже, запускаются автоматически:

Expand Down Expand Up @@ -1097,6 +1097,30 @@ if (splitButton.disabled === false) {

Сообщает `split-button-optional-disabled`.

#### Splitter

Все входы сплиттера и его разделителя были геттерами и сеттерами с приведением типов внутри, поэтому автоматическая миграция на сигналы пропустила все тринадцать. Теперь это сигнальные входы, а приведением занимаются `booleanAttribute` и `numberAttribute`.

С `KbqGutterGhostDirective` произошло обратное. Его `visible`, `x`, `y`, `direction` и `size` были `@Input()` только по названию: сплиттер отрисовывает `<kbq-gutter-ghost>` вообще без привязок и задаёт их императивно во время перетаскивания, вне зоны Angular. Теперь это обычные свойства, поэтому привязка в шаблоне перестанет компилироваться — поддерживаемого способа расположить «призрак» самому никогда и не было.

| Что было | Как мигрировать вручную |
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `.hideGutters` / `.direction` / `.disabled` / `.useGhost` / `.gutterSize` | Читать как вызовы — переписывается за вас |
| `.isDragging` / `.isVertical` | Читать как вызовы — переписывается за вас |
| `gutter.direction` / `.order` / `.size` / `.isVertical` / `.dragged` | Читать как вызовы — переписывается за вас |
| `.resizing` | Удалён — он был мёртвым и всегда возвращал `false`; используйте `isDragging()` |
| `.elementRef` / `.changeDetectorRef` / `.areas` / `.areaRefs` / `.gutters` / `.ghost` | Закрытая внутренняя кухня раскладки |

**`hideGutters`, `disabled` и `useGhost` стали `booleanAttribute`-входами.** Атрибут без значения теперь означает `true`; `coerceBooleanProperty` считал пустую строку ложью.

**`gutterSize`, который не является положительным числом, откатывается к значению по умолчанию — 6**, а не сохраняет предыдущее значение. Старый сеттер читал собственный геттер, поэтому некорректное значение молча оставляло последнее корректное.

**Разделитель пересчитывает свою раскладку реактивно**, а не один раз в `ngOnInit`, поэтому смена `direction` после инициализации теперь применяется — и очищает размер, принадлежащий другому направлению, который раньше оставался залипшим `width` или `height`.

**Область сплиттера отписывается от `gutterPositionChange` при уничтожении.** Область, удалённая из долгоживущего сплиттера, раньше продолжала отправлять `sizeChange` при каждом последующем перетаскивании.

Закрывается схематиком `splitter-signals`: чтения и запись в `dragged` переписываются, остальное сообщается в отчёте.

#### Title

`kbq-title` измеряет свой хост и открывает тултип, когда текст обрезан. Ревью сохранило эту поверхность — вход `kbq-title` и открываемый тултип — и закрыло стоящий за ней механизм измерения.
Expand Down
10 changes: 5 additions & 5 deletions packages/components/splitter/splitter.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
@for (area of areas; track area) {
@if (!$last) {
<kbq-gutter
[attr.disabled]="disabled || null"
[direction]="direction"
[attr.disabled]="disabled() || null"
[direction]="direction()"
[order]="$index * 2 + 1"
[size]="gutterSize"
[style.display]="hideGutters ? 'none' : 'flex'"
[size]="gutterSize()"
[style.display]="hideGutters() ? 'none' : 'flex'"
(mousedown)="onMouseDown($event, $index, $index + 1)"
/>
}
}

@if (useGhost) {
@if (useGhost()) {
<kbq-gutter-ghost />
}
Loading