UNPKG

@ynmstudio/utils

Version:
141 lines (135 loc) 7.63 kB
import * as i0 from '@angular/core'; import { input, Component, InjectionToken, Optional, SkipSelf, inject, ViewContainerRef, Injector, Renderer2, EnvironmentInjector, numberAttribute, computed, effect, createComponent, Directive } from '@angular/core'; class DynamicHeadingComponent { constructor() { this.class = input(''); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: DynamicHeadingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.13", type: DynamicHeadingComponent, isStandalone: true, selector: "[dynamicHeadingWrapper]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "class()" } }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host.debug ::ng-deep>*{position:relative}:host.debug ::ng-deep>*:after{position:absolute;background-color:#ffb6c1;color:#fff;font-size:12px;padding:.25em;line-height:1.1;border-radius:2px;content:\"H\" attr(data-level) / \"Heading \" attr(data-level);top:0;right:0;transform:translateY(-50%)}:host.debug:hover ::ng-deep>*:after{background-color:red}\n"] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: DynamicHeadingComponent, decorators: [{ type: Component, args: [{ selector: '[dynamicHeadingWrapper]', template: '<ng-content></ng-content>', host: { '[class]': 'class()', }, styles: [":host.debug ::ng-deep>*{position:relative}:host.debug ::ng-deep>*:after{position:absolute;background-color:#ffb6c1;color:#fff;font-size:12px;padding:.25em;line-height:1.1;border-radius:2px;content:\"H\" attr(data-level) / \"Heading \" attr(data-level);top:0;right:0;transform:translateY(-50%)}:host.debug:hover ::ng-deep>*:after{background-color:red}\n"] }] }] }); /** * Injection token to control the base heading level within components. * * This provider allows setting or resetting the heading level hierarchy within specific components. * This is useful when you want to start a new heading hierarchy from level 1, regardless of parent levels. * * Common use cases include: * - Reset to h1 at the start of a new <article> element to maintain proper document outline * - Start fresh heading hierarchy in <aside> elements or sidebars * - Modal dialogs or overlays that should have their own heading structure * - Independent widgets or components that can be placed anywhere but need consistent heading levels * - Blog post or article comments sections that should start their own hierarchy * * @example * ```typescript * @Component({ * providers: [ * { provide: DYNAMIC_HEADING_LEVEL, useValue: 1 } // Reset to h1 * ] * }) * ``` */ const DYNAMIC_HEADING_LEVEL = new InjectionToken('DYNAMIC_HEADING_LEVEL', { factory: () => 1, providedIn: 'root', }); /** * Injection token to enable debug mode for dynamic headings. * * When set to true, a pseudo element will be rendered next to each heading element * showing its current heading level (e.g. "H2/Heading 2"). This provides visual feedback * about the computed heading levels during development. * * @default false */ const DYNAMIC_HEADING_DEBUG = new InjectionToken('DYNAMIC_HEADING_DEBUG', { factory: () => false, providedIn: 'root', }); /** * Factory function to increase the heading level relative to parent headings. * * This can be used in two ways: * 1. As a provider to automatically increment heading levels by X relative to parent headings * (e.g. h1 -> h2 -> h3) * 2. Alternatively, the level/offset inputs can be used directly on the dynamicHeading directive * to explicitly set the heading level, overriding the automatic increments * * @param offset Number of levels to increment from the parent heading level (defaults to 1) * @returns Provider configuration for DYNAMIC_HEADING_LEVEL */ function increaseDynamicHeadingLevel() { return { provide: DYNAMIC_HEADING_LEVEL, useFactory: (parentLevel) => { // If parentLevel is null or undefined, start from 2 return (parentLevel ?? 1) + 1; }, deps: [[new Optional(), new SkipSelf(), DYNAMIC_HEADING_LEVEL]], }; } class DynamicHeadingDirective { #viewContainerRef; #injector; #renderer; #environment; #currentHeadingLevel; constructor() { this.#viewContainerRef = inject(ViewContainerRef); this.#injector = inject(Injector); this.#renderer = inject(Renderer2); this.#environment = inject(EnvironmentInjector); this.#currentHeadingLevel = inject(DYNAMIC_HEADING_LEVEL); this.debug = inject(DYNAMIC_HEADING_DEBUG); this.dynamicHeadingClass = input(''); this._level = input(this.#currentHeadingLevel, { alias: 'level', transform: (value) => numberAttribute(value) ?? 1 }); this.offset = input(0, { transform: (value) => numberAttribute(value) ?? 0 }); this.level = computed(() => Math.max(1, Math.min(6, this._level() + this.offset()))); effect(() => { this.#viewContainerRef?.clear(); const hostElement = this.#renderer.createElement(`h${this.level()}`); const heading = createComponent(DynamicHeadingComponent, { hostElement, environmentInjector: this.#environment, elementInjector: this.#injector, projectableNodes: [ [this.#viewContainerRef.element.nativeElement] ], }); heading.setInput('class', `${this.dynamicHeadingClass()} ${this.debug ? 'debug' : ''}`); this.#viewContainerRef.insert(heading.hostView); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: DynamicHeadingDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.13", type: DynamicHeadingDirective, isStandalone: true, selector: "[dynamicHeading]", inputs: { dynamicHeadingClass: { classPropertyName: "dynamicHeadingClass", publicName: "dynamicHeadingClass", isSignal: true, isRequired: false, transformFunction: null }, _level: { classPropertyName: "_level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-level": "level()" } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: DynamicHeadingDirective, decorators: [{ type: Directive, args: [{ selector: '[dynamicHeading]', standalone: true, host: { '[attr.data-level]': 'level()', }, }] }], ctorParameters: () => [] }); /* * Public API Surface of draw-blurhash */ // export * from './dynamic-heading.component'; /** * Generated bundle index. Do not edit. */ export { DYNAMIC_HEADING_DEBUG, DYNAMIC_HEADING_LEVEL, DynamicHeadingDirective, increaseDynamicHeadingLevel }; //# sourceMappingURL=ynmstudio-utils-dynamic-heading.mjs.map