feat: support providing global custom gutter component#534
feat: support providing global custom gutter component#534Harpush wants to merge 2 commits intoangular-split:mainfrom
Conversation
698fa8e to
c0eaf83
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds a new way to globally customize the split gutter via dependency injection (gutterComponent), while also refining cursor/drag behavior based on whether gutters expose explicit drag handles or excluded regions.
Changes:
- Add
gutterComponentto globalAngularSplitDefaultOptions(with hierarchical injector inheritance viaprovideAngularSplitOptions). - Update
SplitComponentrendering to preferGutterTemplate > GutterComponent > Default(usingNgComponentOutlet) and adjust default gutter cursor behavior when handles exist. - Introduce
SplitGuttersManagerServiceand update gutter handle/exclude directives to register themselves and control drag start + cursor styling.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/app/examples/custom-gutter-style/custom-gutter.component.ts | New example custom gutter component used as an injected gutterComponent. |
| src/app/examples/custom-gutter-style/custom-gutter-style.component.ts | Updates example to use provideAngularSplitOptions({ gutterComponent }) and adjusts cursor suppression on excludes. |
| src/app/examples/custom-gutter-style/custom-gutter-style.component.scss | Removes now-inlined example A gutter styling. |
| projects/angular-split/src/public_api.ts | Exposes new gutter-related types publicly. |
| projects/angular-split/src/lib/split/split.component.ts | Adds manager service + uses it to gate drag start; imports NgComponentOutlet. |
| projects/angular-split/src/lib/split/split.component.html | Renders injected gutter component when no gutter template is provided. |
| projects/angular-split/src/lib/split/split.component.css | Removes default resize cursor when gutters have handles; relies on handle/exclude directives for cursor. |
| projects/angular-split/src/lib/gutter/split-gutters-manager.service.ts | New per-split service to track handles/excludes and decide if drag can start. |
| projects/angular-split/src/lib/gutter/split-gutter.directive.ts | Simplifies gutter directive to template-only; context type now aliases the shared context. |
| projects/angular-split/src/lib/gutter/split-gutter-exclude-from-drag.directive.ts | Registers excludes with manager + adds default cursor styling (optionally suppressed). |
| projects/angular-split/src/lib/gutter/split-gutter-drag-handle.directive.ts | Registers handles with manager + adds resize cursor styling (optionally suppressed). |
| projects/angular-split/src/lib/gutter/split-gutter-context.ts | New shared context type for both template and component gutters. |
| projects/angular-split/src/lib/gutter/split-gutter-component.ts | New interface describing the expected gutter component contract. |
| projects/angular-split/src/lib/angular-split-config.token.ts | Adds gutterComponent option to defaults and supports DI-based overrides. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| elements.splice(elements.indexOf(elementRef), 1) | ||
|
|
There was a problem hiding this comment.
removeFromMap assumes the gutter entry exists and that elementRef is present in the array. If map.get(gutterNum) returns undefined (e.g. due to mismatched gutterNum / double-destroy) this will throw, and if indexOf(elementRef) returns -1 it will incorrectly remove the last element. Consider guarding for missing entries and a missing index (no-op) before splicing, and only deleting the key when the array is truly empty.
| elements.splice(elements.indexOf(elementRef), 1) | |
| if (!elements) { | |
| return | |
| } | |
| const elementIndex = elements.indexOf(elementRef) | |
| if (elementIndex === -1) { | |
| return | |
| } | |
| elements.splice(elementIndex, 1) |
| import type { SplitGutterContext } from './split-gutter-context' | ||
|
|
||
| export interface SplitGutterComponent { | ||
| context: InputSignal<SplitGutterContext> |
There was a problem hiding this comment.
SplitGutterComponent currently requires context: InputSignal<SplitGutterContext>, which forces consumers to use the signal-based input() API to satisfy gutterComponent: Type<SplitGutterComponent>. Since *ngComponentOutlet will also work with a classic @Input() context: SplitGutterContext, consider widening the contract (e.g., context: SplitGutterContext | InputSignal<SplitGutterContext>) so consumers aren’t artificially constrained by types.
| context: InputSignal<SplitGutterContext> | |
| context: SplitGutterContext | InputSignal<SplitGutterContext> |
|
@Harpush A pulled CP in. Not sure the points are valid, I'll leave that up to you. |
|
@SanderElias |
|
@Harpush works out for me, I approved! |
|
@SanderElias great! So you can merge and hopefully we can publish a new angular 20 version before migrating to 21 |
Add support for customizing the gutter using dependency injection by providing a gutter component.
The priority is:
GutterTemplate > GutterComponent > Default.For example:
Due to the inheritance of the split options the above snippet will only override the
gutterComponentwhile keeping the rest of the options from the parent injector.The second commit adds cursor control. The default
resizecursor is applied when no custom gutter is given or when the custom gutter has no handles. If there are handles the defaultresizecursor is removed.Each handle adds
resizecursor unlesssuppressDefaultCursoris added.Each exclude adds
defaultcursor unlesssuppressDefaultCursoris added.