@radix-ng/primitives 0.40.0 → 0.41.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.
@@ -0,0 +1 @@
1
+ # @radix-ng/primitives/dismissible-layer
@@ -0,0 +1 @@
1
+ export * from './src/utils';
@@ -0,0 +1,38 @@
1
+ import { BooleanInput } from '@angular/cdk/coercion';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Listens for when focus happens outside a DOM subtree.
5
+ * Returns props to pass to the root (node) of the subtree we want to check.
6
+ */
7
+ export declare class RdxFocusOutside {
8
+ #private;
9
+ readonly enabledInput: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
10
+ set enabled(value: boolean);
11
+ get enabled(): boolean;
12
+ readonly focusOutside: import("@angular/core").OutputEmitterRef<FocusEvent>;
13
+ private readonly isFocusInsideDOMTree;
14
+ private readonly focusCaptureHandler;
15
+ private readonly blurCaptureHandler;
16
+ constructor();
17
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdxFocusOutside, never>;
18
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RdxFocusOutside, "[rdxFocusOutside]", ["rdxFocusOutside"], { "enabledInput": { "alias": "enabled"; "required": false; "isSignal": true; }; }, { "focusOutside": "focusOutside"; }, never, never, true, never>;
19
+ }
20
+ /**
21
+ * Listens for `pointerdown` outside a DOM subtree. We use `pointerdown` rather than `pointerup`
22
+ * to mimic layer dismissing behavior present in OS.
23
+ * Returns props to pass to the node we want to check for outside events.
24
+ */
25
+ export declare class RdxPointerDownOutside {
26
+ #private;
27
+ private readonly elementRef;
28
+ readonly enabledInput: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
29
+ set enabled(value: boolean);
30
+ get enabled(): boolean;
31
+ readonly pointerDownOutside: import("@angular/core").OutputEmitterRef<PointerEvent>;
32
+ private readonly isPointerInsideDOMTree;
33
+ private readonly handleAndDispatchPointerDownOutsideEvent;
34
+ private handleClick;
35
+ constructor();
36
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdxPointerDownOutside, never>;
37
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RdxPointerDownOutside, "[rdxPointerDownOutside]", ["rdxPointerDownOutside"], { "enabledInput": { "alias": "enabled"; "required": false; "isSignal": true; }; }, { "pointerDownOutside": "pointerDownOutside"; }, never, never, true, never>;
38
+ }
@@ -0,0 +1 @@
1
+ # @radix-ng/primitives/editable
@@ -0,0 +1 @@
1
+ export * from './src/editable-root';
@@ -0,0 +1,67 @@
1
+ import { BooleanInput, NumberInput } from '@angular/cdk/coercion';
2
+ import { Signal, WritableSignal } from '@angular/core';
3
+ import { RdxPointerDownOutside } from '@radix-ng/primitives/dismissible-layer';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@radix-ng/primitives/dismissible-layer";
6
+ type EditableRootContext = {
7
+ disabled: Signal<boolean>;
8
+ value: Signal<string | null | undefined>;
9
+ inputValue: WritableSignal<string | undefined>;
10
+ placeholder: Signal<{
11
+ edit: string;
12
+ preview: string;
13
+ }>;
14
+ isEditing: Signal<boolean>;
15
+ submitMode: Signal<SubmitMode>;
16
+ activationMode: Signal<ActivationMode>;
17
+ edit: () => void;
18
+ cancel: () => void;
19
+ submit: () => void;
20
+ maxLength: Signal<number | undefined>;
21
+ startWithEditMode: Signal<boolean>;
22
+ isEmpty: Signal<boolean>;
23
+ readonly: Signal<boolean>;
24
+ selectOnFocus: Signal<boolean>;
25
+ autoResize: Signal<boolean>;
26
+ inputRef: WritableSignal<HTMLInputElement | undefined>;
27
+ };
28
+ export declare const injectEditableRootContext: (optional?: boolean) => EditableRootContext | null, provideEditableRootContext: (useFactory: () => EditableRootContext) => import("@angular/core").Provider;
29
+ type ActivationMode = 'focus' | 'dblclick' | 'none';
30
+ type SubmitMode = 'blur' | 'enter' | 'none' | 'both';
31
+ /**
32
+ * @group Components
33
+ */
34
+ export declare class RdxEditableRoot {
35
+ private readonly focusOutside;
36
+ readonly pointerDownOutside: RdxPointerDownOutside;
37
+ readonly value: import("@angular/core").ModelSignal<string | undefined>;
38
+ readonly placeholder: import("@angular/core").InputSignal<string>;
39
+ readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
40
+ readonly readonly: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
41
+ readonly selectOnFocus: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
42
+ readonly submitMode: import("@angular/core").InputSignal<SubmitMode>;
43
+ readonly maxLength: import("@angular/core").InputSignalWithTransform<number | undefined, NumberInput>;
44
+ /**
45
+ * Whether to start with the edit mode active
46
+ */
47
+ readonly startWithEditMode: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
48
+ readonly activationMode: import("@angular/core").InputSignal<ActivationMode>;
49
+ readonly autoResize: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
50
+ readonly required: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
51
+ readonly isEmpty: Signal<boolean>;
52
+ readonly $placeholder: Signal<string | {
53
+ edit: string;
54
+ preview: string;
55
+ }>;
56
+ readonly isEditing: WritableSignal<boolean>;
57
+ readonly inputValue: WritableSignal<string | undefined>;
58
+ readonly inputRef: WritableSignal<HTMLInputElement | undefined>;
59
+ constructor();
60
+ handleDismiss(): void;
61
+ submit(): void;
62
+ cancel(): void;
63
+ edit(): void;
64
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdxEditableRoot, never>;
65
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RdxEditableRoot, "[rdxEditableRoot]", ["rdxEditableRoot"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "selectOnFocus": { "alias": "selectOnFocus"; "required": false; "isSignal": true; }; "submitMode": { "alias": "submitMode"; "required": false; "isSignal": true; }; "maxLength": { "alias": "maxLength"; "required": false; "isSignal": true; }; "startWithEditMode": { "alias": "startWithEditMode"; "required": false; "isSignal": true; }; "activationMode": { "alias": "activationMode"; "required": false; "isSignal": true; }; "autoResize": { "alias": "autoResize"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, [{ directive: typeof i1.RdxFocusOutside; inputs: {}; outputs: {}; }, { directive: typeof i1.RdxPointerDownOutside; inputs: {}; outputs: {}; }]>;
66
+ }
67
+ export {};
@@ -0,0 +1,211 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, booleanAttribute, linkedSignal, output, signal, inject, ElementRef, effect, Directive } from '@angular/core';
3
+
4
+ function isLayerExist(layerElement, targetElement) {
5
+ const targetLayer = targetElement.closest('[data-dismissable-layer]');
6
+ const mainLayer = layerElement.dataset['dismissableLayer'] === ''
7
+ ? layerElement
8
+ : layerElement.querySelector('[data-dismissable-layer]');
9
+ const nodeList = Array.from(layerElement.ownerDocument.querySelectorAll('[data-dismissable-layer]'));
10
+ if (targetLayer && (mainLayer === targetLayer || nodeList.indexOf(mainLayer) < nodeList.indexOf(targetLayer))) {
11
+ return true;
12
+ }
13
+ else {
14
+ return false;
15
+ }
16
+ }
17
+ /**
18
+ * Listens for when focus happens outside a DOM subtree.
19
+ * Returns props to pass to the root (node) of the subtree we want to check.
20
+ */
21
+ class RdxFocusOutside {
22
+ #enabled;
23
+ set enabled(value) {
24
+ if (this.#enabled() !== value) {
25
+ this.#enabled.set(value);
26
+ }
27
+ }
28
+ get enabled() {
29
+ return this.#enabled();
30
+ }
31
+ constructor() {
32
+ this.enabledInput = input(true, { transform: booleanAttribute, alias: 'enabled' });
33
+ this.#enabled = linkedSignal(() => this.enabledInput());
34
+ this.focusOutside = output();
35
+ /*
36
+ * Flag to indicate if the focus is currently within the DOM subtree
37
+ */
38
+ this.isFocusInsideDOMTree = signal(false);
39
+ /*
40
+ * Handles capturing the focus event to mark focus as inside the DOM subtree
41
+ */
42
+ this.focusCaptureHandler = () => {
43
+ if (!this.enabled)
44
+ return;
45
+ this.isFocusInsideDOMTree.set(true);
46
+ };
47
+ /*
48
+ * Handles capturing the blur event to mark focus as outside the DOM subtree
49
+ */
50
+ this.blurCaptureHandler = () => {
51
+ if (!this.enabled)
52
+ return;
53
+ this.isFocusInsideDOMTree.set(false);
54
+ };
55
+ const elementRef = inject(ElementRef);
56
+ effect((onCleanup) => {
57
+ if (!this.#enabled()) {
58
+ return;
59
+ }
60
+ const ownerDocument = elementRef.nativeElement.ownerDocument ?? globalThis.document;
61
+ const focusHandler = async (event) => {
62
+ if (!elementRef?.nativeElement) {
63
+ return;
64
+ }
65
+ await Promise.resolve();
66
+ await Promise.resolve();
67
+ const target = event.target;
68
+ if (!elementRef.nativeElement || !target || isLayerExist(elementRef.nativeElement, target)) {
69
+ return;
70
+ }
71
+ if (target && !this.isFocusInsideDOMTree()) {
72
+ this.focusOutside.emit(event);
73
+ }
74
+ };
75
+ elementRef.nativeElement.addEventListener('focus', this.focusCaptureHandler, {
76
+ capture: true
77
+ });
78
+ elementRef.nativeElement.addEventListener('blur', this.blurCaptureHandler, {
79
+ capture: true
80
+ });
81
+ ownerDocument.addEventListener('focusin', focusHandler);
82
+ onCleanup(() => {
83
+ elementRef.nativeElement.removeEventListener('focus', this.focusCaptureHandler, {
84
+ capture: true
85
+ });
86
+ elementRef.nativeElement.removeEventListener('blur', this.blurCaptureHandler, {
87
+ capture: true
88
+ });
89
+ ownerDocument.removeEventListener('focusin', focusHandler);
90
+ });
91
+ });
92
+ }
93
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxFocusOutside, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
94
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.4", type: RdxFocusOutside, isStandalone: true, selector: "[rdxFocusOutside]", inputs: { enabledInput: { classPropertyName: "enabledInput", publicName: "enabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { focusOutside: "focusOutside" }, exportAs: ["rdxFocusOutside"], ngImport: i0 }); }
95
+ }
96
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxFocusOutside, decorators: [{
97
+ type: Directive,
98
+ args: [{
99
+ selector: '[rdxFocusOutside]',
100
+ exportAs: 'rdxFocusOutside'
101
+ }]
102
+ }], ctorParameters: () => [] });
103
+ /**
104
+ * Listens for `pointerdown` outside a DOM subtree. We use `pointerdown` rather than `pointerup`
105
+ * to mimic layer dismissing behavior present in OS.
106
+ * Returns props to pass to the node we want to check for outside events.
107
+ */
108
+ class RdxPointerDownOutside {
109
+ #enabled;
110
+ set enabled(value) {
111
+ if (this.#enabled() !== value) {
112
+ this.#enabled.set(value);
113
+ }
114
+ }
115
+ get enabled() {
116
+ return this.#enabled();
117
+ }
118
+ constructor() {
119
+ this.elementRef = inject(ElementRef);
120
+ this.enabledInput = input(true, { transform: booleanAttribute, alias: 'enabled' });
121
+ this.#enabled = linkedSignal(() => this.enabledInput());
122
+ this.pointerDownOutside = output();
123
+ this.isPointerInsideDOMTree = signal(false);
124
+ this.handleAndDispatchPointerDownOutsideEvent = (e) => () => this.pointerDownOutside.emit(e);
125
+ effect((onCleanup) => {
126
+ if (!this.#enabled()) {
127
+ return;
128
+ }
129
+ const ownerDocument = this.elementRef.nativeElement.ownerDocument ?? globalThis.document;
130
+ const handlePointerDown = async (event) => {
131
+ if (event.target && !this.isPointerInsideDOMTree()) {
132
+ /**
133
+ * On touch devices, we need to wait for a click event because browsers implement
134
+ * a ~350ms delay between the time the user stops touching the display and when the
135
+ * browser executres events. We need to ensure we don't reactivate pointer-events within
136
+ * this timeframe otherwise the browser may execute events that should have been prevented.
137
+ *
138
+ * Additionally, this also lets us deal automatically with cancellations when a click event
139
+ * isn't raised because the page was considered scrolled/drag-scrolled, long-pressed, etc.
140
+ *
141
+ * This is why we also continuously remove the previous listener, because we cannot be
142
+ * certain that it was raised, and therefore cleaned-up.
143
+ */
144
+ if (event.pointerType === 'touch') {
145
+ ownerDocument.removeEventListener('click', this.handleClick);
146
+ this.handleClick = this.handleAndDispatchPointerDownOutsideEvent(event);
147
+ ownerDocument.addEventListener('click', this.handleClick, {
148
+ once: true
149
+ });
150
+ }
151
+ else {
152
+ this.pointerDownOutside.emit(event);
153
+ }
154
+ }
155
+ else {
156
+ // We need to remove the event listener in case the outside click has been canceled.
157
+ // See: https://github.com/radix-ui/primitives/issues/2171
158
+ ownerDocument.removeEventListener('click', this.handleClick);
159
+ }
160
+ this.isPointerInsideDOMTree.set(false);
161
+ };
162
+ /**
163
+ * if this directive executes in a component that mounts via a `pointerdown` event, the event
164
+ * would bubble up to the document and trigger a `pointerDownOutside` event. We avoid
165
+ * this by delaying the event listener registration on the document.
166
+ * This is not Angular specific, but rather how the DOM works, ie:
167
+ * ```
168
+ * button.addEventListener('pointerdown', () => {
169
+ * console.log('I will log');
170
+ * document.addEventListener('pointerdown', () => {
171
+ * console.log('I will also log');
172
+ * })
173
+ * });
174
+ */
175
+ const timerId = window.setTimeout(() => {
176
+ ownerDocument.addEventListener('pointerdown', handlePointerDown);
177
+ }, 0);
178
+ const onPointerDownCapture = () => {
179
+ if (!this.enabled) {
180
+ return;
181
+ }
182
+ this.isPointerInsideDOMTree.set(true);
183
+ };
184
+ this.elementRef.nativeElement.addEventListener('pointerdown', onPointerDownCapture, { capture: true });
185
+ onCleanup(() => {
186
+ window.clearTimeout(timerId);
187
+ ownerDocument.removeEventListener('pointerdown', handlePointerDown);
188
+ ownerDocument.removeEventListener('click', this.handleClick);
189
+ this.elementRef.nativeElement.removeEventListener('pointerdown', onPointerDownCapture, {
190
+ capture: true
191
+ });
192
+ });
193
+ });
194
+ }
195
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxPointerDownOutside, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
196
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.4", type: RdxPointerDownOutside, isStandalone: true, selector: "[rdxPointerDownOutside]", inputs: { enabledInput: { classPropertyName: "enabledInput", publicName: "enabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pointerDownOutside: "pointerDownOutside" }, exportAs: ["rdxPointerDownOutside"], ngImport: i0 }); }
197
+ }
198
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxPointerDownOutside, decorators: [{
199
+ type: Directive,
200
+ args: [{
201
+ selector: '[rdxPointerDownOutside]',
202
+ exportAs: 'rdxPointerDownOutside'
203
+ }]
204
+ }], ctorParameters: () => [] });
205
+
206
+ /**
207
+ * Generated bundle index. Do not edit.
208
+ */
209
+
210
+ export { RdxFocusOutside, RdxPointerDownOutside };
211
+ //# sourceMappingURL=radix-ng-primitives-dismissible-layer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radix-ng-primitives-dismissible-layer.mjs","sources":["../../../packages/primitives/dismissible-layer/src/utils.ts","../../../packages/primitives/dismissible-layer/radix-ng-primitives-dismissible-layer.ts"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n linkedSignal,\n output,\n signal\n} from '@angular/core';\n\nfunction isLayerExist(layerElement: HTMLElement, targetElement: HTMLElement) {\n const targetLayer = targetElement.closest('[data-dismissable-layer]');\n\n const mainLayer =\n layerElement.dataset['dismissableLayer'] === ''\n ? layerElement\n : (layerElement.querySelector('[data-dismissable-layer]') as HTMLElement);\n\n const nodeList = Array.from(layerElement.ownerDocument.querySelectorAll('[data-dismissable-layer]'));\n\n if (targetLayer && (mainLayer === targetLayer || nodeList.indexOf(mainLayer) < nodeList.indexOf(targetLayer))) {\n return true;\n } else {\n return false;\n }\n}\n\n/**\n * Listens for when focus happens outside a DOM subtree.\n * Returns props to pass to the root (node) of the subtree we want to check.\n */\n@Directive({\n selector: '[rdxFocusOutside]',\n exportAs: 'rdxFocusOutside'\n})\nexport class RdxFocusOutside {\n readonly enabledInput = input<boolean, BooleanInput>(true, { transform: booleanAttribute, alias: 'enabled' });\n\n readonly #enabled = linkedSignal(() => this.enabledInput());\n\n set enabled(value: boolean) {\n if (this.#enabled() !== value) {\n this.#enabled.set(value);\n }\n }\n\n get enabled() {\n return this.#enabled();\n }\n\n readonly focusOutside = output<FocusEvent>();\n\n /*\n * Flag to indicate if the focus is currently within the DOM subtree\n */\n private readonly isFocusInsideDOMTree = signal(false);\n\n /*\n * Handles capturing the focus event to mark focus as inside the DOM subtree\n */\n private readonly focusCaptureHandler = () => {\n if (!this.enabled) return;\n this.isFocusInsideDOMTree.set(true);\n };\n\n /*\n * Handles capturing the blur event to mark focus as outside the DOM subtree\n */\n private readonly blurCaptureHandler = () => {\n if (!this.enabled) return;\n this.isFocusInsideDOMTree.set(false);\n };\n\n constructor() {\n const elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n\n effect((onCleanup) => {\n if (!this.#enabled()) {\n return;\n }\n\n const ownerDocument = elementRef.nativeElement.ownerDocument ?? globalThis.document;\n\n const focusHandler = async (event: FocusEvent) => {\n if (!elementRef?.nativeElement) {\n return;\n }\n\n await Promise.resolve();\n await Promise.resolve();\n\n const target = event.target as HTMLElement | undefined;\n if (!elementRef.nativeElement || !target || isLayerExist(elementRef.nativeElement, target)) {\n return;\n }\n\n if (target && !this.isFocusInsideDOMTree()) {\n this.focusOutside.emit(event);\n }\n };\n\n elementRef.nativeElement.addEventListener('focus', this.focusCaptureHandler, {\n capture: true\n });\n elementRef.nativeElement.addEventListener('blur', this.blurCaptureHandler, {\n capture: true\n });\n\n ownerDocument.addEventListener('focusin', focusHandler);\n\n onCleanup(() => {\n elementRef.nativeElement.removeEventListener('focus', this.focusCaptureHandler, {\n capture: true\n });\n\n elementRef.nativeElement.removeEventListener('blur', this.blurCaptureHandler, {\n capture: true\n });\n\n ownerDocument.removeEventListener('focusin', focusHandler);\n });\n });\n }\n}\n\n/**\n * Listens for `pointerdown` outside a DOM subtree. We use `pointerdown` rather than `pointerup`\n * to mimic layer dismissing behavior present in OS.\n * Returns props to pass to the node we want to check for outside events.\n */\n@Directive({\n selector: '[rdxPointerDownOutside]',\n exportAs: 'rdxPointerDownOutside'\n})\nexport class RdxPointerDownOutside {\n private readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);\n\n readonly enabledInput = input<boolean, BooleanInput>(true, { transform: booleanAttribute, alias: 'enabled' });\n\n readonly #enabled = linkedSignal(() => this.enabledInput());\n\n set enabled(value: boolean) {\n if (this.#enabled() !== value) {\n this.#enabled.set(value);\n }\n }\n\n get enabled() {\n return this.#enabled();\n }\n\n readonly pointerDownOutside = output<PointerEvent>();\n\n private readonly isPointerInsideDOMTree = signal(false);\n\n private readonly handleAndDispatchPointerDownOutsideEvent = (e: PointerEvent) => () =>\n this.pointerDownOutside.emit(e);\n\n private handleClick: () => void | undefined;\n\n constructor() {\n effect((onCleanup) => {\n if (!this.#enabled()) {\n return;\n }\n\n const ownerDocument = this.elementRef.nativeElement.ownerDocument ?? globalThis.document;\n\n const handlePointerDown = async (event: PointerEvent) => {\n if (event.target && !this.isPointerInsideDOMTree()) {\n /**\n * On touch devices, we need to wait for a click event because browsers implement\n * a ~350ms delay between the time the user stops touching the display and when the\n * browser executres events. We need to ensure we don't reactivate pointer-events within\n * this timeframe otherwise the browser may execute events that should have been prevented.\n *\n * Additionally, this also lets us deal automatically with cancellations when a click event\n * isn't raised because the page was considered scrolled/drag-scrolled, long-pressed, etc.\n *\n * This is why we also continuously remove the previous listener, because we cannot be\n * certain that it was raised, and therefore cleaned-up.\n */\n if (event.pointerType === 'touch') {\n ownerDocument.removeEventListener('click', this.handleClick);\n this.handleClick = this.handleAndDispatchPointerDownOutsideEvent(event);\n ownerDocument.addEventListener('click', this.handleClick, {\n once: true\n });\n } else {\n this.pointerDownOutside.emit(event);\n }\n } else {\n // We need to remove the event listener in case the outside click has been canceled.\n // See: https://github.com/radix-ui/primitives/issues/2171\n ownerDocument.removeEventListener('click', this.handleClick);\n }\n this.isPointerInsideDOMTree.set(false);\n };\n /**\n * if this directive executes in a component that mounts via a `pointerdown` event, the event\n * would bubble up to the document and trigger a `pointerDownOutside` event. We avoid\n * this by delaying the event listener registration on the document.\n * This is not Angular specific, but rather how the DOM works, ie:\n * ```\n * button.addEventListener('pointerdown', () => {\n * console.log('I will log');\n * document.addEventListener('pointerdown', () => {\n * console.log('I will also log');\n * })\n * });\n */\n const timerId = window.setTimeout(() => {\n ownerDocument.addEventListener('pointerdown', handlePointerDown);\n }, 0);\n\n const onPointerDownCapture = () => {\n if (!this.enabled) {\n return;\n }\n this.isPointerInsideDOMTree.set(true);\n };\n\n this.elementRef.nativeElement.addEventListener('pointerdown', onPointerDownCapture, { capture: true });\n\n onCleanup(() => {\n window.clearTimeout(timerId);\n ownerDocument.removeEventListener('pointerdown', handlePointerDown);\n ownerDocument.removeEventListener('click', this.handleClick);\n this.elementRef.nativeElement.removeEventListener('pointerdown', onPointerDownCapture, {\n capture: true\n });\n });\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, model, input, booleanAttribute, numberAttribute, computed, signal, afterNextRender, Directive } from '@angular/core';
3
+ import { createContext, watch } from '@radix-ng/primitives/core';
4
+ import * as i1 from '@radix-ng/primitives/dismissible-layer';
5
+ import { RdxFocusOutside, RdxPointerDownOutside } from '@radix-ng/primitives/dismissible-layer';
6
+
7
+ const [injectEditableRootContext, provideEditableRootContext] = createContext('EditableRoot');
8
+ const rootContext = () => {
9
+ const context = inject(RdxEditableRoot);
10
+ return {
11
+ disabled: context.disabled,
12
+ value: context.value,
13
+ inputValue: context.inputValue,
14
+ placeholder: context.$placeholder,
15
+ isEditing: context.isEditing,
16
+ submitMode: context.submitMode,
17
+ activationMode: context.activationMode,
18
+ edit: context.edit,
19
+ cancel: context.cancel,
20
+ submit: context.submit,
21
+ maxLength: context.maxLength,
22
+ startWithEditMode: context.startWithEditMode,
23
+ isEmpty: context.isEmpty,
24
+ readonly: context.readonly,
25
+ autoResize: context.autoResize,
26
+ selectOnFocus: context.selectOnFocus,
27
+ inputRef: context.inputRef
28
+ };
29
+ };
30
+ /**
31
+ * @group Components
32
+ */
33
+ class RdxEditableRoot {
34
+ constructor() {
35
+ this.focusOutside = inject(RdxFocusOutside);
36
+ this.pointerDownOutside = inject(RdxPointerDownOutside);
37
+ this.value = model();
38
+ this.placeholder = input('Enter text...');
39
+ this.disabled = input(false, { transform: booleanAttribute });
40
+ this.readonly = input(false, { transform: booleanAttribute });
41
+ this.selectOnFocus = input(false, { transform: booleanAttribute });
42
+ this.submitMode = input('blur');
43
+ this.maxLength = input(undefined, { transform: numberAttribute });
44
+ /**
45
+ * Whether to start with the edit mode active
46
+ */
47
+ this.startWithEditMode = input(false, { transform: booleanAttribute });
48
+ this.activationMode = input('focus');
49
+ this.autoResize = input(false, { transform: booleanAttribute });
50
+ this.required = input(false, { transform: booleanAttribute });
51
+ this.isEmpty = computed(() => this.value() === '');
52
+ this.$placeholder = computed(() => {
53
+ return typeof this.placeholder() === 'string'
54
+ ? { edit: this.placeholder(), preview: this.placeholder() }
55
+ : this.placeholder();
56
+ });
57
+ this.isEditing = signal(false);
58
+ this.inputValue = signal(this.value());
59
+ this.inputRef = signal(undefined);
60
+ watch([this.value], ([value]) => {
61
+ if (value) {
62
+ this.inputValue.set(this.value());
63
+ }
64
+ });
65
+ watch([this.isEditing], ([value]) => {
66
+ this.pointerDownOutside.enabled = value;
67
+ this.focusOutside.enabled = value;
68
+ });
69
+ this.pointerDownOutside.pointerDownOutside.subscribe(() => this.handleDismiss());
70
+ this.focusOutside.focusOutside.subscribe(() => this.handleDismiss());
71
+ afterNextRender(() => {
72
+ this.isEditing.set(this.startWithEditMode() ?? false);
73
+ this.inputValue.set(this.value());
74
+ });
75
+ }
76
+ handleDismiss() {
77
+ if (this.isEditing()) {
78
+ if (this.submitMode() === 'blur' || this.submitMode() === 'both') {
79
+ this.submit();
80
+ }
81
+ else {
82
+ this.cancel();
83
+ }
84
+ }
85
+ }
86
+ submit() {
87
+ this.value.set(this.inputValue());
88
+ this.isEditing.set(false);
89
+ }
90
+ cancel() {
91
+ this.isEditing.set(false);
92
+ }
93
+ edit() {
94
+ this.isEditing.set(true);
95
+ this.inputValue.set(this.value());
96
+ }
97
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxEditableRoot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
98
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.4", type: RdxEditableRoot, isStandalone: true, selector: "[rdxEditableRoot]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, selectOnFocus: { classPropertyName: "selectOnFocus", publicName: "selectOnFocus", isSignal: true, isRequired: false, transformFunction: null }, submitMode: { classPropertyName: "submitMode", publicName: "submitMode", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, startWithEditMode: { classPropertyName: "startWithEditMode", publicName: "startWithEditMode", isSignal: true, isRequired: false, transformFunction: null }, activationMode: { classPropertyName: "activationMode", publicName: "activationMode", isSignal: true, isRequired: false, transformFunction: null }, autoResize: { classPropertyName: "autoResize", publicName: "autoResize", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "attr.data-dismissable-layer": "\"\"" } }, providers: [provideEditableRootContext(rootContext)], exportAs: ["rdxEditableRoot"], hostDirectives: [{ directive: i1.RdxFocusOutside }, { directive: i1.RdxPointerDownOutside }], ngImport: i0 }); }
99
+ }
100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: RdxEditableRoot, decorators: [{
101
+ type: Directive,
102
+ args: [{
103
+ selector: '[rdxEditableRoot]',
104
+ exportAs: 'rdxEditableRoot',
105
+ providers: [provideEditableRootContext(rootContext)],
106
+ hostDirectives: [RdxFocusOutside, RdxPointerDownOutside],
107
+ host: {
108
+ '[attr.data-dismissable-layer]': '""'
109
+ }
110
+ }]
111
+ }], ctorParameters: () => [] });
112
+
113
+ /**
114
+ * Generated bundle index. Do not edit.
115
+ */
116
+
117
+ export { RdxEditableRoot, injectEditableRootContext, provideEditableRootContext };
118
+ //# sourceMappingURL=radix-ng-primitives-editable.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radix-ng-primitives-editable.mjs","sources":["../../../packages/primitives/editable/src/editable-root.ts","../../../packages/primitives/editable/radix-ng-primitives-editable.ts"],"sourcesContent":["import { BooleanInput, NumberInput } from '@angular/cdk/coercion';\nimport {\n afterNextRender,\n booleanAttribute,\n computed,\n Directive,\n inject,\n input,\n model,\n numberAttribute,\n Signal,\n signal,\n WritableSignal\n} from '@angular/core';\nimport { createContext, watch } from '@radix-ng/primitives/core';\nimport { RdxFocusOutside, RdxPointerDownOutside } from '@radix-ng/primitives/dismissible-layer';\n\ntype EditableRootContext = {\n disabled: Signal<boolean>;\n value: Signal<string | null | undefined>;\n inputValue: WritableSignal<string | undefined>;\n placeholder: Signal<{ edit: string; preview: string }>;\n isEditing: Signal<boolean>;\n submitMode: Signal<SubmitMode>;\n activationMode: Signal<ActivationMode>;\n edit: () => void;\n cancel: () => void;\n submit: () => void;\n maxLength: Signal<number | undefined>;\n startWithEditMode: Signal<boolean>;\n isEmpty: Signal<boolean>;\n readonly: Signal<boolean>;\n selectOnFocus: Signal<boolean>;\n autoResize: Signal<boolean>;\n inputRef: WritableSignal<HTMLInputElement | undefined>;\n};\n\nexport const [injectEditableRootContext, provideEditableRootContext] =\n createContext<EditableRootContext>('EditableRoot');\n\nconst rootContext = (): EditableRootContext => {\n const context = inject(RdxEditableRoot);\n return {\n disabled: context.disabled,\n value: context.value,\n inputValue: context.inputValue,\n placeholder: context.$placeholder as Signal<{ edit: string; preview: string }>,\n isEditing: context.isEditing,\n submitMode: context.submitMode,\n activationMode: context.activationMode,\n edit: context.edit,\n cancel: context.cancel,\n submit: context.submit,\n maxLength: context.maxLength,\n startWithEditMode: context.startWithEditMode,\n isEmpty: context.isEmpty,\n readonly: context.readonly,\n autoResize: context.autoResize,\n selectOnFocus: context.selectOnFocus,\n inputRef: context.inputRef\n };\n};\n\ntype ActivationMode = 'focus' | 'dblclick' | 'none';\ntype SubmitMode = 'blur' | 'enter' | 'none' | 'both';\n\n/**\n * @group Components\n */\n@Directive({\n selector: '[rdxEditableRoot]',\n exportAs: 'rdxEditableRoot',\n providers: [provideEditableRootContext(rootContext)],\n hostDirectives: [RdxFocusOutside, RdxPointerDownOutside],\n host: {\n '[attr.data-dismissable-layer]': '\"\"'\n }\n})\nexport class RdxEditableRoot {\n private readonly focusOutside = inject(RdxFocusOutside);\n readonly pointerDownOutside = inject(RdxPointerDownOutside);\n\n readonly value = model<string>();\n\n readonly placeholder = input<string>('Enter text...');\n\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly readonly = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly selectOnFocus = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly submitMode = input<SubmitMode>('blur');\n\n readonly maxLength = input<number, NumberInput>(undefined, { transform: numberAttribute });\n\n /**\n * Whether to start with the edit mode active\n */\n readonly startWithEditMode = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly activationMode = input<ActivationMode>('focus');\n\n readonly autoResize = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly required = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly isEmpty = computed(() => this.value() === '');\n\n readonly $placeholder = computed(() => {\n return typeof this.placeholder() === 'string'\n ? { edit: this.placeholder(), preview: this.placeholder() }\n : this.placeholder();\n });\n\n readonly isEditing = signal(false);\n\n readonly inputValue = signal(this.value());\n\n readonly inputRef = signal<HTMLInputElement | undefined>(undefined);\n\n constructor() {\n watch([this.value], ([value]) => {\n if (value) {\n this.inputValue.set(this.value());\n }\n });\n\n watch([this.isEditing], ([value]) => {\n this.pointerDownOutside.enabled = value;\n this.focusOutside.enabled = value;\n });\n\n this.pointerDownOutside.pointerDownOutside.subscribe(() => this.handleDismiss());\n this.focusOutside.focusOutside.subscribe(() => this.handleDismiss());\n\n afterNextRender(() => {\n this.isEditing.set(this.startWithEditMode() ?? false);\n this.inputValue.set(this.value());\n });\n }\n\n handleDismiss() {\n if (this.isEditing()) {\n if (this.submitMode() === 'blur' || this.submitMode() === 'both') {\n this.submit();\n } else {\n this.cancel();\n }\n }\n }\n\n submit() {\n this.value.set(this.inputValue());\n this.isEditing.set(false);\n }\n\n cancel() {\n this.isEditing.set(false);\n }\n\n edit() {\n this.isEditing.set(true);\n this.inputValue.set(this.value());\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -93,7 +93,7 @@ export declare class RdxHoverCardRootDirective {
93
93
  window: Window & typeof globalThis;
94
94
  primitiveConfigs?: import("./utils/types").PrimitiveConfigs;
95
95
  onDestroyCallbacks: Set<() => void>;
96
- "__#14263@#clickDomRootEventCallbacks": Set<(event: MouseEvent) => void>;
96
+ "__#14558@#clickDomRootEventCallbacks": Set<(event: MouseEvent) => void>;
97
97
  registerPrimitive<T extends object>(primitiveInstance: T): void;
98
98
  deregisterPrimitive<T extends object>(primitiveInstance: T): void;
99
99
  preventPrimitiveFromCdkEvent<T extends object>(primitiveInstance: T, eventType: import("./utils/types").EventType): void;
@@ -104,9 +104,9 @@ export declare class RdxHoverCardRootDirective {
104
104
  primitivePreventedFromCdkEvent<T extends object>(primitiveInstance: T, eventType: import("./utils/types").EventType): boolean | undefined;
105
105
  addClickDomRootEventCallback(callback: (event: MouseEvent) => void): void;
106
106
  removeClickDomRootEventCallback(callback: (event: MouseEvent) => void): boolean;
107
- "__#14263@#setPreventPrimitiveFromCdkEvent"<T extends object, R extends import("./utils/types").EventType, K extends import("./utils/types").PrimitiveConfig[`prevent${Capitalize<R>}`]>(primitiveInstance: T, eventType: R, value: K): void;
108
- "__#14263@#registerOnDestroyCallbacks"(): void;
109
- "__#14263@#listenToClickDomRootEvent"(): void;
107
+ "__#14558@#setPreventPrimitiveFromCdkEvent"<T extends object, R extends import("./utils/types").EventType, K extends import("./utils/types").PrimitiveConfig[`prevent${Capitalize<R>}`]>(primitiveInstance: T, eventType: R, value: K): void;
108
+ "__#14558@#registerOnDestroyCallbacks"(): void;
109
+ "__#14558@#listenToClickDomRootEvent"(): void;
110
110
  } | null;
111
111
  /** @ignore */
112
112
  readonly destroyRef: DestroyRef;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radix-ng/primitives",
3
- "version": "0.40.0",
3
+ "version": "0.41.0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -88,10 +88,18 @@
88
88
  "types": "./dialog/index.d.ts",
89
89
  "default": "./fesm2022/radix-ng-primitives-dialog.mjs"
90
90
  },
91
+ "./dismissible-layer": {
92
+ "types": "./dismissible-layer/index.d.ts",
93
+ "default": "./fesm2022/radix-ng-primitives-dismissible-layer.mjs"
94
+ },
91
95
  "./dropdown-menu": {
92
96
  "types": "./dropdown-menu/index.d.ts",
93
97
  "default": "./fesm2022/radix-ng-primitives-dropdown-menu.mjs"
94
98
  },
99
+ "./editable": {
100
+ "types": "./editable/index.d.ts",
101
+ "default": "./fesm2022/radix-ng-primitives-editable.mjs"
102
+ },
95
103
  "./hover-card": {
96
104
  "types": "./hover-card/index.d.ts",
97
105
  "default": "./fesm2022/radix-ng-primitives-hover-card.mjs"
@@ -70,7 +70,7 @@ export declare class RdxPopoverRootDirective {
70
70
  window: Window & typeof globalThis;
71
71
  primitiveConfigs?: import("./utils/types").PrimitiveConfigs;
72
72
  onDestroyCallbacks: Set<() => void>;
73
- "__#18641@#clickDomRootEventCallbacks": Set<(event: MouseEvent) => void>;
73
+ "__#18898@#clickDomRootEventCallbacks": Set<(event: MouseEvent) => void>;
74
74
  registerPrimitive<T extends object>(primitiveInstance: T): void;
75
75
  deregisterPrimitive<T extends object>(primitiveInstance: T): void;
76
76
  preventPrimitiveFromCdkEvent<T extends object>(primitiveInstance: T, eventType: import("./utils/types").EventType): void;
@@ -81,9 +81,9 @@ export declare class RdxPopoverRootDirective {
81
81
  primitivePreventedFromCdkEvent<T extends object>(primitiveInstance: T, eventType: import("./utils/types").EventType): boolean | undefined;
82
82
  addClickDomRootEventCallback(callback: (event: MouseEvent) => void): void;
83
83
  removeClickDomRootEventCallback(callback: (event: MouseEvent) => void): boolean;
84
- "__#18641@#setPreventPrimitiveFromCdkEvent"<T extends object, R extends import("./utils/types").EventType, K extends import("./utils/types").PrimitiveConfig[`prevent${Capitalize<R>}`]>(primitiveInstance: T, eventType: R, value: K): void;
85
- "__#18641@#registerOnDestroyCallbacks"(): void;
86
- "__#18641@#listenToClickDomRootEvent"(): void;
84
+ "__#18898@#setPreventPrimitiveFromCdkEvent"<T extends object, R extends import("./utils/types").EventType, K extends import("./utils/types").PrimitiveConfig[`prevent${Capitalize<R>}`]>(primitiveInstance: T, eventType: R, value: K): void;
85
+ "__#18898@#registerOnDestroyCallbacks"(): void;
86
+ "__#18898@#listenToClickDomRootEvent"(): void;
87
87
  } | null;
88
88
  /** @ignore */
89
89
  readonly destroyRef: DestroyRef;
@@ -79,7 +79,7 @@ export declare class RdxTooltipRootDirective {
79
79
  window: Window & typeof globalThis;
80
80
  primitiveConfigs?: import("./utils/types").PrimitiveConfigs;
81
81
  onDestroyCallbacks: Set<() => void>;
82
- "__#22490@#clickDomRootEventCallbacks": Set<(event: MouseEvent) => void>;
82
+ "__#22743@#clickDomRootEventCallbacks": Set<(event: MouseEvent) => void>;
83
83
  registerPrimitive<T extends object>(primitiveInstance: T): void;
84
84
  deregisterPrimitive<T extends object>(primitiveInstance: T): void;
85
85
  preventPrimitiveFromCdkEvent<T extends object>(primitiveInstance: T, eventType: import("./utils/types").EventType): void;
@@ -90,9 +90,9 @@ export declare class RdxTooltipRootDirective {
90
90
  primitivePreventedFromCdkEvent<T extends object>(primitiveInstance: T, eventType: import("./utils/types").EventType): boolean | undefined;
91
91
  addClickDomRootEventCallback(callback: (event: MouseEvent) => void): void;
92
92
  removeClickDomRootEventCallback(callback: (event: MouseEvent) => void): boolean;
93
- "__#22490@#setPreventPrimitiveFromCdkEvent"<T extends object, R extends import("./utils/types").EventType, K extends import("./utils/types").PrimitiveConfig[`prevent${Capitalize<R>}`]>(primitiveInstance: T, eventType: R, value: K): void;
94
- "__#22490@#registerOnDestroyCallbacks"(): void;
95
- "__#22490@#listenToClickDomRootEvent"(): void;
93
+ "__#22743@#setPreventPrimitiveFromCdkEvent"<T extends object, R extends import("./utils/types").EventType, K extends import("./utils/types").PrimitiveConfig[`prevent${Capitalize<R>}`]>(primitiveInstance: T, eventType: R, value: K): void;
94
+ "__#22743@#registerOnDestroyCallbacks"(): void;
95
+ "__#22743@#listenToClickDomRootEvent"(): void;
96
96
  } | null;
97
97
  /** @ignore */
98
98
  readonly destroyRef: DestroyRef;