@ngneers/controls 0.0.1-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/ngneers-controls-accordion.mjs +234 -0
- package/fesm2022/ngneers-controls-accordion.mjs.map +1 -0
- package/fesm2022/ngneers-controls-api-ng.mjs +959 -0
- package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -0
- package/fesm2022/ngneers-controls-api-resize.mjs +712 -0
- package/fesm2022/ngneers-controls-api-resize.mjs.map +1 -0
- package/fesm2022/ngneers-controls-api.mjs +347 -0
- package/fesm2022/ngneers-controls-api.mjs.map +1 -0
- package/fesm2022/ngneers-controls-avatar.mjs +77 -0
- package/fesm2022/ngneers-controls-avatar.mjs.map +1 -0
- package/fesm2022/ngneers-controls-base.mjs +620 -0
- package/fesm2022/ngneers-controls-base.mjs.map +1 -0
- package/fesm2022/ngneers-controls-breadcrumb.mjs +100 -0
- package/fesm2022/ngneers-controls-breadcrumb.mjs.map +1 -0
- package/fesm2022/ngneers-controls-button-group.mjs +110 -0
- package/fesm2022/ngneers-controls-button-group.mjs.map +1 -0
- package/fesm2022/ngneers-controls-button.mjs +83 -0
- package/fesm2022/ngneers-controls-button.mjs.map +1 -0
- package/fesm2022/ngneers-controls-calendar-time-CJT5AFlA.mjs +74 -0
- package/fesm2022/ngneers-controls-calendar-time-CJT5AFlA.mjs.map +1 -0
- package/fesm2022/ngneers-controls-calendar.mjs +801 -0
- package/fesm2022/ngneers-controls-calendar.mjs.map +1 -0
- package/fesm2022/ngneers-controls-checkbox.mjs +63 -0
- package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -0
- package/fesm2022/ngneers-controls-chip.mjs +55 -0
- package/fesm2022/ngneers-controls-chip.mjs.map +1 -0
- package/fesm2022/ngneers-controls-default-icons.mjs +82 -0
- package/fesm2022/ngneers-controls-default-icons.mjs.map +1 -0
- package/fesm2022/ngneers-controls-defer.mjs +72 -0
- package/fesm2022/ngneers-controls-defer.mjs.map +1 -0
- package/fesm2022/ngneers-controls-dialog.mjs +407 -0
- package/fesm2022/ngneers-controls-dialog.mjs.map +1 -0
- package/fesm2022/ngneers-controls-directives.mjs +498 -0
- package/fesm2022/ngneers-controls-directives.mjs.map +1 -0
- package/fesm2022/ngneers-controls-drawer.mjs +271 -0
- package/fesm2022/ngneers-controls-drawer.mjs.map +1 -0
- package/fesm2022/ngneers-controls-edit-inplace.mjs +127 -0
- package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -0
- package/fesm2022/ngneers-controls-errors.mjs +329 -0
- package/fesm2022/ngneers-controls-errors.mjs.map +1 -0
- package/fesm2022/ngneers-controls-filter.mjs +708 -0
- package/fesm2022/ngneers-controls-filter.mjs.map +1 -0
- package/fesm2022/ngneers-controls-hint.mjs +153 -0
- package/fesm2022/ngneers-controls-hint.mjs.map +1 -0
- package/fesm2022/ngneers-controls-i18n-translations-de.mjs +170 -0
- package/fesm2022/ngneers-controls-i18n-translations-de.mjs.map +1 -0
- package/fesm2022/ngneers-controls-i18n-translations-en.mjs +170 -0
- package/fesm2022/ngneers-controls-i18n-translations-en.mjs.map +1 -0
- package/fesm2022/ngneers-controls-i18n.mjs +57 -0
- package/fesm2022/ngneers-controls-i18n.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon.mjs +195 -0
- package/fesm2022/ngneers-controls-icon.mjs.map +1 -0
- package/fesm2022/ngneers-controls-inplace.mjs +150 -0
- package/fesm2022/ngneers-controls-inplace.mjs.map +1 -0
- package/fesm2022/ngneers-controls-input-field.mjs +165 -0
- package/fesm2022/ngneers-controls-input-field.mjs.map +1 -0
- package/fesm2022/ngneers-controls-input.mjs +72 -0
- package/fesm2022/ngneers-controls-input.mjs.map +1 -0
- package/fesm2022/ngneers-controls-item-view.mjs +473 -0
- package/fesm2022/ngneers-controls-item-view.mjs.map +1 -0
- package/fesm2022/ngneers-controls-list-box.mjs +281 -0
- package/fesm2022/ngneers-controls-list-box.mjs.map +1 -0
- package/fesm2022/ngneers-controls-mask-input.mjs +888 -0
- package/fesm2022/ngneers-controls-mask-input.mjs.map +1 -0
- package/fesm2022/ngneers-controls-menu.mjs +371 -0
- package/fesm2022/ngneers-controls-menu.mjs.map +1 -0
- package/fesm2022/ngneers-controls-message.mjs +30 -0
- package/fesm2022/ngneers-controls-message.mjs.map +1 -0
- package/fesm2022/ngneers-controls-number-input.mjs +366 -0
- package/fesm2022/ngneers-controls-number-input.mjs.map +1 -0
- package/fesm2022/ngneers-controls-paginator.mjs +129 -0
- package/fesm2022/ngneers-controls-paginator.mjs.map +1 -0
- package/fesm2022/ngneers-controls-popover.mjs +215 -0
- package/fesm2022/ngneers-controls-popover.mjs.map +1 -0
- package/fesm2022/ngneers-controls-progress.mjs +98 -0
- package/fesm2022/ngneers-controls-progress.mjs.map +1 -0
- package/fesm2022/ngneers-controls-radio.mjs +152 -0
- package/fesm2022/ngneers-controls-radio.mjs.map +1 -0
- package/fesm2022/ngneers-controls-roving-focus.mjs +323 -0
- package/fesm2022/ngneers-controls-roving-focus.mjs.map +1 -0
- package/fesm2022/ngneers-controls-scroll-shadow.mjs +65 -0
- package/fesm2022/ngneers-controls-scroll-shadow.mjs.map +1 -0
- package/fesm2022/ngneers-controls-scroller.mjs +308 -0
- package/fesm2022/ngneers-controls-scroller.mjs.map +1 -0
- package/fesm2022/ngneers-controls-select-button.mjs +58 -0
- package/fesm2022/ngneers-controls-select-button.mjs.map +1 -0
- package/fesm2022/ngneers-controls-select.mjs +417 -0
- package/fesm2022/ngneers-controls-select.mjs.map +1 -0
- package/fesm2022/ngneers-controls-slider.mjs +167 -0
- package/fesm2022/ngneers-controls-slider.mjs.map +1 -0
- package/fesm2022/ngneers-controls-snackbar.mjs +414 -0
- package/fesm2022/ngneers-controls-snackbar.mjs.map +1 -0
- package/fesm2022/ngneers-controls-spin-buttons.mjs +126 -0
- package/fesm2022/ngneers-controls-spin-buttons.mjs.map +1 -0
- package/fesm2022/ngneers-controls-spinner.mjs +184 -0
- package/fesm2022/ngneers-controls-spinner.mjs.map +1 -0
- package/fesm2022/ngneers-controls-splitter.mjs +604 -0
- package/fesm2022/ngneers-controls-splitter.mjs.map +1 -0
- package/fesm2022/ngneers-controls-state.mjs +185 -0
- package/fesm2022/ngneers-controls-state.mjs.map +1 -0
- package/fesm2022/ngneers-controls-switch.mjs +39 -0
- package/fesm2022/ngneers-controls-switch.mjs.map +1 -0
- package/fesm2022/ngneers-controls-table.mjs +2634 -0
- package/fesm2022/ngneers-controls-table.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tabs.mjs +336 -0
- package/fesm2022/ngneers-controls-tabs.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tag.mjs +30 -0
- package/fesm2022/ngneers-controls-tag.mjs.map +1 -0
- package/fesm2022/ngneers-controls-toast.mjs +350 -0
- package/fesm2022/ngneers-controls-toast.mjs.map +1 -0
- package/fesm2022/ngneers-controls-toggle-button.mjs +70 -0
- package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tooltip.mjs +506 -0
- package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tree.mjs +599 -0
- package/fesm2022/ngneers-controls-tree.mjs.map +1 -0
- package/fesm2022/ngneers-controls-upload.mjs +377 -0
- package/fesm2022/ngneers-controls-upload.mjs.map +1 -0
- package/fesm2022/ngneers-controls-utils-ng.mjs +411 -0
- package/fesm2022/ngneers-controls-utils-ng.mjs.map +1 -0
- package/fesm2022/ngneers-controls-utils.mjs +261 -0
- package/fesm2022/ngneers-controls-utils.mjs.map +1 -0
- package/fesm2022/ngneers-controls.mjs +6 -0
- package/fesm2022/ngneers-controls.mjs.map +1 -0
- package/package.json +302 -0
- package/types/ngneers-controls-accordion.d.ts +139 -0
- package/types/ngneers-controls-api-ng.d.ts +364 -0
- package/types/ngneers-controls-api-resize.d.ts +318 -0
- package/types/ngneers-controls-api.d.ts +145 -0
- package/types/ngneers-controls-avatar.d.ts +54 -0
- package/types/ngneers-controls-base.d.ts +277 -0
- package/types/ngneers-controls-breadcrumb.d.ts +272 -0
- package/types/ngneers-controls-button-group.d.ts +46 -0
- package/types/ngneers-controls-button.d.ts +48 -0
- package/types/ngneers-controls-calendar.d.ts +466 -0
- package/types/ngneers-controls-checkbox.d.ts +40 -0
- package/types/ngneers-controls-chip.d.ts +202 -0
- package/types/ngneers-controls-default-icons.d.ts +5 -0
- package/types/ngneers-controls-defer.d.ts +48 -0
- package/types/ngneers-controls-dialog.d.ts +399 -0
- package/types/ngneers-controls-directives.d.ts +171 -0
- package/types/ngneers-controls-drawer.d.ts +308 -0
- package/types/ngneers-controls-edit-inplace.d.ts +263 -0
- package/types/ngneers-controls-errors.d.ts +155 -0
- package/types/ngneers-controls-filter.d.ts +609 -0
- package/types/ngneers-controls-hint.d.ts +88 -0
- package/types/ngneers-controls-i18n-translations-de.d.ts +164 -0
- package/types/ngneers-controls-i18n-translations-en.d.ts +164 -0
- package/types/ngneers-controls-i18n.d.ts +186 -0
- package/types/ngneers-controls-icon.d.ts +68 -0
- package/types/ngneers-controls-inplace.d.ts +98 -0
- package/types/ngneers-controls-input-field.d.ts +248 -0
- package/types/ngneers-controls-input.d.ts +30 -0
- package/types/ngneers-controls-item-view.d.ts +215 -0
- package/types/ngneers-controls-list-box.d.ts +334 -0
- package/types/ngneers-controls-mask-input.d.ts +434 -0
- package/types/ngneers-controls-menu.d.ts +192 -0
- package/types/ngneers-controls-message.d.ts +21 -0
- package/types/ngneers-controls-number-input.d.ts +146 -0
- package/types/ngneers-controls-paginator.d.ts +255 -0
- package/types/ngneers-controls-popover.d.ts +116 -0
- package/types/ngneers-controls-progress.d.ts +49 -0
- package/types/ngneers-controls-radio.d.ts +91 -0
- package/types/ngneers-controls-roving-focus.d.ts +107 -0
- package/types/ngneers-controls-scroll-shadow.d.ts +25 -0
- package/types/ngneers-controls-scroller.d.ts +151 -0
- package/types/ngneers-controls-select-button.d.ts +51 -0
- package/types/ngneers-controls-select.d.ts +409 -0
- package/types/ngneers-controls-slider.d.ts +57 -0
- package/types/ngneers-controls-snackbar.d.ts +330 -0
- package/types/ngneers-controls-spin-buttons.d.ts +69 -0
- package/types/ngneers-controls-spinner.d.ts +117 -0
- package/types/ngneers-controls-splitter.d.ts +465 -0
- package/types/ngneers-controls-state.d.ts +102 -0
- package/types/ngneers-controls-switch.d.ts +18 -0
- package/types/ngneers-controls-table.d.ts +3127 -0
- package/types/ngneers-controls-tabs.d.ts +118 -0
- package/types/ngneers-controls-tag.d.ts +21 -0
- package/types/ngneers-controls-toast.d.ts +298 -0
- package/types/ngneers-controls-toggle-button.d.ts +48 -0
- package/types/ngneers-controls-tooltip.d.ts +189 -0
- package/types/ngneers-controls-tree.d.ts +409 -0
- package/types/ngneers-controls-upload.d.ts +347 -0
- package/types/ngneers-controls-utils-ng.d.ts +129 -0
- package/types/ngneers-controls-utils.d.ts +130 -0
- package/types/ngneers-controls.d.ts +2 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngneers-controls-base.mjs","sources":["../../src/base/ngn-instance.ts","../../src/base/base.ts","../../src/base/passthrough/pt-engine.ts","../../src/base/passthrough/pt.ts","../../src/base/value-control-base.ts","../../src/base/ngneers-controls-base.ts"],"sourcesContent":["import { afterNextRender, DestroyRef, inject, signal, type Signal, Type } from '@angular/core';\n\nimport type { AnyNgnBase, FullAnyNgnBase } from './base';\n\nconst NGN_INSTANCE_KEY = '__ngneers_control_instance__';\n\nfunction elementWithInstance(\n element: HTMLElement\n): HTMLElement & { [NGN_INSTANCE_KEY]?: AnyNgnBase } {\n return element as HTMLElement & { [NGN_INSTANCE_KEY]?: FullAnyNgnBase };\n}\n\nexport function setNgnInstance(element: HTMLElement, instance: AnyNgnBase): void {\n elementWithInstance(element)[NGN_INSTANCE_KEY] = instance;\n inject(DestroyRef).onDestroy(() => {\n delete elementWithInstance(element)[NGN_INSTANCE_KEY];\n });\n}\n\nexport function getNgnInstance(element: HTMLElement): FullAnyNgnBase {\n return elementWithInstance(element)[NGN_INSTANCE_KEY] as FullAnyNgnBase;\n}\n\nexport function getNearestNgnInstance<T extends Type<Omit<AnyNgnBase, 'kind'>>>(\n element: HTMLElement,\n kind?: T\n): InstanceType<T> | null {\n let current: HTMLElement | null = element;\n while (current) {\n const instance = elementWithInstance(current)[NGN_INSTANCE_KEY] as FullAnyNgnBase | undefined;\n if (instance && (!kind || instance instanceof kind)) {\n return instance as InstanceType<T>;\n }\n current = current.parentElement;\n }\n return null;\n}\n\nexport function getNearestNgnInstanceSig<T extends Type<AnyNgnBase>>(\n element: HTMLElement,\n kind?: T\n): Signal<InstanceType<T> | null> {\n const sig = signal<InstanceType<T> | null>(null);\n afterNextRender(() => {\n sig.set(getNearestNgnInstance(element, kind));\n });\n return sig;\n}\n","import {\n afterNextRender,\n booleanAttribute,\n computed,\n DestroyRef,\n Directive,\n effect,\n ElementRef,\n forwardRef,\n inject,\n InjectionToken,\n Injector,\n input,\n type InputSignal,\n type Provider,\n signal,\n type Signal,\n Type,\n viewChildren,\n} from '@angular/core';\nimport {\n type ControlTemplateInfo,\n injectThemeTemplate,\n injectThemeControlKinds,\n injectThemeColors,\n type AppliedThemeClassCfg,\n Platform,\n} from '@ngneers/controls/api/ng';\nimport { toggleClass } from '@ngneers/controls/utils';\nimport { effectWithPrevious, setInputSignalValue } from '@ngneers/controls/utils-ng';\n\nimport { setNgnInstance } from './ngn-instance';\nimport { type NgnPassthrough, NgnPtEngine } from './passthrough';\n\nimport type { CustomColor, CustomKind } from '@ngneers/controls-custom-types';\nimport type { ControlTemplate } from '@ngneers/controls-themes';\nimport type { ControlName, ThemeTemplate } from '@ngneers/controls-themes/templates';\n\nexport const NGN_CONTROL = new InjectionToken<NgnBase<never>>('NGN_CONTROL');\n\n// eslint-disable-next-line typescript/no-explicit-any\nexport type AnyNgnBase = NgnBaseSafe<any>;\nexport type NgnBaseSafe<T extends ControlName | null> = Omit<\n NgnBase<T>,\n 'kind' | 'appliedKind' | 'pt'\n>;\n\n/* eslint-disable typescript/no-explicit-any */\nexport type FullAnyNgnBase = Omit<NgnBase<any>, 'kind' | 'appliedKind' | 'pt'> & {\n kind: InputSignal<CustomKind<any> | undefined>;\n appliedKind: InputSignal<CustomKind<any> | undefined>;\n pt: InputSignal<NgnPassthrough<any> | undefined>;\n};\n/* eslint-enable typescript/no-explicit-any */\n\n/**\n * @internal\n * Provides the control itself for dependency injection.\n * @param control - The control class to provide.\n * @returns A provider for the control itself.\n */\nexport function provideSelf(control: Type<unknown>): Provider {\n return { provide: NGN_CONTROL, useExisting: forwardRef(() => control) };\n}\n\n@Directive({\n host: { class: 'ngn-control ngn-control-initializing' },\n})\nexport abstract class NgnBase<T extends ControlName | null> {\n protected abstract theme: ControlTemplateInfo<never> | null;\n\n private readonly _defaultKind = signal<CustomKind<T> | undefined>(undefined);\n private readonly _defaultColor = signal<CustomColor | undefined>(undefined);\n private readonly _kindOverride = signal<CustomKind<T> | undefined>(undefined);\n\n /**\n * The element reference for the host element.\n */\n public readonly element = inject<ElementRef<HTMLElement>>(ElementRef);\n /**\n * The injector for the component.\n */\n public readonly injector = inject(Injector);\n /**\n * If true, the control will not apply any theme styles.\n * The base styles of the control will still be applied.\n * @default false\n */\n public readonly unstyled = input(false, { transform: booleanAttribute });\n\n /**\n * Some controls support custom kinds for styling purposes.\n * The available kinds depend on the control and the theme used.\n *\n * TODO: link to custom types documentation\n */\n public readonly kind = input<CustomKind<T> | undefined>(undefined as never);\n public readonly color = input<CustomColor | undefined>(undefined as never);\n\n public readonly appliedKind = computed<CustomKind<T> | undefined>(\n () => this._kindOverride() ?? this.kind() ?? this._defaultKind()\n );\n public readonly appliedColor = computed<CustomColor | undefined>(\n () => this.color() ?? this._defaultColor()\n );\n\n /**\n * Custom passthrough attributes to apply to the control's theme classes and its dependencies.\n * This allows for fine-grained customization of attributes, styles and more.\n */\n public readonly pt = input<T extends string ? NgnPassthrough<T> : never>();\n\n /**\n * Marks a control as the primary value control of a surrounding field\n * (e.g. `ngn-input-field`). Fields resolve their projected control by\n * filtering for this flag, so auxiliary controls placed inside the field\n * (buttons, icons, spin buttons, …) never shadow the actual input.\n * Overridden with `true` by input, mask-input, calendar, select, ….\n */\n public readonly isFieldControl: boolean = false;\n\n /**\n * Hook for placing focus/selection from a pointer event that originated in the\n * surrounding field (or the control itself). The default does nothing and\n * returns `false`, signalling the surrounding field should fall back to its\n * primitive focusing. Controls that own internal focus placement (e.g.\n * mask-input) override this, act on the pointer location, and return `true`.\n */\n public focusFromPointer(_event: MouseEvent): boolean {\n return false;\n }\n\n /**\n * Hook for stepping the control's value (e.g. from `ngn-spin-buttons` or\n * other external steppers). The default does nothing and returns `false`.\n * Controls with a steppable value (e.g. number-input) override this, apply\n * the step and return `true`.\n * @param _direction - `1` to increment, `-1` to decrement.\n * @param _big - Whether to apply the control's big step (e.g. Shift+Arrow).\n */\n public stepValue(_direction: 1 | -1, _big = false): boolean {\n return false;\n }\n\n /**\n * Hook telling external steppers (e.g. `ngn-spin-buttons`) whether the value\n * can currently be stepped in the given direction. The default returns\n * `false`; controls overriding {@link stepValue} override this as well\n * (typically `false` at a min/max bound or while disabled/readonly).\n */\n public canStepValue(_direction: 1 | -1): boolean {\n return false;\n }\n\n /**\n * Hook for clearing the control's own value/state (e.g. from a surrounding\n * field's clear button). The default does nothing and returns `false`, so the\n * caller falls back to clearing the underlying DOM input. Controls that manage\n * their own value (e.g. mask-input) override this to reset and return `true`.\n */\n public clearValue(): boolean {\n return false;\n }\n\n /**\n * Temporarily overrides the authored kind without mutating the public input.\n * Intended for derived control states such as validation-driven hints.\n */\n protected setKindOverride(kind: CustomKind<T> | undefined): void {\n this._kindOverride.set(kind);\n }\n\n private readonly _childNgnControls = viewChildren(NGN_CONTROL);\n private readonly _afterLeaveCbs: (() => void)[] = [];\n\n constructor() {\n // `pt` is typed against this control's own `T`, which makes `this`\n // (NgnBase<T>) structurally incompatible with the type-erased AnyNgnBase\n // alias for an unconstrained/generic T. Safe: AnyNgnBase never reads `pt`\n // in a way that depends on the real T at the call site.\n setNgnInstance(this.element.nativeElement, this as unknown as AnyNgnBase);\n this.prepareAfterLeaveHook();\n effect(() => {\n // Propagate unstyled state to direct child controls, does not affect\n // custom user content passed into ng-content or projected templates.\n this._childNgnControls().forEach(child => {\n setInputSignalValue(child.unstyled, this.unstyled());\n });\n });\n\n this.initializeKindAndColorClasses();\n\n if (inject(Platform).isBrowser) {\n // Remove the initializing class after the first render to prevent FOUC.\n afterNextRender(() => {\n this.element.nativeElement.classList.remove('ngn-control-initializing');\n });\n } else {\n // Remove the initializing class immediately on the server to serve a complete initial HTML.\n this.element.nativeElement.classList.remove('ngn-control-initializing');\n }\n }\n\n /**\n * Prepares the after leave hook to be called when the control is destroyed\n * and its leave animation has finished.\n */\n private prepareAfterLeaveHook() {\n inject(DestroyRef).onDestroy(() => {\n if (typeof this.element.nativeElement.getAnimations !== 'function') {\n this.afterLeaveInternal();\n } else {\n NgnBase._enqueueLeaveCheck(this.element.nativeElement, () => this.afterLeaveInternal());\n }\n });\n }\n\n // --- Batched leave animation checking ---\n // Collects all destroyed components in the same frame into one queue,\n // then processes them in a single rAF to avoid layout thrashing from\n // interleaved getAnimations() calls and DOM mutations.\n\n private static _leaveQueue: { element: HTMLElement; callback: () => void }[] = [];\n private static _leaveRafScheduled = false;\n\n private static _enqueueLeaveCheck(element: HTMLElement, callback: () => void): void {\n NgnBase._leaveQueue.push({ element, callback });\n if (!NgnBase._leaveRafScheduled) {\n NgnBase._leaveRafScheduled = true;\n requestAnimationFrame(() => NgnBase._processLeaveQueue());\n }\n }\n\n private static _processLeaveQueue(): void {\n const queue = NgnBase._leaveQueue;\n NgnBase._leaveQueue = [];\n NgnBase._leaveRafScheduled = false;\n\n // Phase 1: Read all animations (batched queries — no interleaved mutations)\n const results: { animation: Animation | null; callback: () => void }[] = [];\n for (const { element, callback } of queue) {\n results.push({\n animation: NgnBase._findLeaveAnimation(element),\n callback,\n });\n }\n\n // Phase 2: Process results (no more style queries needed)\n for (const { animation, callback } of results) {\n if (!animation) {\n callback();\n } else {\n animation.finished\n .catch(() => {\n // ignore errors from animations being cancelled\n })\n .finally(() => {\n callback();\n });\n }\n }\n }\n\n /**\n * Recursively searches for a leave animation on the element and its parents.\n */\n private static _findLeaveAnimation(element: HTMLElement): Animation | null {\n const animations = element.getAnimations();\n const leaveAnimation = animations.find(\n a => a instanceof CSSAnimation && a.animationName.endsWith('-leave')\n );\n if (leaveAnimation) {\n return leaveAnimation;\n }\n if (element.parentElement) {\n return NgnBase._findLeaveAnimation(element.parentElement);\n }\n return null;\n }\n\n private afterLeaveInternal() {\n /**\n * After the control is hidden/removed from the DOM,\n * manually wipe the innerHTML to ensure no detached children remain\n * mapped to this component's LView slots in the browser's memory.\n * This is especially important for controls that use ng-content\n * or dynamically render child components.\n */\n this.element.nativeElement.innerHTML = '';\n this._afterLeaveCbs.forEach(cb => cb());\n this.afterLeave();\n }\n /**\n * Lifecycle hook that is called after the control has left (been removed from) the DOM.\n * Can be overridden by subclasses to perform custom actions after the leave animation.\n */\n protected afterLeave() {\n // Can be overridden by subclasses\n }\n\n /**\n * @internal\n */\n protected injectThemeTemplate<External extends boolean = false>(\n template: External extends true ? ControlTemplate : T extends string ? ThemeTemplate[T] : never,\n hostClass?: null extends T ? never : AppliedThemeClassCfg<T & string>\n ): ControlTemplateInfo<\n External extends true ? ControlTemplate : T extends string ? ThemeTemplate[T] : never\n > {\n const opts = { unstyled: this.unstyled };\n const theme = injectThemeTemplate(template, opts);\n\n const kinds = injectThemeControlKinds(theme.scope)();\n if (kinds.length) {\n this._defaultKind.set(kinds[0] as CustomKind<T>);\n }\n const colors = injectThemeColors(theme.scope)();\n if (colors.length) {\n this._defaultColor.set(colors[0] as CustomColor);\n }\n\n if (hostClass !== undefined) {\n // See constructor comment: `this` (NgnBase<T>) isn't structurally assignable\n // to NgnBaseSafe<T & string> for a generic T because `pt`'s type still\n // depends on T. Narrow the erasure to this control's own T & string, which\n // matches what NgnPtEngine actually needs here.\n new NgnPtEngine(this as unknown as NgnBaseSafe<T & string>, hostClass);\n }\n\n return theme as ControlTemplateInfo<\n External extends true ? ControlTemplate : T extends string ? ThemeTemplate[T] : never\n >;\n }\n\n /**\n * Toggles the kind and color theme classes based on the current values of the kind and color inputs.\n */\n private initializeKindAndColorClasses() {\n this.initializeAutoThemeClasses('kind', this.appliedKind);\n this.initializeAutoThemeClasses('color', this.appliedColor);\n }\n\n /**\n * Initializes automatic theme class toggling for a given prefix based on the provided string signal.\n *\n * ⚠️ Caution: This method assumes that the control's theme supports classes with the given prefix.\n *\n * ⚠️ Caution: Make sure the signal provides only string or nullish values.\n *\n * @param prefix The prefix for the theme class (e.g., 'kind' or 'color').\n * @param signal The signal that provides the current string value for the theme class.\n */\n protected initializeAutoThemeClasses(prefix: string, signal: Signal<unknown | undefined>) {\n const element = this.element.nativeElement;\n\n type ThemeClassToken = Parameters<ControlTemplateInfo<never>['class']>[0];\n /**\n * We can't know here whether the control has any kind or color classes,\n * so we cast explicitly to ThemeClassToken. In practice, controls without\n * kind or color classes will simply not toggle any classes as the input type does not allow it.\n */\n const classToken = (value: string): ThemeClassToken => value as unknown as ThemeClassToken;\n\n const togglePrefixedThemeClass = (prefix: string, value: unknown, enabled: boolean): void => {\n if (!value) {\n return;\n }\n const theme = this.theme;\n if (!theme) {\n return;\n }\n toggleClass(element, theme.class(classToken(`${prefix}-${value}`)), enabled);\n };\n\n effectWithPrevious(signal, (current, previous) => {\n togglePrefixedThemeClass(prefix, previous, false);\n togglePrefixedThemeClass(prefix, current, true);\n });\n\n this._afterLeaveCbs.push(() => {\n togglePrefixedThemeClass(prefix, signal(), false);\n });\n }\n}\n","import { computed, DestroyRef, ElementRef, inject, type Signal, signal } from '@angular/core';\nimport {\n type ControlTemplateInfo,\n type AppliedThemeClassCfg,\n getAppliedClasses,\n} from '@ngneers/controls/api/ng';\nimport { getPropertyIfExists, objectKeys } from '@ngneers/controls/utils';\nimport { classSignal, effectWithPrevious } from '@ngneers/controls/utils-ng';\n\nimport type { AnyNgnPassthrough, PassthroughValue } from './types';\nimport type { NgnBase, NgnBaseSafe } from '../base';\nimport type { ControlName, ControlTemplate } from '@ngneers/controls-themes';\n\n/** Writable, string-valued properties of `CSSStyleDeclaration` (the camelCase CSS properties). */\ntype WritableStyleKey = Extract<keyof CSSStyleDeclaration, string> &\n {\n [K in keyof CSSStyleDeclaration]: CSSStyleDeclaration[K] extends string ? K : never;\n }[keyof CSSStyleDeclaration];\n\nexport class NgnPtEngine<T extends NgnBaseSafe<Name>, Name extends ControlName> {\n private readonly pt: Signal<NgnBase<Name>>;\n private readonly ptClass: Signal<\n AppliedThemeClassCfg<T extends NgnBaseSafe<infer A> ? (A extends null ? never : A) : never>\n >;\n\n private readonly _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly _destroyRef = inject(DestroyRef);\n\n /** The passthrough values currently applied to the element, for teardown on destroy. */\n private _currentAppliedPts: ReturnType<NgnPtEngine<T, Name>['_appliedPts']>;\n\n private readonly classes = computed(() => {\n const pt = this.pt();\n if ('theme' in pt) {\n const theme = pt['theme'] as ControlTemplateInfo<ControlTemplate<Name>>;\n const res = getAppliedClasses(this.ptClass(), theme);\n return res;\n }\n return [];\n });\n\n private readonly _appliedPts = computed(() => {\n const pt = this.pt()?.pt() as AnyNgnPassthrough;\n if (!pt) {\n return;\n }\n const classes = this.classes();\n return classes.map(({ name: ptClass }) => {\n const classPt = getPropertyIfExists(pt, ptClass);\n return classPt;\n });\n });\n\n constructor(\n pt: Signal<T> | T,\n ptClass:\n | Signal<\n AppliedThemeClassCfg<\n T extends NgnBaseSafe<infer A> ? (A extends null ? never : A) : never\n >\n >\n | AppliedThemeClassCfg<T extends NgnBaseSafe<infer A> ? (A extends null ? never : A) : never>,\n options?: {\n /**\n * When `false`, the engine only toggles the resolved theme class(es) on the\n * element and does NOT apply the control's `pt` slice (styles/attributes/\n * classes/listeners) for those classes. Used for dependency-slot markers,\n * where the forwarded passthrough is applied through the nested control's\n * own engine rather than flatly on the host. Defaults to `true`.\n */\n applyPassthrough?: boolean;\n }\n ) {\n const sigPt = typeof pt === 'function' ? pt : signal(pt);\n const sigPtClass = typeof ptClass === 'function' ? ptClass : signal(ptClass);\n\n this.pt = sigPt as unknown as Signal<NgnBase<Name>>;\n this.ptClass = sigPtClass;\n\n const classes = computed(() => this.classes().map(c => c.class));\n classSignal(this._elementRef.nativeElement, classes);\n\n if (options?.applyPassthrough === false) {\n return;\n }\n\n effectWithPrevious(this._appliedPts, (current, previous) => {\n if (previous) {\n for (const classPt of previous) {\n if (!classPt) {\n continue;\n }\n this.removePreviousPtValues(classPt);\n }\n }\n if (current) {\n for (const classPt of current) {\n if (!classPt) {\n continue;\n }\n this.setNewPtValues(classPt);\n }\n }\n this._currentAppliedPts = current;\n });\n\n // Detach applied passthrough (notably event listeners) when the element is\n // destroyed, so nothing leaks past the control's lifetime.\n this._destroyRef.onDestroy(() => {\n if (!this._currentAppliedPts) {\n return;\n }\n for (const classPt of this._currentAppliedPts) {\n if (!classPt) {\n continue;\n }\n this.removePreviousPtValues(classPt);\n }\n });\n }\n\n private setNewPtValues(classPt: PassthroughValue) {\n if (classPt.$styles) {\n const keys = objectKeys(classPt.$styles);\n keys.forEach(key => {\n this._elementRef.nativeElement.style[key as WritableStyleKey] =\n (classPt.$styles?.[key] as string) || '';\n });\n }\n if (classPt.$attributes) {\n const keys = objectKeys(classPt.$attributes);\n keys.forEach(key => {\n this._elementRef.nativeElement.setAttribute(\n key as string,\n (classPt.$attributes?.[key] as string) || ''\n );\n });\n }\n if (classPt.$classes) {\n const arrayOfClasses = Array.isArray(classPt.$classes)\n ? classPt.$classes.flatMap(c => c.split(' '))\n : classPt.$classes.split(' ');\n arrayOfClasses.forEach(cls => {\n try {\n this._elementRef.nativeElement.classList.add(cls);\n } catch {\n console.warn(`Could not add class '${cls}' to element`, this._elementRef.nativeElement);\n }\n });\n }\n if (classPt.$listeners) {\n objectKeys(classPt.$listeners).forEach(eventName => {\n const handler = classPt.$listeners?.[eventName];\n if (!handler) {\n return;\n }\n this._elementRef.nativeElement.addEventListener(eventName, handler as any);\n });\n }\n }\n\n private removePreviousPtValues(classPt: PassthroughValue) {\n if (classPt.$styles) {\n const keys = objectKeys(classPt.$styles);\n keys.forEach(key => {\n this._elementRef.nativeElement.style[key as WritableStyleKey] = '';\n });\n }\n if (classPt.$attributes) {\n const keys = objectKeys(classPt.$attributes);\n keys.forEach(key => {\n this._elementRef.nativeElement.removeAttribute(key as string);\n });\n }\n if (classPt.$classes) {\n const arrayOfClasses = Array.isArray(classPt.$classes)\n ? classPt.$classes.flatMap(c => c.split(' '))\n : classPt.$classes.split(' ');\n arrayOfClasses.forEach(cls => {\n try {\n this._elementRef.nativeElement.classList.remove(cls);\n } catch {\n console.warn(\n `Could not remove class '${cls}' from element`,\n this._elementRef.nativeElement\n );\n }\n });\n }\n if (classPt.$listeners) {\n objectKeys(classPt.$listeners).forEach(eventName => {\n const listener = classPt.$listeners?.[eventName];\n if (!listener) {\n return;\n }\n this._elementRef.nativeElement.removeEventListener(eventName, listener as any);\n });\n }\n }\n}\n","import { computed, Directive, effect, inject, input, isDevMode } from '@angular/core';\nimport { setInputSignalValue } from '@ngneers/controls/utils-ng';\n\nimport { NGN_CONTROL } from '../base';\nimport { NgnPtEngine } from './pt-engine';\n\nimport type { AnyNgnPassthrough } from './types';\nimport type { FullAnyNgnBase, NgnBaseSafe } from '../base';\nimport type { AppliedThemeClassCfg } from '@ngneers/controls/api/ng';\nimport type { ControlName, ControlTemplate, ThemeTemplate } from '@ngneers/controls-themes';\n\n/** The control name backing a parent `NgnBaseSafe`, or `never` for a nameless base. */\ntype ParentName<T> = T extends NgnBaseSafe<infer A> ? (A extends null ? never : A) : never;\n\n/**\n * Union of the NON-projected dependency-slot class tokens declared on a control's\n * theme template — i.e. the valid `[ptDep]` targets for parent control `Name`.\n * Projected slots are excluded — they have no host element to bind `[ptDep]` to,\n * so accepting them would type-check a no-op.\n */\nexport type DepClass<Name extends ControlName> = ThemeTemplate[Name] extends ControlTemplate\n ? Exclude<ThemeTemplate[Name]['dependencies'][number], { projected: true }>['class']\n : never;\n\n// Internal passthrough directive; intentionally uses the non-prefixed `ptInt` selector.\n@Directive({ selector: '[ptInt]' })\nexport class NgnPt<T extends NgnBaseSafe<Name>, Name extends ControlName> {\n /** The parent control whose theme/passthrough this element pulls from. */\n public readonly ptInt = input.required<T>();\n /**\n * Parent-scope class token(s) applied to this element, along with the parent's\n * `pt` slice for those classes. Use for flat theme parts of the parent.\n */\n public readonly ptClass = input<AppliedThemeClassCfg<ParentName<T>>>();\n /**\n * Dependency-slot class on the parent. Applies the parent's marker class\n * (`{parentScope}-{ptDep}`) to this element and forwards the parent's\n * `pt[ptDep]` slice into the nested control that lives on this element, so the\n * nested control resolves it against its own theme.\n */\n public readonly ptDep = input<DepClass<ParentName<T>>>();\n\n /**\n * The nested control hosted on THIS element (present when `ptDep` targets a\n * control). `self: true` is essential: without it the injection climbs to an\n * ancestor control (e.g. the parent that owns `[ptInt]`), and the forwarding\n * effect would then overwrite the ancestor's `pt` instead of the child's.\n */\n private readonly _self = inject(NGN_CONTROL, {\n optional: true,\n self: true,\n }) as unknown as FullAnyNgnBase | null;\n\n /**\n * Flat class engine for `ptClass`: applies the parent's scope class(es) and the\n * matching `pt` slice to this element. A missing `ptClass` resolves to a no-op.\n */\n private readonly _classEngine = new NgnPtEngine(\n this.ptInt,\n computed(() => this.ptClass() ?? ({} as AppliedThemeClassCfg<ParentName<T>>))\n );\n\n /**\n * Marker engine for `ptDep`: applies ONLY the parent's `{parentScope}-{ptDep}`\n * class to this element (`applyPassthrough: false`). The forwarded slice is\n * applied separately, through the nested control's own engine.\n */\n private readonly _markerEngine = new NgnPtEngine(\n this.ptInt,\n computed(() => (this.ptDep() ?? {}) as AppliedThemeClassCfg<ParentName<T>>),\n { applyPassthrough: false }\n );\n\n /** The parent's `pt` slice for the current `ptDep` slot, or `undefined`. */\n private readonly _depSlice = computed<AnyNgnPassthrough | undefined>(() => {\n const dep = this.ptDep();\n if (!dep) {\n return undefined;\n }\n const parentPt = (this.ptInt() as unknown as FullAnyNgnBase).pt?.() as\n | Record<string, AnyNgnPassthrough>\n | undefined;\n return parentPt?.[dep as string];\n });\n\n constructor() {\n const self = this._self;\n if (!self) {\n // No nested control on this element (e.g. `ptDep` on a plain element): only\n // the marker class applies; there is no child theme to forward the slice to.\n // Warn (dev only) if a `ptDep` is actually set — read it in an effect, since\n // inputs are not yet resolved in the constructor.\n if (isDevMode()) {\n effect(() => {\n if (this.ptDep()) {\n console.warn(\n '[ptDep] is set but no nested control was found on this element; the parent' +\n \" dependency slice can't be forwarded. Did you forget to host a control here?\"\n );\n }\n });\n }\n return;\n }\n // Forward the parent's dependency slice into the nested control's own `pt`\n // input, so the child's existing engine(s) resolve it against its theme.\n // Reactive to parent `pt` changes; torn down with the directive/child. Writes\n // on every run (even `undefined`) so a slice that disappears (e.g. `ptDep`\n // cleared) clears the child's `pt` instead of leaving it stale; the child's\n // own engine already treats a falsy `pt` as a no-op.\n effect(() => {\n setInputSignalValue(self.pt, this._depSlice());\n });\n }\n}\n","import { booleanAttribute, Directive, input, model } from '@angular/core';\nimport { generateElementId } from '@ngneers/controls/utils-ng';\n\nimport { NgnBase } from './base';\n\nimport type { FormValueControl } from '@angular/forms/signals';\nimport type { ControlName } from '@ngneers/controls-themes/templates';\n\n@Directive()\nexport abstract class ValueControlBase<C extends ControlName, T>\n extends NgnBase<C>\n implements FormValueControl<T>\n{\n /**\n * The label for the control.\n */\n public readonly label = input<string | null>(null);\n /**\n * Sets the `aria-labelledby` attribute on the control.\n * @default null\n */\n public readonly labelledBy = input<string | null>(null);\n /**\n * The ID for the control\n * @default generateElementId()\n */\n public readonly inputId = input<string>(generateElementId());\n /**\n * Explicitly apply invalid state styling\n * @default false\n */\n public readonly invalid = input(false, { transform: booleanAttribute });\n /**\n * The value of the control.\n */\n public readonly value = model<T>(undefined as T);\n /**\n * Set the disabled state of the control.\n */\n public readonly disabled = input(false, { transform: booleanAttribute });\n\n public readonly readonly = input(false, { transform: booleanAttribute });\n\n public readonly touched = model(false);\n\n public readonly dirty = input(false, { transform: booleanAttribute });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { viewChild, contentChild, input, computed, Directive, inject, Component } from '@angular/core';
|
|
4
|
+
import { RouterLink } from '@angular/router';
|
|
5
|
+
import { templateTypesFn, NgnTemplate } from '@ngneers/controls/api/ng';
|
|
6
|
+
import { NgnBase, NgnPt, provideSelf } from '@ngneers/controls/base';
|
|
7
|
+
import { I18n } from '@ngneers/controls/i18n';
|
|
8
|
+
import { NgnIcon } from '@ngneers/controls/icon';
|
|
9
|
+
import { NgnItemView } from '@ngneers/controls/item-view';
|
|
10
|
+
import { NgnMenu } from '@ngneers/controls/menu';
|
|
11
|
+
import { maybeCallback } from '@ngneers/controls/utils';
|
|
12
|
+
import { breadcrumbControlTemplate } from '@ngneers/controls-themes/templates/breadcrumb';
|
|
13
|
+
|
|
14
|
+
class BreadcrumbTemplates extends NgnBase {
|
|
15
|
+
// Item template
|
|
16
|
+
_defaultItemTemplate = viewChild.required('defaultItemTemplate');
|
|
17
|
+
_userItemTemplate = contentChild('item', /* @ts-ignore */
|
|
18
|
+
...(ngDevMode ? [{ debugName: "_userItemTemplate" }] : /* istanbul ignore next */ []));
|
|
19
|
+
/**
|
|
20
|
+
* Set a custom template for an item.
|
|
21
|
+
* Can also be set using an `<ng-template>` element with `#item` template reference variable.
|
|
22
|
+
*/
|
|
23
|
+
templateItem = input(null, /* @ts-ignore */
|
|
24
|
+
...(ngDevMode ? [{ debugName: "templateItem" }] : /* istanbul ignore next */ []));
|
|
25
|
+
itemTemplate = computed(() => this._userItemTemplate() ?? this.templateItem() ?? this._defaultItemTemplate(), /* @ts-ignore */
|
|
26
|
+
...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
|
|
27
|
+
// Separator template
|
|
28
|
+
_defaultSeparatorTemplate = viewChild.required('defaultSeparatorTemplate');
|
|
29
|
+
_userSeparatorTemplate = contentChild('separator', /* @ts-ignore */
|
|
30
|
+
...(ngDevMode ? [{ debugName: "_userSeparatorTemplate" }] : /* istanbul ignore next */ []));
|
|
31
|
+
/**
|
|
32
|
+
* Set a custom template for a separator.
|
|
33
|
+
* Can also be set using an `<ng-template>` element with `#separator` template reference variable.
|
|
34
|
+
*/
|
|
35
|
+
templateSeparator = input(null, /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "templateSeparator" }] : /* istanbul ignore next */ []));
|
|
37
|
+
separatorTemplate = computed(() => this._userSeparatorTemplate() ?? this.templateSeparator() ?? this._defaultSeparatorTemplate(), /* @ts-ignore */
|
|
38
|
+
...(ngDevMode ? [{ debugName: "separatorTemplate" }] : /* istanbul ignore next */ []));
|
|
39
|
+
// Overflow template
|
|
40
|
+
_defaultOverflowTemplate = viewChild.required('defaultOverflowTemplate');
|
|
41
|
+
_userOverflowTemplate = contentChild('overflow', /* @ts-ignore */
|
|
42
|
+
...(ngDevMode ? [{ debugName: "_userOverflowTemplate" }] : /* istanbul ignore next */ []));
|
|
43
|
+
/**
|
|
44
|
+
* Set a custom template for the overflowing items.
|
|
45
|
+
* Can also be set using an `<ng-template>` element with `#overflow` template reference variable.
|
|
46
|
+
*/
|
|
47
|
+
templateOverflow = input(null, /* @ts-ignore */
|
|
48
|
+
...(ngDevMode ? [{ debugName: "templateOverflow" }] : /* istanbul ignore next */ []));
|
|
49
|
+
overflowTemplate = computed(() => this._userOverflowTemplate() ?? this.templateOverflow() ?? this._defaultOverflowTemplate(), /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "overflowTemplate" }] : /* istanbul ignore next */ []));
|
|
51
|
+
/**
|
|
52
|
+
* Types for the breadcrumb templates.
|
|
53
|
+
*/
|
|
54
|
+
templateTypes = templateTypesFn();
|
|
55
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: BreadcrumbTemplates, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
56
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.5", type: BreadcrumbTemplates, isStandalone: true, inputs: { templateItem: { classPropertyName: "templateItem", publicName: "templateItem", isSignal: true, isRequired: false, transformFunction: null }, templateSeparator: { classPropertyName: "templateSeparator", publicName: "templateSeparator", isSignal: true, isRequired: false, transformFunction: null }, templateOverflow: { classPropertyName: "templateOverflow", publicName: "templateOverflow", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "_userItemTemplate", first: true, predicate: ["item"], descendants: true, isSignal: true }, { propertyName: "_userSeparatorTemplate", first: true, predicate: ["separator"], descendants: true, isSignal: true }, { propertyName: "_userOverflowTemplate", first: true, predicate: ["overflow"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_defaultItemTemplate", first: true, predicate: ["defaultItemTemplate"], descendants: true, isSignal: true }, { propertyName: "_defaultSeparatorTemplate", first: true, predicate: ["defaultSeparatorTemplate"], descendants: true, isSignal: true }, { propertyName: "_defaultOverflowTemplate", first: true, predicate: ["defaultOverflowTemplate"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0 });
|
|
57
|
+
}
|
|
58
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: BreadcrumbTemplates, decorators: [{
|
|
59
|
+
type: Directive
|
|
60
|
+
}], propDecorators: { _defaultItemTemplate: [{ type: i0.ViewChild, args: ['defaultItemTemplate', { isSignal: true }] }], _userItemTemplate: [{ type: i0.ContentChild, args: ['item', { isSignal: true }] }], templateItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateItem", required: false }] }], _defaultSeparatorTemplate: [{ type: i0.ViewChild, args: ['defaultSeparatorTemplate', { isSignal: true }] }], _userSeparatorTemplate: [{ type: i0.ContentChild, args: ['separator', { isSignal: true }] }], templateSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateSeparator", required: false }] }], _defaultOverflowTemplate: [{ type: i0.ViewChild, args: ['defaultOverflowTemplate', { isSignal: true }] }], _userOverflowTemplate: [{ type: i0.ContentChild, args: ['overflow', { isSignal: true }] }], templateOverflow: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateOverflow", required: false }] }] } });
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @category control
|
|
64
|
+
*/
|
|
65
|
+
class NgnBreadcrumb extends BreadcrumbTemplates {
|
|
66
|
+
theme = this.injectThemeTemplate(breadcrumbControlTemplate, 'root');
|
|
67
|
+
i18n = inject(I18n).translations;
|
|
68
|
+
/**
|
|
69
|
+
* The breadcrumb entries to render, ordered from root to the current page.
|
|
70
|
+
* @see {@link BreadcrumbItem}
|
|
71
|
+
*/
|
|
72
|
+
items = input.required(/* @ts-ignore */
|
|
73
|
+
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
74
|
+
/**
|
|
75
|
+
* Icon rendered between adjacent breadcrumb items.
|
|
76
|
+
* Falls back to the theme's default separator icon when unset.
|
|
77
|
+
*/
|
|
78
|
+
iconItemSeparator = input(/* @ts-ignore */
|
|
79
|
+
...(ngDevMode ? [undefined, { debugName: "iconItemSeparator" }] : /* istanbul ignore next */ []));
|
|
80
|
+
/**
|
|
81
|
+
* Icon for the overflow menu trigger shown when items are collapsed to save space.
|
|
82
|
+
* Falls back to the theme's default overflow icon when unset.
|
|
83
|
+
*/
|
|
84
|
+
iconOverflow = input(/* @ts-ignore */
|
|
85
|
+
...(ngDevMode ? [undefined, { debugName: "iconOverflow" }] : /* istanbul ignore next */ []));
|
|
86
|
+
maybeCallback = maybeCallback;
|
|
87
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnBreadcrumb, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
88
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.5", type: NgnBreadcrumb, isStandalone: true, selector: "ngn-breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, iconItemSeparator: { classPropertyName: "iconItemSeparator", publicName: "iconItemSeparator", isSignal: true, isRequired: false, transformFunction: null }, iconOverflow: { classPropertyName: "iconOverflow", publicName: "iconOverflow", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideSelf(NgnBreadcrumb)], usesInheritance: true, ngImport: i0, template: "<ngn-item-view\n #itemView\n [ptInt]=\"this\"\n [ptDep]=\"'item-view'\"\n [items]=\"items()\"\n [idField]=\"'id'\"\n [templateItem]=\"itemTemplate()\"\n [templateSeparator]=\"separatorTemplate()\"\n [templateOverflow]=\"usedOverflowTemplate\"\n [iconItemSeparator]=\"iconItemSeparator()\"\n [overflowStrategy]=\"'start'\"\n [overflowStrategyFreezeCount]=\"1\"\n/>\n\n<ng-template #usedOverflowTemplate [ngnTemplate]=\"itemView.templateTypes.overflow\" let-overflow>\n <ng-container\n *ngTemplateOutlet=\"\n overflowTemplate();\n context: { $implicit: { icon: iconOverflow(), overflowingItems: overflow.overflowItems } }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\n <a\n [ptInt]=\"this\"\n [ptClass]=\"{\n item: true,\n 'item-clickable': !!item.callback || !!item.route,\n }\"\n (click)=\"item.callback?.()\"\n [routerLink]=\"item.route\"\n >\n {{ maybeCallback(item.label) }}\n </a>\n</ng-template>\n\n<ng-template #defaultSeparatorTemplate [ngnTemplate]=\"templateTypes.separator\" let-separator>\n <span [ptInt]=\"this\" [ptClass]=\"'separator'\">\n <ngn-icon defaultIcon=\"breadcrumb-separator\" [icon]=\"separator.icon\" />\n </span>\n</ng-template>\n\n<ng-template #defaultOverflowTemplate [ngnTemplate]=\"templateTypes.overflow\" let-overflow>\n <button\n #menuAnchor\n [ptInt]=\"this\"\n [ptClass]=\"'overflow'\"\n [attr.aria-label]=\"i18n['breadcrumb_overflow']()\"\n (click)=\"menu.show()\"\n >\n <ngn-icon defaultIcon=\"breadcrumb-overflow\" [icon]=\"overflow.icon\" />\n </button>\n <ngn-menu\n #menu\n [ptInt]=\"this\"\n [ptDep]=\"'menu'\"\n [popover]=\"true\"\n [items]=\"overflow.overflowingItems\"\n [anchor]=\"menuAnchor\"\n />\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass", "ptDep"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgnTemplate, selector: "ng-template[ngnTemplate]", inputs: ["ngnTemplate"] }, { kind: "component", type: NgnIcon, selector: "ngn-icon", inputs: ["defaultIcon", "icon"] }, { kind: "component", type: NgnItemView, selector: "ngn-item-view", inputs: ["idField", "items", "separator", "iconItemSeparator", "overflowStrategy", "overflowStrategyFreezeCount", "overflowStrategyIndex", "sameWidthItems"] }, { kind: "component", type: NgnMenu, selector: "ngn-menu", inputs: ["elementId", "anchor", "items", "autoAnchorAria", "popover", "placement", "iconSubmenuIndicator", "isSubMenu", "openSubmenuOnHover", "open"], outputs: ["closed", "closing", "closeAll", "openChange"] }] });
|
|
89
|
+
}
|
|
90
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnBreadcrumb, decorators: [{
|
|
91
|
+
type: Component,
|
|
92
|
+
args: [{ selector: 'ngn-breadcrumb', imports: [NgnPt, RouterLink, NgTemplateOutlet, NgnTemplate, NgnIcon, NgnItemView, NgnMenu], providers: [provideSelf(NgnBreadcrumb)], template: "<ngn-item-view\n #itemView\n [ptInt]=\"this\"\n [ptDep]=\"'item-view'\"\n [items]=\"items()\"\n [idField]=\"'id'\"\n [templateItem]=\"itemTemplate()\"\n [templateSeparator]=\"separatorTemplate()\"\n [templateOverflow]=\"usedOverflowTemplate\"\n [iconItemSeparator]=\"iconItemSeparator()\"\n [overflowStrategy]=\"'start'\"\n [overflowStrategyFreezeCount]=\"1\"\n/>\n\n<ng-template #usedOverflowTemplate [ngnTemplate]=\"itemView.templateTypes.overflow\" let-overflow>\n <ng-container\n *ngTemplateOutlet=\"\n overflowTemplate();\n context: { $implicit: { icon: iconOverflow(), overflowingItems: overflow.overflowItems } }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\n <a\n [ptInt]=\"this\"\n [ptClass]=\"{\n item: true,\n 'item-clickable': !!item.callback || !!item.route,\n }\"\n (click)=\"item.callback?.()\"\n [routerLink]=\"item.route\"\n >\n {{ maybeCallback(item.label) }}\n </a>\n</ng-template>\n\n<ng-template #defaultSeparatorTemplate [ngnTemplate]=\"templateTypes.separator\" let-separator>\n <span [ptInt]=\"this\" [ptClass]=\"'separator'\">\n <ngn-icon defaultIcon=\"breadcrumb-separator\" [icon]=\"separator.icon\" />\n </span>\n</ng-template>\n\n<ng-template #defaultOverflowTemplate [ngnTemplate]=\"templateTypes.overflow\" let-overflow>\n <button\n #menuAnchor\n [ptInt]=\"this\"\n [ptClass]=\"'overflow'\"\n [attr.aria-label]=\"i18n['breadcrumb_overflow']()\"\n (click)=\"menu.show()\"\n >\n <ngn-icon defaultIcon=\"breadcrumb-overflow\" [icon]=\"overflow.icon\" />\n </button>\n <ngn-menu\n #menu\n [ptInt]=\"this\"\n [ptDep]=\"'menu'\"\n [popover]=\"true\"\n [items]=\"overflow.overflowingItems\"\n [anchor]=\"menuAnchor\"\n />\n</ng-template>\n" }]
|
|
93
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], iconItemSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconItemSeparator", required: false }] }], iconOverflow: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOverflow", required: false }] }] } });
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Generated bundle index. Do not edit.
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
export { NgnBreadcrumb };
|
|
100
|
+
//# sourceMappingURL=ngneers-controls-breadcrumb.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngneers-controls-breadcrumb.mjs","sources":["../../src/breadcrumb/breadcrumb-templates.ts","../../src/breadcrumb/breadcrumb.ts","../../src/breadcrumb/breadcrumb.html","../../src/breadcrumb/ngneers-controls-breadcrumb.ts"],"sourcesContent":["import { computed, contentChild, Directive, input, TemplateRef, viewChild } from '@angular/core';\nimport { templateTypesFn } from '@ngneers/controls/api/ng';\nimport { NgnBase } from '@ngneers/controls/base';\n\nimport type { ItemTemplateType, OverflowTemplateType, SeparatorTemplateType } from './types';\n\n@Directive()\nexport abstract class BreadcrumbTemplates extends NgnBase<'breadcrumb'> {\n // Item template\n private readonly _defaultItemTemplate =\n viewChild.required<TemplateRef<typeof this.templateTypes.item>>('defaultItemTemplate');\n private readonly _userItemTemplate =\n contentChild<TemplateRef<typeof this.templateTypes.item>>('item');\n /**\n * Set a custom template for an item.\n * Can also be set using an `<ng-template>` element with `#item` template reference variable.\n */\n public readonly templateItem = input<TemplateRef<typeof this.templateTypes.item> | null>(null);\n protected readonly itemTemplate = computed(\n () => this._userItemTemplate() ?? this.templateItem() ?? this._defaultItemTemplate()\n );\n\n // Separator template\n private readonly _defaultSeparatorTemplate = viewChild.required<\n TemplateRef<typeof this.templateTypes.separator>\n >('defaultSeparatorTemplate');\n private readonly _userSeparatorTemplate =\n contentChild<TemplateRef<typeof this.templateTypes.separator>>('separator');\n /**\n * Set a custom template for a separator.\n * Can also be set using an `<ng-template>` element with `#separator` template reference variable.\n */\n public readonly templateSeparator = input<TemplateRef<\n typeof this.templateTypes.separator\n > | null>(null);\n protected readonly separatorTemplate = computed(\n () =>\n this._userSeparatorTemplate() ?? this.templateSeparator() ?? this._defaultSeparatorTemplate()\n );\n\n // Overflow template\n private readonly _defaultOverflowTemplate =\n viewChild.required<TemplateRef<typeof this.templateTypes.overflow>>('defaultOverflowTemplate');\n private readonly _userOverflowTemplate =\n contentChild<TemplateRef<typeof this.templateTypes.overflow>>('overflow');\n /**\n * Set a custom template for the overflowing items.\n * Can also be set using an `<ng-template>` element with `#overflow` template reference variable.\n */\n public readonly templateOverflow = input<TemplateRef<typeof this.templateTypes.overflow> | null>(\n null\n );\n protected readonly overflowTemplate = computed(\n () => this._userOverflowTemplate() ?? this.templateOverflow() ?? this._defaultOverflowTemplate()\n );\n\n /**\n * Types for the breadcrumb templates.\n */\n public readonly templateTypes = templateTypesFn<{\n /**\n * Type of the template variable for the item template.\n */\n item: ItemTemplateType;\n separator: SeparatorTemplateType;\n overflow: OverflowTemplateType;\n }>();\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport { Component, inject, input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { NgnTemplate } from '@ngneers/controls/api/ng';\nimport { NgnPt, provideSelf } from '@ngneers/controls/base';\nimport { I18n } from '@ngneers/controls/i18n';\nimport { NgnIcon } from '@ngneers/controls/icon';\nimport { NgnItemView } from '@ngneers/controls/item-view';\nimport { NgnMenu } from '@ngneers/controls/menu';\nimport { maybeCallback } from '@ngneers/controls/utils';\nimport { breadcrumbControlTemplate } from '@ngneers/controls-themes/templates/breadcrumb';\n\nimport { BreadcrumbTemplates } from './breadcrumb-templates';\n\nimport type { BreadcrumbItem } from './types';\nimport type { IconType } from '@ngneers/controls-custom-types';\n\n/**\n * @category control\n */\n@Component({\n selector: 'ngn-breadcrumb',\n templateUrl: './breadcrumb.html',\n imports: [NgnPt, RouterLink, NgTemplateOutlet, NgnTemplate, NgnIcon, NgnItemView, NgnMenu],\n\n providers: [provideSelf(NgnBreadcrumb)],\n})\nexport class NgnBreadcrumb extends BreadcrumbTemplates {\n protected readonly theme = this.injectThemeTemplate(breadcrumbControlTemplate, 'root');\n protected readonly i18n = inject(I18n).translations;\n\n /**\n * The breadcrumb entries to render, ordered from root to the current page.\n * @see {@link BreadcrumbItem}\n */\n public readonly items = input.required<BreadcrumbItem[]>();\n /**\n * Icon rendered between adjacent breadcrumb items.\n * Falls back to the theme's default separator icon when unset.\n */\n public readonly iconItemSeparator = input<IconType>();\n /**\n * Icon for the overflow menu trigger shown when items are collapsed to save space.\n * Falls back to the theme's default overflow icon when unset.\n */\n public readonly iconOverflow = input<IconType>();\n\n protected readonly maybeCallback = maybeCallback;\n}\n","<ngn-item-view\n #itemView\n [ptInt]=\"this\"\n [ptDep]=\"'item-view'\"\n [items]=\"items()\"\n [idField]=\"'id'\"\n [templateItem]=\"itemTemplate()\"\n [templateSeparator]=\"separatorTemplate()\"\n [templateOverflow]=\"usedOverflowTemplate\"\n [iconItemSeparator]=\"iconItemSeparator()\"\n [overflowStrategy]=\"'start'\"\n [overflowStrategyFreezeCount]=\"1\"\n/>\n\n<ng-template #usedOverflowTemplate [ngnTemplate]=\"itemView.templateTypes.overflow\" let-overflow>\n <ng-container\n *ngTemplateOutlet=\"\n overflowTemplate();\n context: { $implicit: { icon: iconOverflow(), overflowingItems: overflow.overflowItems } }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\n <a\n [ptInt]=\"this\"\n [ptClass]=\"{\n item: true,\n 'item-clickable': !!item.callback || !!item.route,\n }\"\n (click)=\"item.callback?.()\"\n [routerLink]=\"item.route\"\n >\n {{ maybeCallback(item.label) }}\n </a>\n</ng-template>\n\n<ng-template #defaultSeparatorTemplate [ngnTemplate]=\"templateTypes.separator\" let-separator>\n <span [ptInt]=\"this\" [ptClass]=\"'separator'\">\n <ngn-icon defaultIcon=\"breadcrumb-separator\" [icon]=\"separator.icon\" />\n </span>\n</ng-template>\n\n<ng-template #defaultOverflowTemplate [ngnTemplate]=\"templateTypes.overflow\" let-overflow>\n <button\n #menuAnchor\n [ptInt]=\"this\"\n [ptClass]=\"'overflow'\"\n [attr.aria-label]=\"i18n['breadcrumb_overflow']()\"\n (click)=\"menu.show()\"\n >\n <ngn-icon defaultIcon=\"breadcrumb-overflow\" [icon]=\"overflow.icon\" />\n </button>\n <ngn-menu\n #menu\n [ptInt]=\"this\"\n [ptDep]=\"'menu'\"\n [popover]=\"true\"\n [items]=\"overflow.overflowingItems\"\n [anchor]=\"menuAnchor\"\n />\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { isSignal, computed, contentChildren, viewChild, input, inject, Injector, effect, runInInjectionContext, Component } from '@angular/core';
|
|
3
|
+
import { elementSizeSignal, elementsSizesSignal } from '@ngneers/controls/api/ng';
|
|
4
|
+
import { NgnBase, NGN_CONTROL, NgnPt, provideSelf } from '@ngneers/controls/base';
|
|
5
|
+
import { NgnRovingGroup } from '@ngneers/controls/roving-focus';
|
|
6
|
+
import { generateElementId } from '@ngneers/controls/utils-ng';
|
|
7
|
+
import { buttonGroupControlTemplate } from '@ngneers/controls-themes/templates/button-group';
|
|
8
|
+
|
|
9
|
+
const FOCUSABLE_SELECTOR = 'button, a[href], input, select, textarea, [tabindex]';
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the element that should own the roving tab stop for a projected
|
|
12
|
+
* control. The control's host is the focusable element for a native
|
|
13
|
+
* `button[ngnButton]`/`a[ngnButton]`; for wrapper controls like
|
|
14
|
+
* `ngn-toggle-button` the real tab stop is a focusable descendant.
|
|
15
|
+
*/
|
|
16
|
+
function resolveFocusable(host) {
|
|
17
|
+
if (host.matches(FOCUSABLE_SELECTOR))
|
|
18
|
+
return host;
|
|
19
|
+
return host.querySelector(FOCUSABLE_SELECTOR) ?? host;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Reactive disabled flag for a projected control so roving navigation skips it.
|
|
23
|
+
* Prefer the control's own `disabled` signal (e.g. `ngn-toggle-button`); fall
|
|
24
|
+
* back to reflecting the focusable element's native `disabled`/`aria-disabled`
|
|
25
|
+
* for plain `button[ngnButton]`, which has no such signal.
|
|
26
|
+
*/
|
|
27
|
+
function resolveDisabled(ref, element) {
|
|
28
|
+
const controlDisabled = ref.disabled;
|
|
29
|
+
if (isSignal(controlDisabled)) {
|
|
30
|
+
return controlDisabled;
|
|
31
|
+
}
|
|
32
|
+
return computed(() => element.matches(':disabled') || element.getAttribute('aria-disabled') === 'true');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @category control
|
|
36
|
+
*/
|
|
37
|
+
class NgnButtonGroup extends NgnBase {
|
|
38
|
+
theme = this.injectThemeTemplate(buttonGroupControlTemplate, 'root');
|
|
39
|
+
_contentRef = contentChildren(NGN_CONTROL, /* @ts-ignore */
|
|
40
|
+
...(ngDevMode ? [{ debugName: "_contentRef" }] : /* istanbul ignore next */ []));
|
|
41
|
+
_content = computed(() => this._contentRef().map(ref => ref.element.nativeElement), /* @ts-ignore */
|
|
42
|
+
...(ngDevMode ? [{ debugName: "_content" }] : /* istanbul ignore next */ []));
|
|
43
|
+
/**
|
|
44
|
+
* The roving-focus group on the inner container. Coordinates a single tab
|
|
45
|
+
* stop across the projected buttons: the active button gets `tabindex="0"`,
|
|
46
|
+
* the rest `-1`, and arrow keys move focus between them.
|
|
47
|
+
*/
|
|
48
|
+
_roving = viewChild.required(NgnRovingGroup);
|
|
49
|
+
_parentSize = elementSizeSignal(this.element.nativeElement);
|
|
50
|
+
_contentSizes = elementsSizesSignal(this._content);
|
|
51
|
+
_contentWidth = computed(() => {
|
|
52
|
+
const sizes = this._contentSizes();
|
|
53
|
+
return sizes.reduce((acc, size) => acc + size.width, 0);
|
|
54
|
+
}, /* @ts-ignore */
|
|
55
|
+
...(ngDevMode ? [{ debugName: "_contentWidth" }] : /* istanbul ignore next */ []));
|
|
56
|
+
/**
|
|
57
|
+
* Defines the orientation of the button group.
|
|
58
|
+
* - 'auto' - The orientation is determined based on the available space.
|
|
59
|
+
* - 'horizontal' - The buttons are arranged horizontally. (Default for `auto` if enough space)
|
|
60
|
+
* - 'vertical' - The buttons are arranged vertically.
|
|
61
|
+
* @default 'auto'
|
|
62
|
+
*/
|
|
63
|
+
orientation = input('auto', /* @ts-ignore */
|
|
64
|
+
...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
65
|
+
appliedOrientation = computed(() => {
|
|
66
|
+
const orientation = this.orientation();
|
|
67
|
+
if (orientation === 'auto') {
|
|
68
|
+
return this._contentWidth() > this._parentSize().width ? 'vertical' : 'horizontal';
|
|
69
|
+
}
|
|
70
|
+
return orientation;
|
|
71
|
+
}, /* @ts-ignore */
|
|
72
|
+
...(ngDevMode ? [{ debugName: "appliedOrientation" }] : /* istanbul ignore next */ []));
|
|
73
|
+
_injector = inject(Injector);
|
|
74
|
+
constructor() {
|
|
75
|
+
super();
|
|
76
|
+
// Register the projected buttons as roving items so the group owns a single
|
|
77
|
+
// tab stop instead of every button being tabbable. Re-runs when the set of
|
|
78
|
+
// children changes; onCleanup unregisters the previous set. `generateElementId`
|
|
79
|
+
// calls `inject()`, so it must run in an injection context.
|
|
80
|
+
effect(onCleanup => {
|
|
81
|
+
const group = this._roving();
|
|
82
|
+
const items = this._contentRef().map(ref => {
|
|
83
|
+
// The projected control's host is not always the focusable element:
|
|
84
|
+
// `button[ngnButton]` is itself the button, but `ngn-toggle-button`
|
|
85
|
+
// wraps a native `<button>`. Roving must own the real tab stop.
|
|
86
|
+
const host = ref.element.nativeElement;
|
|
87
|
+
const element = resolveFocusable(host);
|
|
88
|
+
if (!element.id) {
|
|
89
|
+
element.id = runInInjectionContext(this._injector, () => generateElementId());
|
|
90
|
+
}
|
|
91
|
+
return { id: element.id, element, disabled: resolveDisabled(ref, element) };
|
|
92
|
+
});
|
|
93
|
+
items.forEach(item => group.register(item));
|
|
94
|
+
onCleanup(() => items.forEach(item => group.unregister(item)));
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnButtonGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
98
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.5", type: NgnButtonGroup, isStandalone: true, selector: "ngn-button-group", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideSelf(NgnButtonGroup)], queries: [{ propertyName: "_contentRef", predicate: NGN_CONTROL, isSignal: true }], viewQueries: [{ propertyName: "_roving", first: true, predicate: NgnRovingGroup, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div\n #content\n ngnRovingGroup\n [orientation]=\"appliedOrientation()\"\n [ptInt]=\"this\"\n [ptClass]=\"{\n horizontal: appliedOrientation() === 'horizontal',\n vertical: appliedOrientation() === 'vertical',\n }\"\n role=\"group\"\n>\n <ng-content />\n</div>\n", dependencies: [{ kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass", "ptDep"] }, { kind: "directive", type: NgnRovingGroup, selector: "[ngnRovingGroup]", inputs: ["orientation", "rovingMode", "rovingWrap"], outputs: ["activeItemChange"], exportAs: ["ngnRovingGroup"] }] });
|
|
99
|
+
}
|
|
100
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnButtonGroup, decorators: [{
|
|
101
|
+
type: Component,
|
|
102
|
+
args: [{ selector: 'ngn-button-group', imports: [NgnPt, NgnRovingGroup], providers: [provideSelf(NgnButtonGroup)], template: "<div\n #content\n ngnRovingGroup\n [orientation]=\"appliedOrientation()\"\n [ptInt]=\"this\"\n [ptClass]=\"{\n horizontal: appliedOrientation() === 'horizontal',\n vertical: appliedOrientation() === 'vertical',\n }\"\n role=\"group\"\n>\n <ng-content />\n</div>\n" }]
|
|
103
|
+
}], ctorParameters: () => [], propDecorators: { _contentRef: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => NGN_CONTROL), { isSignal: true }] }], _roving: [{ type: i0.ViewChild, args: [i0.forwardRef(() => NgnRovingGroup), { isSignal: true }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }] } });
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Generated bundle index. Do not edit.
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
export { NgnButtonGroup };
|
|
110
|
+
//# sourceMappingURL=ngneers-controls-button-group.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngneers-controls-button-group.mjs","sources":["../../src/button-group/button-group.ts","../../src/button-group/button-group.html","../../src/button-group/ngneers-controls-button-group.ts"],"sourcesContent":["import {\n Component,\n computed,\n contentChildren,\n effect,\n inject,\n Injector,\n input,\n isSignal,\n runInInjectionContext,\n viewChild,\n type Signal,\n} from '@angular/core';\nimport { elementSizeSignal, elementsSizesSignal } from '@ngneers/controls/api/ng';\nimport { NgnBase, NGN_CONTROL, provideSelf, NgnPt } from '@ngneers/controls/base';\nimport { NgnRovingGroup } from '@ngneers/controls/roving-focus';\nimport { generateElementId } from '@ngneers/controls/utils-ng';\nimport { buttonGroupControlTemplate } from '@ngneers/controls-themes/templates/button-group';\n\nconst FOCUSABLE_SELECTOR = 'button, a[href], input, select, textarea, [tabindex]';\n\n/**\n * Resolve the element that should own the roving tab stop for a projected\n * control. The control's host is the focusable element for a native\n * `button[ngnButton]`/`a[ngnButton]`; for wrapper controls like\n * `ngn-toggle-button` the real tab stop is a focusable descendant.\n */\nfunction resolveFocusable(host: HTMLElement): HTMLElement {\n if (host.matches(FOCUSABLE_SELECTOR)) return host;\n return host.querySelector<HTMLElement>(FOCUSABLE_SELECTOR) ?? host;\n}\n\n/**\n * Reactive disabled flag for a projected control so roving navigation skips it.\n * Prefer the control's own `disabled` signal (e.g. `ngn-toggle-button`); fall\n * back to reflecting the focusable element's native `disabled`/`aria-disabled`\n * for plain `button[ngnButton]`, which has no such signal.\n */\nfunction resolveDisabled(ref: object, element: HTMLElement): Signal<boolean> {\n const controlDisabled = (ref as { disabled?: unknown }).disabled;\n if (isSignal(controlDisabled)) {\n return controlDisabled as Signal<boolean>;\n }\n return computed(\n () => element.matches(':disabled') || element.getAttribute('aria-disabled') === 'true'\n );\n}\n\n/**\n * @category control\n */\n@Component({\n selector: 'ngn-button-group',\n templateUrl: './button-group.html',\n imports: [NgnPt, NgnRovingGroup],\n\n providers: [provideSelf(NgnButtonGroup)],\n})\nexport class NgnButtonGroup extends NgnBase<'buttonGroup'> {\n protected readonly theme = this.injectThemeTemplate(buttonGroupControlTemplate, 'root');\n\n private readonly _contentRef = contentChildren(NGN_CONTROL);\n private readonly _content = computed(() =>\n this._contentRef().map(ref => ref.element.nativeElement)\n );\n\n /**\n * The roving-focus group on the inner container. Coordinates a single tab\n * stop across the projected buttons: the active button gets `tabindex=\"0\"`,\n * the rest `-1`, and arrow keys move focus between them.\n */\n private readonly _roving = viewChild.required(NgnRovingGroup);\n private readonly _parentSize = elementSizeSignal(this.element.nativeElement);\n private readonly _contentSizes = elementsSizesSignal(this._content);\n private readonly _contentWidth = computed(() => {\n const sizes = this._contentSizes();\n return sizes.reduce((acc, size) => acc + size.width, 0);\n });\n\n /**\n * Defines the orientation of the button group.\n * - 'auto' - The orientation is determined based on the available space.\n * - 'horizontal' - The buttons are arranged horizontally. (Default for `auto` if enough space)\n * - 'vertical' - The buttons are arranged vertically.\n * @default 'auto'\n */\n public readonly orientation = input<'auto' | 'horizontal' | 'vertical'>('auto');\n protected readonly appliedOrientation = computed(() => {\n const orientation = this.orientation();\n if (orientation === 'auto') {\n return this._contentWidth() > this._parentSize().width ? 'vertical' : 'horizontal';\n }\n return orientation;\n });\n\n private readonly _injector = inject(Injector);\n\n constructor() {\n super();\n\n // Register the projected buttons as roving items so the group owns a single\n // tab stop instead of every button being tabbable. Re-runs when the set of\n // children changes; onCleanup unregisters the previous set. `generateElementId`\n // calls `inject()`, so it must run in an injection context.\n effect(onCleanup => {\n const group = this._roving();\n const items = this._contentRef().map(ref => {\n // The projected control's host is not always the focusable element:\n // `button[ngnButton]` is itself the button, but `ngn-toggle-button`\n // wraps a native `<button>`. Roving must own the real tab stop.\n const host = ref.element.nativeElement;\n const element = resolveFocusable(host);\n if (!element.id) {\n element.id = runInInjectionContext(this._injector, () => generateElementId());\n }\n return { id: element.id, element, disabled: resolveDisabled(ref, element) };\n });\n items.forEach(item => group.register(item));\n onCleanup(() => items.forEach(item => group.unregister(item)));\n });\n }\n}\n","<div\n #content\n ngnRovingGroup\n [orientation]=\"appliedOrientation()\"\n [ptInt]=\"this\"\n [ptClass]=\"{\n horizontal: appliedOrientation() === 'horizontal',\n vertical: appliedOrientation() === 'vertical',\n }\"\n role=\"group\"\n>\n <ng-content />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, booleanAttribute, Directive, output, Component } from '@angular/core';
|
|
3
|
+
import { NgnBase, provideSelf } from '@ngneers/controls/base';
|
|
4
|
+
import { NgnIcon } from '@ngneers/controls/icon';
|
|
5
|
+
import { NgnTooltip } from '@ngneers/controls/tooltip';
|
|
6
|
+
import { toggleClass, maybeCallback } from '@ngneers/controls/utils';
|
|
7
|
+
import { buttonControlTemplate } from '@ngneers/controls-themes/templates/button';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @category control
|
|
11
|
+
*/
|
|
12
|
+
class NgnButton extends NgnBase {
|
|
13
|
+
theme = this.injectThemeTemplate(buttonControlTemplate, {
|
|
14
|
+
root: true,
|
|
15
|
+
inline: () => this.inline(),
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Whether the button is displayed inline.
|
|
19
|
+
* This will make the button height fit the current line height.
|
|
20
|
+
*/
|
|
21
|
+
inline = input(false, { ...(ngDevMode ? { debugName: "inline" } : /* istanbul ignore next */ {}), transform: booleanAttribute,
|
|
22
|
+
// alias follows the ngn{Directive}{Prop} convention for the `button[ngnButton], a[ngnButton]` selector
|
|
23
|
+
alias: 'ngnButtonInline' });
|
|
24
|
+
constructor() {
|
|
25
|
+
super();
|
|
26
|
+
toggleClass(this.element.nativeElement, this.theme.class('root'), true);
|
|
27
|
+
}
|
|
28
|
+
afterLeave() {
|
|
29
|
+
toggleClass(this.element.nativeElement, this.theme.class('root'), false);
|
|
30
|
+
}
|
|
31
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnButton, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
32
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: NgnButton, isStandalone: true, selector: "button[ngnButton], a[ngnButton]", inputs: { inline: { classPropertyName: "inline", publicName: "ngnButtonInline", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideSelf(NgnButton)], exportAs: ["ngnButton"], usesInheritance: true, ngImport: i0 });
|
|
33
|
+
}
|
|
34
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnButton, decorators: [{
|
|
35
|
+
type: Directive,
|
|
36
|
+
args: [{
|
|
37
|
+
selector: 'button[ngnButton], a[ngnButton]',
|
|
38
|
+
providers: [provideSelf(NgnButton)],
|
|
39
|
+
exportAs: 'ngnButton',
|
|
40
|
+
}]
|
|
41
|
+
}], ctorParameters: () => [], propDecorators: { inline: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngnButtonInline", required: false }] }] } });
|
|
42
|
+
|
|
43
|
+
class NgnActionButton extends NgnBase {
|
|
44
|
+
theme = null;
|
|
45
|
+
/**
|
|
46
|
+
* The configuration describing the button: its label, icon, tooltip, value,
|
|
47
|
+
* and the action callback fired on click.
|
|
48
|
+
* @see {@link NgnActionButtonConfig}
|
|
49
|
+
*/
|
|
50
|
+
config = input.required(/* @ts-ignore */
|
|
51
|
+
...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
|
|
52
|
+
/**
|
|
53
|
+
* Whether the inner button is displayed inline (line-height sized).
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
inline = input(false, { ...(ngDevMode ? { debugName: "inline" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
57
|
+
/**
|
|
58
|
+
* Emits the {@link config}'s `value` when the button is clicked, after its
|
|
59
|
+
* `action` callback has run.
|
|
60
|
+
*/
|
|
61
|
+
clicked = output();
|
|
62
|
+
maybeCallback = maybeCallback;
|
|
63
|
+
click(event) {
|
|
64
|
+
// Run the config's action callback first, then emit `clicked` — consumers
|
|
65
|
+
// (snackbar, dialog) treat `clicked` as the dismiss signal, so the action
|
|
66
|
+
// must fire before the host tears the button down.
|
|
67
|
+
this.config().action?.(event);
|
|
68
|
+
this.clicked.emit(this.config().value);
|
|
69
|
+
}
|
|
70
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnActionButton, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
71
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: NgnActionButton, isStandalone: true, selector: "ngn-action-button", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, inline: { classPropertyName: "inline", publicName: "inline", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, providers: [provideSelf(NgnActionButton)], usesInheritance: true, ngImport: i0, template: "<button\n type=\"button\"\n ngnButton\n [kind]=\"config().kind\"\n [color]=\"config().color\"\n [ngnButtonInline]=\"inline()\"\n [disabled]=\"config().disabled\"\n (click)=\"click($event)\"\n [attr.data-test-id]=\"config().testId\"\n [ngnTooltip]=\"config().kind === 'icon' ? maybeCallback(config().label) : null\"\n ngnTooltipAutoAriaMode=\"label\"\n>\n @if (config().icon || config().defaultIcon) {\n <ngn-icon [icon]=\"config().icon\" [defaultIcon]=\"config().defaultIcon\" />\n } @else {\n {{ maybeCallback(config().label) }}\n }\n</button>\n", dependencies: [{ kind: "directive", type: NgnButton, selector: "button[ngnButton], a[ngnButton]", inputs: ["ngnButtonInline"], exportAs: ["ngnButton"] }, { kind: "component", type: NgnIcon, selector: "ngn-icon", inputs: ["defaultIcon", "icon"] }, { kind: "directive", type: NgnTooltip, selector: "[ngnTooltip]", inputs: ["ngnTooltip", "ngnTooltipShowOnlyIfTruncated", "ngnTooltipSize", "ngnTooltipOptions", "ngnTooltipPlacement", "ngnTooltipOffset", "ngnTooltipShowDelay", "ngnTooltipHideDelay", "ngnTooltipShowArrow", "ngnTooltipShowOnHover", "ngnTooltipShowOnFocus", "ngnTooltipHideOnTooltipHover", "ngnTooltipHideOnClick", "ngnTooltipAutoAriaMode"], exportAs: ["ngnTooltip"] }] });
|
|
72
|
+
}
|
|
73
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnActionButton, decorators: [{
|
|
74
|
+
type: Component,
|
|
75
|
+
args: [{ selector: 'ngn-action-button', imports: [NgnButton, NgnIcon, NgnTooltip], providers: [provideSelf(NgnActionButton)], template: "<button\n type=\"button\"\n ngnButton\n [kind]=\"config().kind\"\n [color]=\"config().color\"\n [ngnButtonInline]=\"inline()\"\n [disabled]=\"config().disabled\"\n (click)=\"click($event)\"\n [attr.data-test-id]=\"config().testId\"\n [ngnTooltip]=\"config().kind === 'icon' ? maybeCallback(config().label) : null\"\n ngnTooltipAutoAriaMode=\"label\"\n>\n @if (config().icon || config().defaultIcon) {\n <ngn-icon [icon]=\"config().icon\" [defaultIcon]=\"config().defaultIcon\" />\n } @else {\n {{ maybeCallback(config().label) }}\n }\n</button>\n" }]
|
|
76
|
+
}], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], inline: [{ type: i0.Input, args: [{ isSignal: true, alias: "inline", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Generated bundle index. Do not edit.
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
export { NgnActionButton, NgnButton };
|
|
83
|
+
//# sourceMappingURL=ngneers-controls-button.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngneers-controls-button.mjs","sources":["../../src/button/button.ts","../../src/button/action-button.ts","../../src/button/action-button.html","../../src/button/ngneers-controls-button.ts"],"sourcesContent":["import { booleanAttribute, Directive, input } from '@angular/core';\nimport { NgnBase, provideSelf } from '@ngneers/controls/base';\nimport { toggleClass } from '@ngneers/controls/utils';\nimport { buttonControlTemplate } from '@ngneers/controls-themes/templates/button';\n\n/**\n * @category control\n */\n@Directive({\n selector: 'button[ngnButton], a[ngnButton]',\n providers: [provideSelf(NgnButton)],\n exportAs: 'ngnButton',\n})\nexport class NgnButton extends NgnBase<'button'> {\n protected readonly theme = this.injectThemeTemplate(buttonControlTemplate, {\n root: true,\n inline: () => this.inline(),\n });\n\n /**\n * Whether the button is displayed inline.\n * This will make the button height fit the current line height.\n */\n public readonly inline = input(false, {\n transform: booleanAttribute,\n // alias follows the ngn{Directive}{Prop} convention for the `button[ngnButton], a[ngnButton]` selector\n alias: 'ngnButtonInline',\n });\n\n constructor() {\n super();\n toggleClass(this.element.nativeElement, this.theme.class('root'), true);\n }\n\n protected override afterLeave(): void {\n toggleClass(this.element.nativeElement, this.theme.class('root'), false);\n }\n}\n","import { booleanAttribute, Component, input, output } from '@angular/core';\nimport { NgnBase, provideSelf } from '@ngneers/controls/base';\nimport { NgnIcon } from '@ngneers/controls/icon';\nimport { NgnTooltip } from '@ngneers/controls/tooltip';\nimport { maybeCallback } from '@ngneers/controls/utils';\n\nimport { NgnButton } from './button';\n\nimport type { NgnActionButtonConfig } from '@ngneers/controls/api';\n\n@Component({\n selector: 'ngn-action-button',\n templateUrl: 'action-button.html',\n imports: [NgnButton, NgnIcon, NgnTooltip],\n providers: [provideSelf(NgnActionButton)],\n})\nexport class NgnActionButton<T> extends NgnBase<null> {\n protected readonly theme = null;\n\n /**\n * The configuration describing the button: its label, icon, tooltip, value,\n * and the action callback fired on click.\n * @see {@link NgnActionButtonConfig}\n */\n public readonly config = input.required<NgnActionButtonConfig<T>>();\n\n /**\n * Whether the inner button is displayed inline (line-height sized).\n * @default false\n */\n public readonly inline = input(false, { transform: booleanAttribute });\n\n /**\n * Emits the {@link config}'s `value` when the button is clicked, after its\n * `action` callback has run.\n */\n public readonly clicked = output<T>();\n\n protected readonly maybeCallback = maybeCallback;\n\n protected click(event: PointerEvent): void {\n // Run the config's action callback first, then emit `clicked` — consumers\n // (snackbar, dialog) treat `clicked` as the dismiss signal, so the action\n // must fire before the host tears the button down.\n this.config().action?.(event);\n this.clicked.emit(this.config().value);\n }\n}\n","<button\n type=\"button\"\n ngnButton\n [kind]=\"config().kind\"\n [color]=\"config().color\"\n [ngnButtonInline]=\"inline()\"\n [disabled]=\"config().disabled\"\n (click)=\"click($event)\"\n [attr.data-test-id]=\"config().testId\"\n [ngnTooltip]=\"config().kind === 'icon' ? maybeCallback(config().label) : null\"\n ngnTooltipAutoAriaMode=\"label\"\n>\n @if (config().icon || config().defaultIcon) {\n <ngn-icon [icon]=\"config().icon\" [defaultIcon]=\"config().defaultIcon\" />\n } @else {\n {{ maybeCallback(config().label) }}\n }\n</button>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, input, output, computed, Component } from '@angular/core';
|
|
3
|
+
import { Platform } from '@ngneers/controls/api/ng';
|
|
4
|
+
import { I18n } from '@ngneers/controls/i18n';
|
|
5
|
+
import { NgnInput } from '@ngneers/controls/input';
|
|
6
|
+
import { NgnInputField } from '@ngneers/controls/input-field';
|
|
7
|
+
import { DATE_TIME_MASKS, NgnMaskInput } from '@ngneers/controls/mask-input';
|
|
8
|
+
|
|
9
|
+
class CalendarTime {
|
|
10
|
+
i18n = inject(I18n).translations;
|
|
11
|
+
isTouchDevice = inject(Platform).isTouchDevice();
|
|
12
|
+
component = input.required(/* @ts-ignore */
|
|
13
|
+
...(ngDevMode ? [{ debugName: "component" }] : /* istanbul ignore next */ []));
|
|
14
|
+
currentValue = input.required(/* @ts-ignore */
|
|
15
|
+
...(ngDevMode ? [{ debugName: "currentValue" }] : /* istanbul ignore next */ []));
|
|
16
|
+
showSeconds = input.required(/* @ts-ignore */
|
|
17
|
+
...(ngDevMode ? [{ debugName: "showSeconds" }] : /* istanbul ignore next */ []));
|
|
18
|
+
timeChange = output();
|
|
19
|
+
mask = computed(() => this.showSeconds() ? DATE_TIME_MASKS.time : DATE_TIME_MASKS.timeShort, /* @ts-ignore */
|
|
20
|
+
...(ngDevMode ? [{ debugName: "mask" }] : /* istanbul ignore next */ []));
|
|
21
|
+
value = computed(() => {
|
|
22
|
+
const currentValue = this.currentValue();
|
|
23
|
+
if (!currentValue)
|
|
24
|
+
return null;
|
|
25
|
+
function padZero(num) {
|
|
26
|
+
return num < 10 ? `0${num}` : `${num}`;
|
|
27
|
+
}
|
|
28
|
+
const hours = padZero(currentValue.getHours());
|
|
29
|
+
const minutes = padZero(currentValue.getMinutes());
|
|
30
|
+
const seconds = padZero(currentValue.getSeconds());
|
|
31
|
+
return this.showSeconds() ? `${hours}:${minutes}:${seconds}` : `${hours}:${minutes}`;
|
|
32
|
+
}, /* @ts-ignore */
|
|
33
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
34
|
+
onValueChange(value) {
|
|
35
|
+
if (!value) {
|
|
36
|
+
this.timeChange.emit(null);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const [hours, minutes, seconds] = value.split(':').map(Number);
|
|
40
|
+
if (hours === undefined || minutes === undefined) {
|
|
41
|
+
throw new Error(`Invalid time value: ${value}`);
|
|
42
|
+
}
|
|
43
|
+
if (isNaN(hours)) {
|
|
44
|
+
this.timeChange.emit(null);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const fixedMinutes = isNaN(minutes) ? 0 : minutes;
|
|
48
|
+
const currentDate = this.currentValue();
|
|
49
|
+
const newDate = new Date(currentDate || new Date());
|
|
50
|
+
newDate.setHours(hours);
|
|
51
|
+
newDate.setMinutes(fixedMinutes);
|
|
52
|
+
if (this.showSeconds()) {
|
|
53
|
+
const fixedSeconds = isNaN(seconds ?? 0) ? 0 : (seconds ?? 0);
|
|
54
|
+
newDate.setSeconds(fixedSeconds);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
newDate.setSeconds(0);
|
|
58
|
+
}
|
|
59
|
+
if (newDate.getMinutes() !== currentDate?.getMinutes() ||
|
|
60
|
+
newDate.getHours() !== currentDate?.getHours() ||
|
|
61
|
+
(this.showSeconds() && newDate.getSeconds() !== currentDate?.getSeconds())) {
|
|
62
|
+
this.timeChange.emit(newDate);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CalendarTime, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
66
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CalendarTime, isStandalone: true, selector: "ngn-calendar-time", inputs: { component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null }, currentValue: { classPropertyName: "currentValue", publicName: "currentValue", isSignal: true, isRequired: true, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { timeChange: "timeChange" }, ngImport: i0, template: "<div>\n @if (isTouchDevice) {\n <ngn-input-field>\n <input\n type=\"time\"\n ngnInput\n [step]=\"showSeconds() ? 1 : 60\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event || '')\"\n />\n </ngn-input-field>\n } @else {\n <ngn-input-field>\n <ngn-mask-input\n [mask]=\"mask()\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event ?? '')\"\n />\n </ngn-input-field>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgnInput, selector: "input[ngnInput], textarea[ngnInput]", inputs: ["invalid", "value"], outputs: ["valueChange"], exportAs: ["ngnInput"] }, { kind: "component", type: NgnMaskInput, selector: "ngn-mask-input", inputs: ["mask"] }, { kind: "component", type: NgnInputField, selector: "ngn-input-field", inputs: ["label", "labelledBy", "labelKind", "inputId", "showClearButton", "iconClearButton", "tabindex", "invalid", "readonly", "disabled"] }] });
|
|
67
|
+
}
|
|
68
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CalendarTime, decorators: [{
|
|
69
|
+
type: Component,
|
|
70
|
+
args: [{ selector: 'ngn-calendar-time', imports: [NgnInput, NgnMaskInput, NgnInputField], template: "<div>\n @if (isTouchDevice) {\n <ngn-input-field>\n <input\n type=\"time\"\n ngnInput\n [step]=\"showSeconds() ? 1 : 60\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event || '')\"\n />\n </ngn-input-field>\n } @else {\n <ngn-input-field>\n <ngn-mask-input\n [mask]=\"mask()\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event ?? '')\"\n />\n </ngn-input-field>\n }\n</div>\n" }]
|
|
71
|
+
}], propDecorators: { component: [{ type: i0.Input, args: [{ isSignal: true, alias: "component", required: true }] }], currentValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentValue", required: true }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: true }] }], timeChange: [{ type: i0.Output, args: ["timeChange"] }] } });
|
|
72
|
+
|
|
73
|
+
export { CalendarTime };
|
|
74
|
+
//# sourceMappingURL=ngneers-controls-calendar-time-CJT5AFlA.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngneers-controls-calendar-time-CJT5AFlA.mjs","sources":["../../src/calendar/time/time.ts","../../src/calendar/time/time.html"],"sourcesContent":["import { Component, computed, inject, input, output } from '@angular/core';\nimport { Platform } from '@ngneers/controls/api/ng';\nimport { I18n } from '@ngneers/controls/i18n';\nimport { NgnInput } from '@ngneers/controls/input';\nimport { NgnInputField } from '@ngneers/controls/input-field';\nimport { DATE_TIME_MASKS, NgnMaskInput } from '@ngneers/controls/mask-input';\n\nimport type { NgnBaseSafe } from '@ngneers/controls/base';\n\n@Component({\n selector: 'ngn-calendar-time',\n templateUrl: './time.html',\n imports: [NgnInput, NgnMaskInput, NgnInputField],\n})\nexport class CalendarTime {\n protected readonly i18n = inject(I18n).translations;\n protected readonly isTouchDevice = inject(Platform).isTouchDevice();\n\n public readonly component = input.required<NgnBaseSafe<'calendar'>>();\n public readonly currentValue = input.required<Date | null>();\n public readonly showSeconds = input.required<boolean>();\n public readonly timeChange = output<Date | null>();\n public readonly mask = computed(() =>\n this.showSeconds() ? DATE_TIME_MASKS.time : DATE_TIME_MASKS.timeShort\n );\n\n protected readonly value = computed(() => {\n const currentValue = this.currentValue();\n if (!currentValue) return null;\n\n function padZero(num: number): string {\n return num < 10 ? `0${num}` : `${num}`;\n }\n\n const hours = padZero(currentValue.getHours());\n const minutes = padZero(currentValue.getMinutes());\n const seconds = padZero(currentValue.getSeconds());\n\n return this.showSeconds() ? `${hours}:${minutes}:${seconds}` : `${hours}:${minutes}`;\n });\n\n protected onValueChange(value: string) {\n if (!value) {\n this.timeChange.emit(null);\n return;\n }\n\n const [hours, minutes, seconds] = value.split(':').map(Number);\n\n if (hours === undefined || minutes === undefined) {\n throw new Error(`Invalid time value: ${value}`);\n }\n\n if (isNaN(hours)) {\n this.timeChange.emit(null);\n return;\n }\n\n const fixedMinutes = isNaN(minutes) ? 0 : minutes;\n\n const currentDate = this.currentValue();\n const newDate = new Date(currentDate || new Date());\n newDate.setHours(hours);\n newDate.setMinutes(fixedMinutes);\n\n if (this.showSeconds()) {\n const fixedSeconds = isNaN(seconds ?? 0) ? 0 : (seconds ?? 0);\n newDate.setSeconds(fixedSeconds);\n } else {\n newDate.setSeconds(0);\n }\n\n if (\n newDate.getMinutes() !== currentDate?.getMinutes() ||\n newDate.getHours() !== currentDate?.getHours() ||\n (this.showSeconds() && newDate.getSeconds() !== currentDate?.getSeconds())\n ) {\n this.timeChange.emit(newDate);\n }\n }\n}\n","<div>\n @if (isTouchDevice) {\n <ngn-input-field>\n <input\n type=\"time\"\n ngnInput\n [step]=\"showSeconds() ? 1 : 60\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event || '')\"\n />\n </ngn-input-field>\n } @else {\n <ngn-input-field>\n <ngn-mask-input\n [mask]=\"mask()\"\n [value]=\"value()\"\n (valueChange)=\"onValueChange($event ?? '')\"\n />\n </ngn-input-field>\n }\n</div>\n"],"names":[],"mappings":"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"}
|