Skip to content

Commit

Permalink
feat: add @ngneat/helipopper/config
Browse files Browse the repository at this point in the history
In this commit, we add a new subpackage called `@ngneat/helipopper/config`.
This change is intended to separate configuration logic from UI-related functionality.
The configuration should be imported at the root level, while the UI components should
only be imported when necessary. Previously, importing the library at the root
level (when providing the loader) caused the bundler to include everything in the
main bundle immediately.

With this approach, the configuration is bundled separately at the root level and
includes only the provider functions.

Additionally, while we had already added a `loader` function, to avoid breaking the
`provideTippyConfig` signature, we introduced a separate function called `provideTippyLoader`,
which exclusively accepts a loader function.
  • Loading branch information
arturovt committed Nov 19, 2024
1 parent cf879bc commit 172f234
Show file tree
Hide file tree
Showing 14 changed files with 98 additions and 39 deletions.
6 changes: 6 additions & 0 deletions projects/ngneat/helipopper/config/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "../../../../node_modules/ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "src/public-api.ts"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { TippyProps } from './tippy.types';

// A variation is a set of predefined tippy properties.
type Variation = Partial<TippyProps>;

export const tooltipVariation: Variation = {
Expand Down
13 changes: 13 additions & 0 deletions projects/ngneat/helipopper/config/src/inject-tippy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { inject } from '@angular/core';

import { TIPPY_REF, type TippyInstance } from './tippy.types';

export function injectTippyRef(): TippyInstance {
const instance = inject(TIPPY_REF, { optional: true });

if (instance) {
return instance;
}

throw new Error('tp is not provided in the current context or on one of its ancestors');
}
16 changes: 16 additions & 0 deletions projects/ngneat/helipopper/config/src/providers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { makeEnvironmentProviders, type Provider } from '@angular/core';

import {
TIPPY_CONFIG,
TIPPY_LOADER,
type TippyLoader,
type TippyConfig,
} from './tippy.types';

export function provideTippyLoader(loader: TippyLoader) {
return makeEnvironmentProviders([{ provide: TIPPY_LOADER, useValue: loader }]);
}

export function provideTippyConfig(config: TippyConfig): Provider {
return { provide: TIPPY_CONFIG, useValue: config };
}
16 changes: 16 additions & 0 deletions projects/ngneat/helipopper/config/src/public-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export { tooltipVariation, popperVariation, withContextMenuVariation } from './defaults';
export {
CreateOptions,
TippyInstance,
TippyProps,
ExtendedTippyProps,
TippyElement,
ExtendedTippyInstance,
TippyConfig,
TippyLoader,
TIPPY_LOADER,
TIPPY_REF,
TIPPY_CONFIG,
} from './tippy.types';
export { provideTippyLoader, provideTippyConfig } from './providers';
export { injectTippyRef } from './inject-tippy';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type tippy from 'tippy.js';
import type { Instance, Props } from 'tippy.js';
import { ElementRef, InjectionToken, type InputSignal } from '@angular/core';
import { ElementRef, InjectionToken } from '@angular/core';
import type { ResolveViewRef, ViewOptions } from '@ngneat/overview';

export interface CreateOptions extends Partial<TippyProps>, ViewOptions {
Expand All @@ -10,8 +10,6 @@ export interface CreateOptions extends Partial<TippyProps>, ViewOptions {
data: any;
}

export const TIPPY_REF = new InjectionToken<TippyInstance>('TIPPY_REF');

export interface TippyInstance extends Instance {
data?: any;
}
Expand All @@ -33,8 +31,12 @@ export interface ExtendedTippyInstance<T> extends TippyInstance {
context?: ViewOptions['context'];
}

export interface TippyConfig extends Partial<ExtendedTippyProps> {
loader: () => typeof tippy | Promise<{ default: typeof tippy }>;
}
export type TippyConfig = Partial<ExtendedTippyProps>;

export type TippyLoader = () => typeof tippy | Promise<{ default: typeof tippy }>;

export const TIPPY_LOADER = new InjectionToken<TippyLoader>('TIPPY_LOADER');

export const TIPPY_REF = /* @__PURE__ */ new InjectionToken<TippyInstance>('TIPPY_REF');

export const TIPPY_CONFIG = new InjectionToken<TippyConfig>('Tippy config');
16 changes: 0 additions & 16 deletions projects/ngneat/helipopper/src/lib/providers.ts

This file was deleted.

2 changes: 1 addition & 1 deletion projects/ngneat/helipopper/src/lib/tippy.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import {
TippyConfig,
TippyInstance,
TippyProps,
} from './tippy.types';
} from '@ngneat/helipopper/config';
import { TippyFactory } from './tippy.factory';
import { coerceBooleanAttribute } from './coercion';

Expand Down
11 changes: 6 additions & 5 deletions projects/ngneat/helipopper/src/lib/tippy.factory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import type tippy from 'tippy.js';
import { inject, Injectable, NgZone } from '@angular/core';
import { defer, from, map, type Observable, of, shareReplay } from 'rxjs';

import { TIPPY_CONFIG, type TippyProps } from './tippy.types';
import { TIPPY_LOADER, type TippyProps } from '@ngneat/helipopper/config';

// We need to use `isPromise` instead of checking whether
// `value instanceof Promise`. In zone.js patched environments, `global.Promise`
Expand All @@ -17,7 +16,7 @@ function isPromise<T>(value: any): value is Promise<T> {
export class TippyFactory {
private readonly _ngZone = inject(NgZone);

private readonly _config = inject(TIPPY_CONFIG);
private readonly _loader = inject(TIPPY_LOADER);

private _tippyImpl$: Observable<typeof tippy> | null = null;

Expand All @@ -31,8 +30,10 @@ export class TippyFactory {
// synchronous and to avoid triggering the `defer` callback repeatedly
// when new subscribers arrive.
this._tippyImpl$ ||= defer(() => {
const maybeTippy = this._ngZone.runOutsideAngular(() => this._config.loader());
return isPromise(maybeTippy) ? from(maybeTippy).pipe(map((tippy) => tippy.default)) : of(maybeTippy);
const maybeTippy = this._ngZone.runOutsideAngular(() => this._loader());
return isPromise(maybeTippy)
? from(maybeTippy).pipe(map((tippy) => tippy.default))
: of(maybeTippy);
}).pipe(shareReplay());

return this._tippyImpl$.pipe(
Expand Down
2 changes: 1 addition & 1 deletion projects/ngneat/helipopper/src/lib/tippy.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
TIPPY_REF,
TippyConfig,
TippyInstance,
} from './tippy.types';
} from '@ngneat/helipopper/config';
import { normalizeClassName, onlyTippyProps } from './utils';
import { TippyFactory } from './tippy.factory';

Expand Down
4 changes: 2 additions & 2 deletions projects/ngneat/helipopper/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ElementRef } from '@angular/core';
import { Observable } from 'rxjs';
import { auditTime, map } from 'rxjs/operators';
import { TippyElement } from './tippy.types';
import { ElementRef } from '@angular/core';
import type { TippyElement } from '@ngneat/helipopper/config';

import { IntersectionObserver } from './intersection-observer';

Expand Down
16 changes: 13 additions & 3 deletions projects/ngneat/helipopper/src/public-api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
export { TippyDirective } from './lib/tippy.directive';
export { tooltipVariation, popperVariation, withContextMenuVariation } from './lib/defaults';
export { TippyService } from './lib/tippy.service';
export { inView, overflowChanges } from './lib/utils';
export { ExtendedTippyInstance, TippyInstance, TIPPY_REF, TippyConfig, TIPPY_CONFIG } from './lib/tippy.types';
export { provideTippyConfig, injectTippyRef } from './lib/providers';

export {
ExtendedTippyInstance,
TippyInstance,
TIPPY_REF,
TippyConfig,
TIPPY_CONFIG,
tooltipVariation,
popperVariation,
withContextMenuVariation,
provideTippyConfig,
injectTippyRef,
} from '@ngneat/helipopper/config';
17 changes: 12 additions & 5 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '@angular/forms';
import { ExampleComponent } from './example/example.component';
import { TippyDirective } from '@ngneat/helipopper';
import {
popperVariation,
provideTippyConfig,
TippyDirective,
tooltipVariation,
withContextMenuVariation,
} from '@ngneat/helipopper';
provideTippyConfig,
provideTippyLoader,
} from '@ngneat/helipopper/config';
import { PlaygroundComponent } from './playground/playground.component';
import { IsVisibleComponent } from './is-visible/isVisible.component';

Expand All @@ -22,11 +23,17 @@ function getZIndex() {
}

@NgModule({
declarations: [AppComponent, ExampleComponent, PlaygroundComponent, ExampleComponent, IsVisibleComponent],
declarations: [
AppComponent,
ExampleComponent,
PlaygroundComponent,
ExampleComponent,
IsVisibleComponent,
],
imports: [BrowserModule, AppRoutingModule, ReactiveFormsModule, TippyDirective],
providers: [
provideTippyLoader(() => import('tippy.js')),
provideTippyConfig({
loader: () => import('tippy.js'),
defaultVariation: 'tooltip',
zIndexGetter: getZIndex,
variations: {
Expand Down
3 changes: 3 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"module": "es2020",
"lib": ["es2020", "dom"],
"paths": {
"@ngneat/helipopper/config": [
"projects/ngneat/helipopper/config/src/public-api.ts"
],
"@ngneat/helipopper": ["projects/ngneat/helipopper/src/public-api.ts"]
},
"useDefineForClassFields": false
Expand Down

0 comments on commit 172f234

Please sign in to comment.