Skip to content

feat: support providing global custom gutter component#534

Open
Harpush wants to merge 2 commits intoangular-split:mainfrom
Harpush:global-custom-gutter-component
Open

feat: support providing global custom gutter component#534
Harpush wants to merge 2 commits intoangular-split:mainfrom
Harpush:global-custom-gutter-component

Conversation

@Harpush
Copy link
Copy Markdown
Collaborator

@Harpush Harpush commented Apr 2, 2026

Add support for customizing the gutter using dependency injection by providing a gutter component.
The priority is: GutterTemplate > GutterComponent > Default.
For example:

providers: [provideAngularSplitOptions({ gutterComponent: CustomGutterComponent })],

Due to the inheritance of the split options the above snippet will only override the gutterComponent while keeping the rest of the options from the parent injector.

The second commit adds cursor control. The default resize cursor is applied when no custom gutter is given or when the custom gutter has no handles. If there are handles the default resize cursor is removed.
Each handle adds resize cursor unless suppressDefaultCursor is added.
Each exclude adds default cursor unless suppressDefaultCursor is added.

@Harpush Harpush requested review from Jefiozie and SanderElias April 2, 2026 12:35
@Harpush Harpush force-pushed the global-custom-gutter-component branch from 698fa8e to c0eaf83 Compare April 2, 2026 18:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 gutterComponent to global AngularSplitDefaultOptions (with hierarchical injector inheritance via provideAngularSplitOptions).
  • Update SplitComponent rendering to prefer GutterTemplate > GutterComponent > Default (using NgComponentOutlet) and adjust default gutter cursor behavior when handles exist.
  • Introduce SplitGuttersManagerService and 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.

Comment on lines +86 to +87
elements.splice(elements.indexOf(elementRef), 1)

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
elements.splice(elements.indexOf(elementRef), 1)
if (!elements) {
return
}
const elementIndex = elements.indexOf(elementRef)
if (elementIndex === -1) {
return
}
elements.splice(elementIndex, 1)

Copilot uses AI. Check for mistakes.
import type { SplitGutterContext } from './split-gutter-context'

export interface SplitGutterComponent {
context: InputSignal<SplitGutterContext>
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
context: InputSignal<SplitGutterContext>
context: SplitGutterContext | InputSignal<SplitGutterContext>

Copilot uses AI. Check for mistakes.
@SanderElias
Copy link
Copy Markdown
Contributor

@Harpush A pulled CP in. Not sure the points are valid, I'll leave that up to you.
Aside from those, it looks good to me. Seems like a good addition!

@Harpush
Copy link
Copy Markdown
Collaborator Author

Harpush commented Apr 3, 2026

@SanderElias
The first comment is a bit of defensive programming... Theoretically it can happen but on creation I add and on destroy I remove.
The second comment allows non signal inputs support - a question whether we want it or not

Copy link
Copy Markdown
Contributor

@SanderElias SanderElias left a comment

Choose a reason for hiding this comment

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

LGTM

@SanderElias
Copy link
Copy Markdown
Contributor

@Harpush works out for me, I approved!

@Harpush
Copy link
Copy Markdown
Collaborator Author

Harpush commented Apr 3, 2026

@SanderElias great! So you can merge and hopefully we can publish a new angular 20 version before migrating to 21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants