ng-primitives 0.64.0 → 0.65.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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
|
|
2
|
-
import { inject, DestroyRef, signal, afterNextRender, effect, untracked, Renderer2, ElementRef } from '@angular/core';
|
|
2
|
+
import { inject, DestroyRef, signal, afterNextRender, afterRenderEffect, effect, untracked, Renderer2, ElementRef } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
4
|
import { pipe, NEVER, EMPTY } from 'rxjs';
|
|
5
5
|
import { takeUntil, catchError, defaultIfEmpty } from 'rxjs/operators';
|
|
@@ -86,7 +86,7 @@ function booleanAttributeBinding(element, attribute, value) {
|
|
|
86
86
|
if (!value) {
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
afterRenderEffect({
|
|
90
90
|
write: () => value() ? element.setAttribute(attribute, '') : element.removeAttribute(attribute),
|
|
91
91
|
});
|
|
92
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ng-primitives-utils.mjs","sources":["../../../../packages/ng-primitives/utils/src/forms/providers.ts","../../../../packages/ng-primitives/utils/src/observables/take-until-destroyed.ts","../../../../packages/ng-primitives/utils/src/forms/status.ts","../../../../packages/ng-primitives/utils/src/helpers/attributes.ts","../../../../packages/ng-primitives/utils/src/helpers/disposables.ts","../../../../packages/ng-primitives/utils/src/helpers/unique-id.ts","../../../../packages/ng-primitives/utils/src/signals/index.ts","../../../../packages/ng-primitives/utils/src/ui/dimensions.ts","../../../../packages/ng-primitives/utils/src/ng-primitives-utils.ts"],"sourcesContent":["import { ExistingProvider, Type } from '@angular/core';\nimport { NG_VALUE_ACCESSOR } from '@angular/forms';\n\n/**\n * A simple helper function to provide a value accessor for a given type.\n * @param type The type to provide the value accessor for\n */\nexport function provideValueAccessor<T>(type: Type<T>): ExistingProvider {\n return { provide: NG_VALUE_ACCESSOR, useExisting: type, multi: true };\n}\n","/* eslint-disable @nx/workspace-take-until-destroyed */\nimport { DestroyRef } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { EMPTY, MonoTypeOperatorFunction, NEVER, pipe } from 'rxjs';\nimport { catchError, defaultIfEmpty, takeUntil } from 'rxjs/operators';\n\n/**\n * The built-in `takeUntilDestroyed` operator does not handle the case when the component is destroyed before the source observable emits.\n * This operator ensures that the source observable completes gracefully without throwing an error.\n * https://github.com/angular/angular/issues/54527#issuecomment-2098254508\n *\n * @internal\n */\nexport function safeTakeUntilDestroyed<T>(destroyRef?: DestroyRef): MonoTypeOperatorFunction<T> {\n return pipe(\n takeUntil(\n NEVER.pipe(\n takeUntilDestroyed(destroyRef),\n catchError(() => EMPTY),\n defaultIfEmpty(null),\n ),\n ),\n );\n}\n","import { DestroyRef, Signal, WritableSignal, afterNextRender, inject, signal } from '@angular/core';\nimport { NgControl } from '@angular/forms';\nimport { safeTakeUntilDestroyed } from '../observables/take-until-destroyed';\n\nexport interface NgpControlStatus {\n valid: boolean | null;\n invalid: boolean | null;\n pristine: boolean | null;\n dirty: boolean | null;\n touched: boolean | null;\n pending: boolean | null;\n disabled: boolean | null;\n}\n\nfunction setStatusSignal(\n control: NgControl | null,\n status: WritableSignal<NgpControlStatus>,\n): void {\n if (!control?.control) {\n return;\n }\n\n status.set({\n valid: control?.control?.valid ?? null,\n invalid: control?.control?.invalid ?? null,\n pristine: control?.control?.pristine ?? null,\n dirty: control?.control?.dirty ?? null,\n touched: control?.control?.touched ?? null,\n pending: control?.control?.pending ?? null,\n disabled: control?.control?.disabled ?? null,\n });\n}\n\nfunction subscribeToControlStatus(\n control: NgControl | null,\n status: WritableSignal<NgpControlStatus>,\n destroyRef?: DestroyRef,\n): void {\n if (!control?.control) {\n return;\n }\n\n control.control.events\n .pipe(safeTakeUntilDestroyed(destroyRef))\n .subscribe(() => setStatusSignal(control, status));\n}\n\n/**\n * A utility function to get the status of an Angular form control as a reactive signal.\n * This function injects the NgControl and returns a signal that reflects the control's status.\n * @internal\n */\nexport function controlStatus(): Signal<NgpControlStatus> {\n const control = inject(NgControl, { optional: true });\n const destroyRef = inject(DestroyRef);\n\n const status = signal<NgpControlStatus>({\n valid: null,\n invalid: null,\n pristine: null,\n dirty: null,\n touched: null,\n pending: null,\n disabled: null,\n });\n\n // Fallback if control is not yet available\n if (!control?.control) {\n // There is still a chance that the control will be available i.e. after executing OnInit lifecycle hook\n // in `formControlName` directive, so we set up an effect to subscribe to the control status\n afterNextRender({\n write: () => {\n // If control is still not available, we do nothing, otherwise we subscribe to the control status\n if (control?.control) {\n subscribeToControlStatus(control, status, destroyRef);\n // We re-set the status to ensure it reflects the current state on initialization\n setStatusSignal(control, status);\n }\n },\n });\n return status;\n }\n\n subscribeToControlStatus(control, status);\n\n return status;\n}\n","import { afterNextRender, Signal } from '@angular/core';\n\nexport function booleanAttributeBinding(\n element: HTMLElement,\n attribute: string,\n value: Signal<boolean> | undefined,\n): void {\n if (!value) {\n return;\n }\n\n afterNextRender({\n write: () =>\n value() ? element.setAttribute(attribute, '') : element.removeAttribute(attribute),\n });\n}\n","import { DestroyRef, inject } from '@angular/core';\n\n/**\n * Disposable functions are a way to manage timers, intervals, and event listeners\n * that should be cleared when a component is destroyed.\n *\n * This is heavily inspired by Headless UI disposables:\n * https://github.com/tailwindlabs/headlessui/blob/main/packages/%40headlessui-react/src/utils/disposables.ts\n */\nexport function injectDisposables() {\n const destroyRef = inject(DestroyRef);\n let isDestroyed = false;\n\n destroyRef.onDestroy(() => (isDestroyed = true));\n\n return {\n /**\n * Set a timeout that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @returns A function to clear the timeout\n */\n setTimeout: (callback: () => void, delay: number) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = setTimeout(callback, delay);\n const cleanup = () => clearTimeout(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set an interval that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @param target\n * @param type\n * @param listener\n * @param options\n * @returns A function to clear the interval\n */\n addEventListener: <K extends keyof HTMLElementEventMap>(\n target: EventTarget,\n type: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n target.addEventListener(type, listener as EventListenerOrEventListenerObject, options);\n const cleanup = () =>\n target.removeEventListener(type, listener as EventListenerOrEventListenerObject, options);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set an interval that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @returns A function to clear the interval\n */\n setInterval: (callback: () => void, delay: number) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = setInterval(callback, delay);\n const cleanup = () => clearInterval(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set a requestAnimationFrame that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @returns A function to clear the requestAnimationFrame\n */\n requestAnimationFrame: (callback: FrameRequestCallback) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = requestAnimationFrame(callback);\n const cleanup = () => cancelAnimationFrame(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n };\n}\n","/**\n * Store a map of unique ids for elements so that there are no collisions.\n */\nconst uniqueIdMap = new Map<string, number>();\n\n/**\n * Generate a unique id for an element\n * @param prefix - The prefix to use for the id\n * @returns The generated id\n */\nexport function uniqueId(prefix: string): string {\n const id = uniqueIdMap.get(prefix) ?? 0;\n uniqueIdMap.set(prefix, id + 1);\n return `${prefix}-${id}`;\n}\n","import { effect, Injector, Signal, signal, untracked } from '@angular/core';\n\n/**\n * Listen for changes to a signal and call a function when the signal changes.\n * @param source\n * @param fn\n * @param options\n * @param options.injector\n * @internal\n */\nexport function onChange<T>(\n source: Signal<T | null | undefined>,\n fn: (value: T | null | undefined, previousValue: T | null | undefined) => void,\n options?: { injector: Injector },\n): void {\n const previousValue = signal(source());\n\n effect(\n () => {\n const value = source();\n if (value !== previousValue()) {\n untracked(() => fn(value, previousValue()));\n previousValue.set(value);\n }\n },\n { injector: options?.injector },\n );\n\n // call the fn with the initial value\n fn(source(), null);\n}\n\n/**\n * Listen for changes to a boolean signal and call one of two functions when the signal changes.\n * @param source\n * @param onTrue\n * @param onFalse\n * @param options\n */\nexport function onBooleanChange(\n source: Signal<boolean>,\n onTrue?: () => void,\n onFalse?: () => void,\n options?: { injector: Injector },\n): void {\n onChange(source, value => (value ? onTrue?.() : onFalse?.()), options);\n}\n","import { ElementRef, Renderer2, afterNextRender, inject, signal } from '@angular/core';\n\n/**\n * Injects the dimensions of the element\n * @returns The dimensions of the element\n */\nexport function injectDimensions() {\n const renderer = inject(Renderer2);\n const element = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n const size = signal<{ width: number; height: number; mounted: boolean }>({\n width: 0,\n height: 0,\n mounted: false,\n });\n let transitionDuration: string | undefined, animationName: string | undefined;\n\n afterNextRender({\n earlyRead: () => {\n transitionDuration = element.style.transitionDuration;\n animationName = element.style.animationName;\n },\n write: () => {\n // block any animations/transitions so the element renders at its full dimensions\n renderer.setStyle(element, 'transitionDuration', '0s');\n renderer.setStyle(element, 'animationName', 'none');\n },\n read: () => {\n const { width, height } = element.getBoundingClientRect();\n size.set({ width, height, mounted: true });\n // restore the original transition duration and animation name\n renderer.setStyle(element, 'transitionDuration', transitionDuration);\n renderer.setStyle(element, 'animationName', animationName);\n },\n });\n\n return size;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ng-primitives-utils.mjs","sources":["../../../../packages/ng-primitives/utils/src/forms/providers.ts","../../../../packages/ng-primitives/utils/src/observables/take-until-destroyed.ts","../../../../packages/ng-primitives/utils/src/forms/status.ts","../../../../packages/ng-primitives/utils/src/helpers/attributes.ts","../../../../packages/ng-primitives/utils/src/helpers/disposables.ts","../../../../packages/ng-primitives/utils/src/helpers/unique-id.ts","../../../../packages/ng-primitives/utils/src/signals/index.ts","../../../../packages/ng-primitives/utils/src/ui/dimensions.ts","../../../../packages/ng-primitives/utils/src/ng-primitives-utils.ts"],"sourcesContent":["import { ExistingProvider, Type } from '@angular/core';\nimport { NG_VALUE_ACCESSOR } from '@angular/forms';\n\n/**\n * A simple helper function to provide a value accessor for a given type.\n * @param type The type to provide the value accessor for\n */\nexport function provideValueAccessor<T>(type: Type<T>): ExistingProvider {\n return { provide: NG_VALUE_ACCESSOR, useExisting: type, multi: true };\n}\n","/* eslint-disable @nx/workspace-take-until-destroyed */\nimport { DestroyRef } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { EMPTY, MonoTypeOperatorFunction, NEVER, pipe } from 'rxjs';\nimport { catchError, defaultIfEmpty, takeUntil } from 'rxjs/operators';\n\n/**\n * The built-in `takeUntilDestroyed` operator does not handle the case when the component is destroyed before the source observable emits.\n * This operator ensures that the source observable completes gracefully without throwing an error.\n * https://github.com/angular/angular/issues/54527#issuecomment-2098254508\n *\n * @internal\n */\nexport function safeTakeUntilDestroyed<T>(destroyRef?: DestroyRef): MonoTypeOperatorFunction<T> {\n return pipe(\n takeUntil(\n NEVER.pipe(\n takeUntilDestroyed(destroyRef),\n catchError(() => EMPTY),\n defaultIfEmpty(null),\n ),\n ),\n );\n}\n","import { DestroyRef, Signal, WritableSignal, afterNextRender, inject, signal } from '@angular/core';\nimport { NgControl } from '@angular/forms';\nimport { safeTakeUntilDestroyed } from '../observables/take-until-destroyed';\n\nexport interface NgpControlStatus {\n valid: boolean | null;\n invalid: boolean | null;\n pristine: boolean | null;\n dirty: boolean | null;\n touched: boolean | null;\n pending: boolean | null;\n disabled: boolean | null;\n}\n\nfunction setStatusSignal(\n control: NgControl | null,\n status: WritableSignal<NgpControlStatus>,\n): void {\n if (!control?.control) {\n return;\n }\n\n status.set({\n valid: control?.control?.valid ?? null,\n invalid: control?.control?.invalid ?? null,\n pristine: control?.control?.pristine ?? null,\n dirty: control?.control?.dirty ?? null,\n touched: control?.control?.touched ?? null,\n pending: control?.control?.pending ?? null,\n disabled: control?.control?.disabled ?? null,\n });\n}\n\nfunction subscribeToControlStatus(\n control: NgControl | null,\n status: WritableSignal<NgpControlStatus>,\n destroyRef?: DestroyRef,\n): void {\n if (!control?.control) {\n return;\n }\n\n control.control.events\n .pipe(safeTakeUntilDestroyed(destroyRef))\n .subscribe(() => setStatusSignal(control, status));\n}\n\n/**\n * A utility function to get the status of an Angular form control as a reactive signal.\n * This function injects the NgControl and returns a signal that reflects the control's status.\n * @internal\n */\nexport function controlStatus(): Signal<NgpControlStatus> {\n const control = inject(NgControl, { optional: true });\n const destroyRef = inject(DestroyRef);\n\n const status = signal<NgpControlStatus>({\n valid: null,\n invalid: null,\n pristine: null,\n dirty: null,\n touched: null,\n pending: null,\n disabled: null,\n });\n\n // Fallback if control is not yet available\n if (!control?.control) {\n // There is still a chance that the control will be available i.e. after executing OnInit lifecycle hook\n // in `formControlName` directive, so we set up an effect to subscribe to the control status\n afterNextRender({\n write: () => {\n // If control is still not available, we do nothing, otherwise we subscribe to the control status\n if (control?.control) {\n subscribeToControlStatus(control, status, destroyRef);\n // We re-set the status to ensure it reflects the current state on initialization\n setStatusSignal(control, status);\n }\n },\n });\n return status;\n }\n\n subscribeToControlStatus(control, status);\n\n return status;\n}\n","import { afterRenderEffect, Signal } from '@angular/core';\n\nexport function booleanAttributeBinding(\n element: HTMLElement,\n attribute: string,\n value: Signal<boolean> | undefined,\n): void {\n if (!value) {\n return;\n }\n\n afterRenderEffect({\n write: () =>\n value() ? element.setAttribute(attribute, '') : element.removeAttribute(attribute),\n });\n}\n","import { DestroyRef, inject } from '@angular/core';\n\n/**\n * Disposable functions are a way to manage timers, intervals, and event listeners\n * that should be cleared when a component is destroyed.\n *\n * This is heavily inspired by Headless UI disposables:\n * https://github.com/tailwindlabs/headlessui/blob/main/packages/%40headlessui-react/src/utils/disposables.ts\n */\nexport function injectDisposables() {\n const destroyRef = inject(DestroyRef);\n let isDestroyed = false;\n\n destroyRef.onDestroy(() => (isDestroyed = true));\n\n return {\n /**\n * Set a timeout that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @returns A function to clear the timeout\n */\n setTimeout: (callback: () => void, delay: number) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = setTimeout(callback, delay);\n const cleanup = () => clearTimeout(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set an interval that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @param target\n * @param type\n * @param listener\n * @param options\n * @returns A function to clear the interval\n */\n addEventListener: <K extends keyof HTMLElementEventMap>(\n target: EventTarget,\n type: K,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions,\n ) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n target.addEventListener(type, listener as EventListenerOrEventListenerObject, options);\n const cleanup = () =>\n target.removeEventListener(type, listener as EventListenerOrEventListenerObject, options);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set an interval that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @param delay The delay before the callback is executed\n * @returns A function to clear the interval\n */\n setInterval: (callback: () => void, delay: number) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = setInterval(callback, delay);\n const cleanup = () => clearInterval(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n /**\n * Set a requestAnimationFrame that will be cleared when the component is destroyed.\n * @param callback The callback to execute\n * @returns A function to clear the requestAnimationFrame\n */\n requestAnimationFrame: (callback: FrameRequestCallback) => {\n if (isDestroyed) {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n return () => {};\n }\n\n const id = requestAnimationFrame(callback);\n const cleanup = () => cancelAnimationFrame(id);\n destroyRef.onDestroy(cleanup);\n return cleanup;\n },\n };\n}\n","/**\n * Store a map of unique ids for elements so that there are no collisions.\n */\nconst uniqueIdMap = new Map<string, number>();\n\n/**\n * Generate a unique id for an element\n * @param prefix - The prefix to use for the id\n * @returns The generated id\n */\nexport function uniqueId(prefix: string): string {\n const id = uniqueIdMap.get(prefix) ?? 0;\n uniqueIdMap.set(prefix, id + 1);\n return `${prefix}-${id}`;\n}\n","import { effect, Injector, Signal, signal, untracked } from '@angular/core';\n\n/**\n * Listen for changes to a signal and call a function when the signal changes.\n * @param source\n * @param fn\n * @param options\n * @param options.injector\n * @internal\n */\nexport function onChange<T>(\n source: Signal<T | null | undefined>,\n fn: (value: T | null | undefined, previousValue: T | null | undefined) => void,\n options?: { injector: Injector },\n): void {\n const previousValue = signal(source());\n\n effect(\n () => {\n const value = source();\n if (value !== previousValue()) {\n untracked(() => fn(value, previousValue()));\n previousValue.set(value);\n }\n },\n { injector: options?.injector },\n );\n\n // call the fn with the initial value\n fn(source(), null);\n}\n\n/**\n * Listen for changes to a boolean signal and call one of two functions when the signal changes.\n * @param source\n * @param onTrue\n * @param onFalse\n * @param options\n */\nexport function onBooleanChange(\n source: Signal<boolean>,\n onTrue?: () => void,\n onFalse?: () => void,\n options?: { injector: Injector },\n): void {\n onChange(source, value => (value ? onTrue?.() : onFalse?.()), options);\n}\n","import { ElementRef, Renderer2, afterNextRender, inject, signal } from '@angular/core';\n\n/**\n * Injects the dimensions of the element\n * @returns The dimensions of the element\n */\nexport function injectDimensions() {\n const renderer = inject(Renderer2);\n const element = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n const size = signal<{ width: number; height: number; mounted: boolean }>({\n width: 0,\n height: 0,\n mounted: false,\n });\n let transitionDuration: string | undefined, animationName: string | undefined;\n\n afterNextRender({\n earlyRead: () => {\n transitionDuration = element.style.transitionDuration;\n animationName = element.style.animationName;\n },\n write: () => {\n // block any animations/transitions so the element renders at its full dimensions\n renderer.setStyle(element, 'transitionDuration', '0s');\n renderer.setStyle(element, 'animationName', 'none');\n },\n read: () => {\n const { width, height } = element.getBoundingClientRect();\n size.set({ width, height, mounted: true });\n // restore the original transition duration and animation name\n renderer.setStyle(element, 'transitionDuration', transitionDuration);\n renderer.setStyle(element, 'animationName', animationName);\n },\n });\n\n return size;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "ng-primitives",
|
|
3
3
|
"description": "Angular Primitives is a low-level headless UI component library with a focus on accessibility, customization, and developer experience. ",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.65.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"angular",
|
|
8
8
|
"primitives",
|
|
@@ -75,14 +75,14 @@
|
|
|
75
75
|
"types": "./autofill/index.d.ts",
|
|
76
76
|
"default": "./fesm2022/ng-primitives-autofill.mjs"
|
|
77
77
|
},
|
|
78
|
-
"./button": {
|
|
79
|
-
"types": "./button/index.d.ts",
|
|
80
|
-
"default": "./fesm2022/ng-primitives-button.mjs"
|
|
81
|
-
},
|
|
82
78
|
"./avatar": {
|
|
83
79
|
"types": "./avatar/index.d.ts",
|
|
84
80
|
"default": "./fesm2022/ng-primitives-avatar.mjs"
|
|
85
81
|
},
|
|
82
|
+
"./button": {
|
|
83
|
+
"types": "./button/index.d.ts",
|
|
84
|
+
"default": "./fesm2022/ng-primitives-button.mjs"
|
|
85
|
+
},
|
|
86
86
|
"./checkbox": {
|
|
87
87
|
"types": "./checkbox/index.d.ts",
|
|
88
88
|
"default": "./fesm2022/ng-primitives-checkbox.mjs"
|
|
@@ -155,6 +155,10 @@
|
|
|
155
155
|
"types": "./popover/index.d.ts",
|
|
156
156
|
"default": "./fesm2022/ng-primitives-popover.mjs"
|
|
157
157
|
},
|
|
158
|
+
"./portal": {
|
|
159
|
+
"types": "./portal/index.d.ts",
|
|
160
|
+
"default": "./fesm2022/ng-primitives-portal.mjs"
|
|
161
|
+
},
|
|
158
162
|
"./progress": {
|
|
159
163
|
"types": "./progress/index.d.ts",
|
|
160
164
|
"default": "./fesm2022/ng-primitives-progress.mjs"
|
|
@@ -163,10 +167,6 @@
|
|
|
163
167
|
"types": "./radio/index.d.ts",
|
|
164
168
|
"default": "./fesm2022/ng-primitives-radio.mjs"
|
|
165
169
|
},
|
|
166
|
-
"./portal": {
|
|
167
|
-
"types": "./portal/index.d.ts",
|
|
168
|
-
"default": "./fesm2022/ng-primitives-portal.mjs"
|
|
169
|
-
},
|
|
170
170
|
"./resize": {
|
|
171
171
|
"types": "./resize/index.d.ts",
|
|
172
172
|
"default": "./fesm2022/ng-primitives-resize.mjs"
|
|
@@ -207,14 +207,18 @@
|
|
|
207
207
|
"types": "./textarea/index.d.ts",
|
|
208
208
|
"default": "./fesm2022/ng-primitives-textarea.mjs"
|
|
209
209
|
},
|
|
210
|
-
"./toggle-group": {
|
|
211
|
-
"types": "./toggle-group/index.d.ts",
|
|
212
|
-
"default": "./fesm2022/ng-primitives-toggle-group.mjs"
|
|
213
|
-
},
|
|
214
210
|
"./toast": {
|
|
215
211
|
"types": "./toast/index.d.ts",
|
|
216
212
|
"default": "./fesm2022/ng-primitives-toast.mjs"
|
|
217
213
|
},
|
|
214
|
+
"./toggle": {
|
|
215
|
+
"types": "./toggle/index.d.ts",
|
|
216
|
+
"default": "./fesm2022/ng-primitives-toggle.mjs"
|
|
217
|
+
},
|
|
218
|
+
"./toggle-group": {
|
|
219
|
+
"types": "./toggle-group/index.d.ts",
|
|
220
|
+
"default": "./fesm2022/ng-primitives-toggle-group.mjs"
|
|
221
|
+
},
|
|
218
222
|
"./toolbar": {
|
|
219
223
|
"types": "./toolbar/index.d.ts",
|
|
220
224
|
"default": "./fesm2022/ng-primitives-toolbar.mjs"
|
|
@@ -226,10 +230,6 @@
|
|
|
226
230
|
"./utils": {
|
|
227
231
|
"types": "./utils/index.d.ts",
|
|
228
232
|
"default": "./fesm2022/ng-primitives-utils.mjs"
|
|
229
|
-
},
|
|
230
|
-
"./toggle": {
|
|
231
|
-
"types": "./toggle/index.d.ts",
|
|
232
|
-
"default": "./fesm2022/ng-primitives-toggle.mjs"
|
|
233
233
|
}
|
|
234
234
|
},
|
|
235
235
|
"module": "fesm2022/ng-primitives.mjs",
|
|
@@ -17,7 +17,11 @@ export type ButtonVariant = 'primary' | 'secondary' | 'destructive' | 'outline'
|
|
|
17
17
|
@Component({
|
|
18
18
|
selector: 'button[app-button]',
|
|
19
19
|
hostDirectives: [{ directive: NgpButton, inputs: ['disabled'] }],
|
|
20
|
-
template:
|
|
20
|
+
template: \`
|
|
21
|
+
<ng-content select="[slot=leading]" />
|
|
22
|
+
<ng-content />
|
|
23
|
+
<ng-content select="[slot=trailing]" />
|
|
24
|
+
\`,
|
|
21
25
|
host: {
|
|
22
26
|
'[attr.data-size]': 'size()',
|
|
23
27
|
'[attr.data-variant]': 'variant()',
|
|
@@ -41,8 +45,56 @@ export type ButtonVariant = 'primary' | 'secondary' | 'destructive' | 'outline'
|
|
|
41
45
|
align-items: center;
|
|
42
46
|
justify-content: center;
|
|
43
47
|
cursor: pointer;
|
|
48
|
+
gap: 0.5rem;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
:host[data-hover] {
|
|
52
|
+
background-color: var(--ngp-background-hover);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
:host[data-focus-visible] {
|
|
56
|
+
outline: 2px solid var(--ngp-focus-ring);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:host[data-press] {
|
|
60
|
+
background-color: var(--ngp-background-active);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Size variants */
|
|
64
|
+
:host[data-size='sm'] {
|
|
65
|
+
height: 2rem;
|
|
66
|
+
padding-left: 0.75rem;
|
|
67
|
+
padding-right: 0.75rem;
|
|
68
|
+
font-size: 0.875rem;
|
|
69
|
+
--ng-icon__size: 0.875rem;
|
|
44
70
|
}
|
|
45
71
|
|
|
72
|
+
:host[data-size='md'],
|
|
73
|
+
:host:not([data-size]) {
|
|
74
|
+
height: 2.5rem;
|
|
75
|
+
padding-left: 1rem;
|
|
76
|
+
padding-right: 1rem;
|
|
77
|
+
font-size: 0.875rem;
|
|
78
|
+
--ng-icon__size: 0.875rem;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:host[data-size='lg'] {
|
|
82
|
+
height: 3rem;
|
|
83
|
+
padding-left: 1.25rem;
|
|
84
|
+
padding-right: 1.25rem;
|
|
85
|
+
font-size: 1rem;
|
|
86
|
+
--ng-icon__size: 1rem;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
:host[data-size='xl'] {
|
|
90
|
+
height: 3.5rem;
|
|
91
|
+
padding-left: 1.5rem;
|
|
92
|
+
padding-right: 1.5rem;
|
|
93
|
+
font-size: 1.125rem;
|
|
94
|
+
--ng-icon__size: 1.125rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Variant styles */
|
|
46
98
|
:host[data-variant='primary'],
|
|
47
99
|
:host:not([data-variant]) {
|
|
48
100
|
background-color: var(--ngp-background);
|
|
@@ -116,58 +168,25 @@ export type ButtonVariant = 'primary' | 'secondary' | 'destructive' | 'outline'
|
|
|
116
168
|
}
|
|
117
169
|
|
|
118
170
|
:host[data-variant='ghost'][data-press] {
|
|
119
|
-
background-color: var(--ngp-
|
|
171
|
+
background-color: var(--ngp-background-active);
|
|
120
172
|
}
|
|
121
173
|
|
|
122
174
|
:host[data-variant='link'] {
|
|
123
175
|
background-color: transparent;
|
|
124
|
-
color: var(--ngp-
|
|
176
|
+
color: var(--ngp-link-color, #3b82f6);
|
|
125
177
|
border: none;
|
|
126
178
|
box-shadow: none;
|
|
127
|
-
text-decoration
|
|
128
|
-
|
|
129
|
-
padding: 0;
|
|
179
|
+
text-decoration: underline;
|
|
180
|
+
text-underline-offset: 4px;
|
|
130
181
|
}
|
|
131
182
|
|
|
132
183
|
:host[data-variant='link'][data-hover] {
|
|
133
|
-
text-decoration-
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
:host[data-variant='link'][data-press] {
|
|
137
|
-
text-decoration-line: underline;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
:host[data-focus-visible] {
|
|
141
|
-
outline: 2px solid var(--ngp-focus-ring);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
:host[data-size='sm'] {
|
|
145
|
-
height: 2rem;
|
|
146
|
-
padding-left: 0.75rem;
|
|
147
|
-
padding-right: 0.75rem;
|
|
148
|
-
font-size: 0.875rem;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
:host[data-size='md'],
|
|
152
|
-
:host:not([data-size]) {
|
|
153
|
-
height: 2.5rem;
|
|
154
|
-
padding-left: 1rem;
|
|
155
|
-
padding-right: 1rem;
|
|
156
|
-
font-size: 0.875rem;
|
|
184
|
+
text-decoration-thickness: 2px;
|
|
157
185
|
}
|
|
158
186
|
|
|
159
|
-
:host[
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
padding-right: 1.25rem;
|
|
163
|
-
font-size: 1rem;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
:host[data-size='xl'] {
|
|
167
|
-
height: 3.5rem;
|
|
168
|
-
padding-left: 1.5rem;
|
|
169
|
-
padding-right: 1.5rem;
|
|
170
|
-
font-size: 1.125rem;
|
|
187
|
+
:host[disabled] {
|
|
188
|
+
opacity: 0.5;
|
|
189
|
+
cursor: not-allowed;
|
|
171
190
|
}
|
|
172
191
|
\`,
|
|
173
192
|
})
|
|
@@ -14,7 +14,11 @@ export type ButtonVariant = 'primary' | 'secondary' | 'destructive' | 'outline'
|
|
|
14
14
|
@Component({
|
|
15
15
|
selector: 'button[<%= prefix %>-button]',
|
|
16
16
|
hostDirectives: [{ directive: NgpButton, inputs: ['disabled'] }],
|
|
17
|
-
template:
|
|
17
|
+
template: `
|
|
18
|
+
<ng-content select="[slot=leading]" />
|
|
19
|
+
<ng-content />
|
|
20
|
+
<ng-content select="[slot=trailing]" />
|
|
21
|
+
`,
|
|
18
22
|
host: {
|
|
19
23
|
'[attr.data-size]': 'size()',
|
|
20
24
|
'[attr.data-variant]': 'variant()',
|
|
@@ -38,8 +42,56 @@ export type ButtonVariant = 'primary' | 'secondary' | 'destructive' | 'outline'
|
|
|
38
42
|
align-items: center;
|
|
39
43
|
justify-content: center;
|
|
40
44
|
cursor: pointer;
|
|
45
|
+
gap: 0.5rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:host[data-hover] {
|
|
49
|
+
background-color: var(--ngp-background-hover);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:host[data-focus-visible] {
|
|
53
|
+
outline: 2px solid var(--ngp-focus-ring);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:host[data-press] {
|
|
57
|
+
background-color: var(--ngp-background-active);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Size variants */
|
|
61
|
+
:host[data-size='sm'] {
|
|
62
|
+
height: 2rem;
|
|
63
|
+
padding-left: 0.75rem;
|
|
64
|
+
padding-right: 0.75rem;
|
|
65
|
+
font-size: 0.875rem;
|
|
66
|
+
--ng-icon__size: 0.875rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
:host[data-size='md'],
|
|
70
|
+
:host:not([data-size]) {
|
|
71
|
+
height: 2.5rem;
|
|
72
|
+
padding-left: 1rem;
|
|
73
|
+
padding-right: 1rem;
|
|
74
|
+
font-size: 0.875rem;
|
|
75
|
+
--ng-icon__size: 0.875rem;
|
|
41
76
|
}
|
|
42
77
|
|
|
78
|
+
:host[data-size='lg'] {
|
|
79
|
+
height: 3rem;
|
|
80
|
+
padding-left: 1.25rem;
|
|
81
|
+
padding-right: 1.25rem;
|
|
82
|
+
font-size: 1rem;
|
|
83
|
+
--ng-icon__size: 1rem;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
:host[data-size='xl'] {
|
|
87
|
+
height: 3.5rem;
|
|
88
|
+
padding-left: 1.5rem;
|
|
89
|
+
padding-right: 1.5rem;
|
|
90
|
+
font-size: 1.125rem;
|
|
91
|
+
--ng-icon__size: 1.125rem;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Variant styles */
|
|
43
95
|
:host[data-variant='primary'],
|
|
44
96
|
:host:not([data-variant]) {
|
|
45
97
|
background-color: var(--ngp-background);
|
|
@@ -113,58 +165,25 @@ export type ButtonVariant = 'primary' | 'secondary' | 'destructive' | 'outline'
|
|
|
113
165
|
}
|
|
114
166
|
|
|
115
167
|
:host[data-variant='ghost'][data-press] {
|
|
116
|
-
background-color: var(--ngp-
|
|
168
|
+
background-color: var(--ngp-background-active);
|
|
117
169
|
}
|
|
118
170
|
|
|
119
171
|
:host[data-variant='link'] {
|
|
120
172
|
background-color: transparent;
|
|
121
|
-
color: var(--ngp-
|
|
173
|
+
color: var(--ngp-link-color, #3b82f6);
|
|
122
174
|
border: none;
|
|
123
175
|
box-shadow: none;
|
|
124
|
-
text-decoration
|
|
125
|
-
|
|
126
|
-
padding: 0;
|
|
176
|
+
text-decoration: underline;
|
|
177
|
+
text-underline-offset: 4px;
|
|
127
178
|
}
|
|
128
179
|
|
|
129
180
|
:host[data-variant='link'][data-hover] {
|
|
130
|
-
text-decoration-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
:host[data-variant='link'][data-press] {
|
|
134
|
-
text-decoration-line: underline;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
:host[data-focus-visible] {
|
|
138
|
-
outline: 2px solid var(--ngp-focus-ring);
|
|
181
|
+
text-decoration-thickness: 2px;
|
|
139
182
|
}
|
|
140
183
|
|
|
141
|
-
:host[
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
padding-right: 0.75rem;
|
|
145
|
-
font-size: 0.875rem;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
:host[data-size='md'],
|
|
149
|
-
:host:not([data-size]) {
|
|
150
|
-
height: 2.5rem;
|
|
151
|
-
padding-left: 1rem;
|
|
152
|
-
padding-right: 1rem;
|
|
153
|
-
font-size: 0.875rem;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
:host[data-size='lg'] {
|
|
157
|
-
height: 3rem;
|
|
158
|
-
padding-left: 1.25rem;
|
|
159
|
-
padding-right: 1.25rem;
|
|
160
|
-
font-size: 1rem;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
:host[data-size='xl'] {
|
|
164
|
-
height: 3.5rem;
|
|
165
|
-
padding-left: 1.5rem;
|
|
166
|
-
padding-right: 1.5rem;
|
|
167
|
-
font-size: 1.125rem;
|
|
184
|
+
:host[disabled] {
|
|
185
|
+
opacity: 0.5;
|
|
186
|
+
cursor: not-allowed;
|
|
168
187
|
}
|
|
169
188
|
`,
|
|
170
189
|
})
|