@frame-ui-ng/components 0.2.0-beta.0 → 0.3.0-beta.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.
Files changed (36) hide show
  1. package/button/src/styles/button.css +15 -3
  2. package/dropdown-menu/src/styles/_vars.css +1 -1
  3. package/dropdown-menu/src/styles/dropdown-menu-item.css +87 -87
  4. package/fesm2022/frame-ui-ng-components-calendar.mjs +369 -263
  5. package/fesm2022/frame-ui-ng-components-calendar.mjs.map +1 -1
  6. package/fesm2022/frame-ui-ng-components-command.mjs +1 -1
  7. package/fesm2022/frame-ui-ng-components-command.mjs.map +1 -1
  8. package/fesm2022/frame-ui-ng-components-date-picker.mjs +232 -226
  9. package/fesm2022/frame-ui-ng-components-date-picker.mjs.map +1 -1
  10. package/fesm2022/frame-ui-ng-components-dropdown-menu.mjs +45 -22
  11. package/fesm2022/frame-ui-ng-components-dropdown-menu.mjs.map +1 -1
  12. package/fesm2022/frame-ui-ng-components-input.mjs +6 -3
  13. package/fesm2022/frame-ui-ng-components-input.mjs.map +1 -1
  14. package/fesm2022/frame-ui-ng-components-select.mjs +6 -3
  15. package/fesm2022/frame-ui-ng-components-select.mjs.map +1 -1
  16. package/fesm2022/frame-ui-ng-components-sidebar.mjs +47 -4
  17. package/fesm2022/frame-ui-ng-components-sidebar.mjs.map +1 -1
  18. package/fesm2022/frame-ui-ng-components-tooltip.mjs +263 -254
  19. package/fesm2022/frame-ui-ng-components-tooltip.mjs.map +1 -1
  20. package/fesm2022/frame-ui-ng-components.mjs +703 -519
  21. package/fesm2022/frame-ui-ng-components.mjs.map +1 -1
  22. package/input/src/styles/input-group.css +50 -0
  23. package/package.json +2 -2
  24. package/select/src/styles/select-trigger.css +7 -36
  25. package/src/styles/blueprint.css +4 -11
  26. package/styles/blueprint.css +4 -11
  27. package/tooltip/src/styles/tooltip.css +3 -9
  28. package/types/frame-ui-ng-components-calendar.d.ts +14 -0
  29. package/types/frame-ui-ng-components-context-menu.d.ts +2 -2
  30. package/types/frame-ui-ng-components-date-picker.d.ts +3 -1
  31. package/types/frame-ui-ng-components-dropdown-menu.d.ts +3 -3
  32. package/types/frame-ui-ng-components-input.d.ts +6 -3
  33. package/types/frame-ui-ng-components-select.d.ts +6 -3
  34. package/types/frame-ui-ng-components-sidebar.d.ts +8 -1
  35. package/types/frame-ui-ng-components-tooltip.d.ts +43 -73
  36. package/types/frame-ui-ng-components.d.ts +84 -55
@@ -1,7 +1,8 @@
1
+ import { Overlay } from '@angular/cdk/overlay';
2
+ import { ComponentPortal } from '@angular/cdk/portal';
3
+ import { DOCUMENT, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
1
4
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, TemplateRef, input, booleanAttribute, Directive, ElementRef, output, signal, computed, afterNextRender, ChangeDetectionStrategy, Component, effect, NgModule } from '@angular/core';
3
- import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
4
- import { NgTemplateOutlet } from '@angular/common';
5
+ import { inject, DestroyRef, ElementRef, PLATFORM_ID, input, booleanAttribute, numberAttribute, signal, effect, Directive, TemplateRef, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
5
6
 
6
7
  function buildTooltipPositions(options) {
7
8
  const primary = buildPosition(options.side, options);
@@ -54,76 +55,7 @@ function oppositeSide(side) {
54
55
  return 'left';
55
56
  }
56
57
 
57
- const FR_TOOLTIP_CONTROLLER = new InjectionToken('FR_TOOLTIP_CONTROLLER');
58
-
59
- let nextTooltipId = 0;
60
- class FrTooltipContent {
61
- templateRef = inject((TemplateRef));
62
- id = `frame-tooltip-${nextTooltipId++}`;
63
- align = input('center', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
64
- alignOffset = input(0, ...(ngDevMode ? [{ debugName: "alignOffset" }] : /* istanbul ignore next */ []));
65
- arrow = input(false, { ...(ngDevMode ? { debugName: "arrow" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
66
- debugVisible = input(false, { ...(ngDevMode ? { debugName: "debugVisible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
67
- side = input('top', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
68
- sideOffset = input(8, ...(ngDevMode ? [{ debugName: "sideOffset" }] : /* istanbul ignore next */ []));
69
- getPositions() {
70
- return buildTooltipPositions({
71
- align: this.align(),
72
- alignOffset: this.alignOffset(),
73
- side: this.side(),
74
- sideOffset: this.sideOffset(),
75
- });
76
- }
77
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
78
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.16", type: FrTooltipContent, isStandalone: true, selector: "ng-template[frTooltipContent]", inputs: { align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, alignOffset: { classPropertyName: "alignOffset", publicName: "alignOffset", isSignal: true, isRequired: false, transformFunction: null }, arrow: { classPropertyName: "arrow", publicName: "arrow", isSignal: true, isRequired: false, transformFunction: null }, debugVisible: { classPropertyName: "debugVisible", publicName: "debugVisible", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "sideOffset", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["frTooltipContent"], ngImport: i0 });
79
- }
80
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipContent, decorators: [{
81
- type: Directive,
82
- args: [{
83
- selector: 'ng-template[frTooltipContent]',
84
- exportAs: 'frTooltipContent',
85
- }]
86
- }], propDecorators: { align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], alignOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignOffset", required: false }] }], arrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "arrow", required: false }] }], debugVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "debugVisible", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], sideOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOffset", required: false }] }] } });
87
- class FrTooltipPanel {
88
- content = inject(FrTooltipContent);
89
- root = inject(FR_TOOLTIP_CONTROLLER);
90
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipPanel, deps: [], target: i0.ɵɵFactoryTarget.Directive });
91
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.16", type: FrTooltipPanel, isStandalone: true, selector: "[frTooltipPanel]", host: { attributes: { "role": "tooltip" }, properties: { "id": "content.id", "attr.data-side": "root.overlaySide()", "attr.data-arrow": "content.arrow() ? \"\" : null" }, classAttribute: "frame-tooltip__content" }, ngImport: i0 });
92
- }
93
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipPanel, decorators: [{
94
- type: Directive,
95
- args: [{
96
- selector: '[frTooltipPanel]',
97
- host: {
98
- class: 'frame-tooltip__content',
99
- role: 'tooltip',
100
- '[id]': 'content.id',
101
- '[attr.data-side]': 'root.overlaySide()',
102
- '[attr.data-arrow]': 'content.arrow() ? "" : null',
103
- },
104
- }]
105
- }] });
106
- class FrTooltipShortcut {
107
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipShortcut, deps: [], target: i0.ɵɵFactoryTarget.Directive });
108
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.16", type: FrTooltipShortcut, isStandalone: true, selector: "[frTooltipShortcut]", host: { classAttribute: "frame-tooltip__shortcut" }, ngImport: i0 });
109
- }
110
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipShortcut, decorators: [{
111
- type: Directive,
112
- args: [{
113
- selector: '[frTooltipShortcut]',
114
- host: {
115
- class: 'frame-tooltip__shortcut',
116
- },
117
- }]
118
- }] });
119
-
120
- const DEFAULT_POSITIONS = buildTooltipPositions({
121
- align: 'center',
122
- alignOffset: 0,
123
- side: 'top',
124
- sideOffset: 8,
125
- });
126
- const TOOLTIP_TOKEN_NAMES = [
58
+ const FR_TOOLTIP_TOKEN_NAMES = [
127
59
  '--frame-tooltip-content-bg',
128
60
  '--frame-tooltip-content-color',
129
61
  '--frame-tooltip-content-border',
@@ -140,34 +72,104 @@ const TOOLTIP_TOKEN_NAMES = [
140
72
  '--frame-tooltip-motion-scale',
141
73
  '--frame-tooltip-motion-easing',
142
74
  ];
143
- class FrTooltipRoot {
75
+
76
+ let nextInlineTooltipId = 0;
77
+ class FrTooltipDirective {
78
+ destroyRef = inject(DestroyRef);
79
+ document = inject(DOCUMENT);
144
80
  elementRef = inject(ElementRef);
145
- openDelay = input(700, ...(ngDevMode ? [{ debugName: "openDelay" }] : /* istanbul ignore next */ []));
146
- closeDelay = input(0, ...(ngDevMode ? [{ debugName: "closeDelay" }] : /* istanbul ignore next */ []));
147
- defaultOpen = input(false, { ...(ngDevMode ? { debugName: "defaultOpen" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
148
- debugVisible = input(false, { ...(ngDevMode ? { debugName: "debugVisible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
149
- openChange = output();
81
+ overlay = inject(Overlay);
82
+ platformId = inject(PLATFORM_ID);
83
+ content = input(null, { ...(ngDevMode ? { debugName: "content" } : /* istanbul ignore next */ {}), alias: 'frTooltip' });
84
+ align = input('center', { ...(ngDevMode ? { debugName: "align" } : /* istanbul ignore next */ {}), alias: 'frTooltipAlign' });
85
+ alignOffset = input(0, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), alias: 'frTooltipAlignOffset' });
86
+ arrow = input(false, { ...(ngDevMode ? { debugName: "arrow" } : /* istanbul ignore next */ {}), alias: 'frTooltipArrow', transform: booleanAttribute });
87
+ closeDelay = input(0, { ...(ngDevMode ? { debugName: "closeDelay" } : /* istanbul ignore next */ {}), alias: 'frTooltipCloseDelay' });
88
+ openDelay = input(0, { ...(ngDevMode ? { debugName: "openDelay" } : /* istanbul ignore next */ {}), alias: 'frTooltipOpenDelay', transform: numberAttribute });
89
+ side = input('top', { ...(ngDevMode ? { debugName: "side" } : /* istanbul ignore next */ {}), alias: 'frTooltipSide' });
90
+ sideOffset = input(8, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), alias: 'frTooltipSideOffset' });
150
91
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
151
- content = signal(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
152
- overlaySide = signal('top', ...(ngDevMode ? [{ debugName: "overlaySide" }] : /* istanbul ignore next */ []));
153
- openTimer = null;
92
+ tooltipId = `frame-tooltip-inline-${nextInlineTooltipId++}`;
154
93
  closeTimer = null;
155
- triggerElement = null;
156
- positions = computed(() => this.content()?.getPositions() ?? DEFAULT_POSITIONS, ...(ngDevMode ? [{ debugName: "positions" }] : /* istanbul ignore next */ []));
94
+ disabledObserver = null;
95
+ openTimer = null;
96
+ overlayRef = null;
97
+ panelRef = null;
98
+ triggerElement = this.elementRef.nativeElement;
99
+ wrapped = false;
100
+ wrapper = null;
101
+ teardownListeners = [];
157
102
  constructor() {
158
- afterNextRender(() => {
159
- if (this.defaultOpen() || this.debugVisible()) {
160
- this.open();
103
+ this.destroyRef.onDestroy(() => this.destroy());
104
+ effect(() => {
105
+ const content = this.content();
106
+ if (this.panelRef && content) {
107
+ this.updatePanelInputs();
108
+ }
109
+ if (!content) {
110
+ this.close();
161
111
  }
162
112
  });
163
113
  }
164
- registerTrigger(trigger) {
165
- this.triggerElement = trigger;
114
+ ngAfterViewInit() {
115
+ if (!isPlatformBrowser(this.platformId)) {
116
+ return;
117
+ }
118
+ this.ensureDisabledHostWrapper();
119
+ this.bindTriggerEvents();
120
+ this.observeDisabledState();
166
121
  }
167
- setContent(content) {
168
- this.content.set(content instanceof FrTooltipContent ? content : null);
122
+ bindTriggerEvents() {
123
+ const target = this.triggerElement;
124
+ this.teardownListeners.push(this.listen(target, 'mouseenter', () => this.openWithDelay()));
125
+ this.teardownListeners.push(this.listen(target, 'mouseleave', () => this.closeWithDelay()));
126
+ this.teardownListeners.push(this.listen(target, 'focusin', () => this.openWithDelay()));
127
+ this.teardownListeners.push(this.listen(target, 'focusout', () => this.closeWithDelay()));
128
+ this.teardownListeners.push(this.listen(target, 'keydown', (event) => {
129
+ const keyboardEvent = event;
130
+ if (keyboardEvent.key === 'Escape') {
131
+ keyboardEvent.preventDefault();
132
+ this.close();
133
+ }
134
+ }));
135
+ }
136
+ ensureDisabledHostWrapper() {
137
+ const element = this.elementRef.nativeElement;
138
+ if (!('disabled' in element) || !element.hasAttribute('disabled') || this.wrapped) {
139
+ return;
140
+ }
141
+ const parent = element.parentNode;
142
+ if (!parent) {
143
+ return;
144
+ }
145
+ const wrapper = this.document.createElement('span');
146
+ wrapper.className = 'frame-tooltip__disabled-trigger';
147
+ wrapper.tabIndex = 0;
148
+ parent.insertBefore(wrapper, element);
149
+ wrapper.appendChild(element);
150
+ this.triggerElement = wrapper;
151
+ this.wrapper = wrapper;
152
+ this.wrapped = true;
153
+ }
154
+ observeDisabledState() {
155
+ const element = this.elementRef.nativeElement;
156
+ if (!('disabled' in element)) {
157
+ return;
158
+ }
159
+ this.disabledObserver = new MutationObserver(() => {
160
+ if (!element.hasAttribute('disabled') || this.wrapped) {
161
+ return;
162
+ }
163
+ this.teardownTriggerListeners();
164
+ this.ensureDisabledHostWrapper();
165
+ this.bindTriggerEvents();
166
+ });
167
+ this.disabledObserver.observe(element, { attributes: true, attributeFilter: ['disabled'] });
169
168
  }
170
169
  openWithDelay() {
170
+ if (!this.content()) {
171
+ return;
172
+ }
171
173
  this.cancelClose();
172
174
  this.cancelOpen();
173
175
  const delay = Math.max(0, this.openDelay());
@@ -178,9 +180,6 @@ class FrTooltipRoot {
178
180
  this.openTimer = setTimeout(() => this.open(), delay);
179
181
  }
180
182
  closeWithDelay() {
181
- if (this.debugVisible()) {
182
- return;
183
- }
184
183
  this.cancelOpen();
185
184
  this.cancelClose();
186
185
  const delay = Math.max(0, this.closeDelay());
@@ -191,80 +190,93 @@ class FrTooltipRoot {
191
190
  this.closeTimer = setTimeout(() => this.close(), delay);
192
191
  }
193
192
  open() {
194
- if (!this.content()) {
193
+ const content = this.content();
194
+ if (!content) {
195
195
  return;
196
196
  }
197
- if (!this.isOpen()) {
198
- this.isOpen.set(true);
199
- this.openChange.emit(true);
200
- this.scheduleCustomPropertySync();
197
+ if (!this.overlayRef) {
198
+ this.overlayRef = this.createOverlay();
199
+ }
200
+ if (!this.overlayRef.hasAttached()) {
201
+ this.panelRef = this.overlayRef.attach(new ComponentPortal(FrTooltipInlinePanel));
202
+ this.updatePanelInputs();
203
+ this.syncCustomPropertiesToOverlay();
201
204
  }
205
+ this.isOpen.set(true);
202
206
  }
203
207
  close() {
204
- if (this.debugVisible()) {
205
- return;
206
- }
207
208
  this.cancelOpen();
208
209
  this.cancelClose();
209
- if (this.isOpen()) {
210
- this.isOpen.set(false);
211
- this.openChange.emit(false);
212
- }
210
+ this.overlayRef?.detach();
211
+ this.panelRef = null;
212
+ this.isOpen.set(false);
213
213
  }
214
- handleOverlayKeydown(event) {
215
- if (event.key === 'Escape') {
216
- event.preventDefault();
217
- this.close();
218
- }
214
+ createOverlay() {
215
+ const positionStrategy = this.overlay
216
+ .position()
217
+ .flexibleConnectedTo(this.triggerElement)
218
+ .withPositions(this.positions())
219
+ .withPush(true)
220
+ .withViewportMargin(8);
221
+ positionStrategy.positionChanges.subscribe((event) => this.handlePositionChange(event));
222
+ const overlayRef = this.overlay.create({
223
+ panelClass: ['frame-tooltip-overlay', `frame-tooltip-overlay--${this.side()}`],
224
+ positionStrategy,
225
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
226
+ });
227
+ overlayRef.keydownEvents().subscribe((event) => {
228
+ if (event.key === 'Escape') {
229
+ event.preventDefault();
230
+ this.close();
231
+ }
232
+ });
233
+ return overlayRef;
234
+ }
235
+ positions() {
236
+ return buildTooltipPositions({
237
+ align: this.align(),
238
+ alignOffset: this.alignOffset(),
239
+ side: this.side(),
240
+ sideOffset: this.sideOffset(),
241
+ });
219
242
  }
220
243
  handlePositionChange(event) {
221
244
  const pair = event.connectionPair;
222
- if (pair.overlayY === 'top') {
223
- this.overlaySide.set('bottom');
224
- return;
225
- }
226
- if (pair.overlayY === 'bottom') {
227
- this.overlaySide.set('top');
228
- return;
229
- }
230
- this.overlaySide.set(pair.overlayX === 'start' ? 'right' : 'left');
245
+ const side = pair.overlayY === 'top'
246
+ ? 'bottom'
247
+ : pair.overlayY === 'bottom'
248
+ ? 'top'
249
+ : pair.overlayX === 'start'
250
+ ? 'right'
251
+ : 'left';
252
+ this.panelRef?.setInput('side', side);
253
+ this.overlayRef?.removePanelClass(['frame-tooltip-overlay--top', 'frame-tooltip-overlay--right', 'frame-tooltip-overlay--bottom', 'frame-tooltip-overlay--left']);
254
+ this.overlayRef?.addPanelClass(`frame-tooltip-overlay--${side}`);
231
255
  }
232
- overlayPanelClasses() {
233
- return ['frame-tooltip-overlay', `frame-tooltip-overlay--${this.overlaySide()}`];
234
- }
235
- cancelOpen() {
236
- if (this.openTimer) {
237
- clearTimeout(this.openTimer);
238
- this.openTimer = null;
239
- }
240
- }
241
- cancelClose() {
242
- if (this.closeTimer) {
243
- clearTimeout(this.closeTimer);
244
- this.closeTimer = null;
256
+ updatePanelInputs() {
257
+ const panelRef = this.panelRef;
258
+ if (!panelRef) {
259
+ return;
245
260
  }
261
+ panelRef.setInput('arrow', this.arrow());
262
+ panelRef.setInput('content', this.content() ?? '');
263
+ panelRef.setInput('id', this.tooltipId);
264
+ panelRef.setInput('side', this.side());
246
265
  }
247
266
  syncCustomPropertiesToOverlay() {
248
- const triggerElement = this.triggerElement;
249
- const overlayPane = document.querySelector('.cdk-overlay-pane.frame-tooltip-overlay');
267
+ const overlayPane = this.overlayRef?.overlayElement;
250
268
  const panel = overlayPane?.querySelector('.frame-tooltip__content');
251
- if (!triggerElement || !overlayPane || !panel) {
269
+ if (!overlayPane || !panel) {
252
270
  return;
253
271
  }
254
272
  this.copyCustomProperties(this.elementRef.nativeElement, overlayPane, panel);
255
- this.copyCustomProperties(triggerElement, overlayPane, panel);
256
- }
257
- scheduleCustomPropertySync() {
258
- queueMicrotask(() => {
259
- this.syncCustomPropertiesToOverlay();
260
- if (typeof requestAnimationFrame === 'function') {
261
- requestAnimationFrame(() => this.syncCustomPropertiesToOverlay());
262
- }
263
- });
273
+ if (this.wrapper) {
274
+ this.copyCustomProperties(this.wrapper, overlayPane, panel);
275
+ }
264
276
  }
265
277
  copyCustomProperties(source, overlayPane, panel) {
266
278
  const sourceStyles = getComputedStyle(source);
267
- for (const propertyName of TOOLTIP_TOKEN_NAMES) {
279
+ for (const propertyName of FR_TOOLTIP_TOKEN_NAMES) {
268
280
  const propertyValue = sourceStyles.getPropertyValue(propertyName);
269
281
  if (propertyValue.trim()) {
270
282
  overlayPane.style.setProperty(propertyName, propertyValue);
@@ -281,139 +293,136 @@ class FrTooltipRoot {
281
293
  panel.style.setProperty(propertyName, propertyValue);
282
294
  }
283
295
  }
284
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipRoot, deps: [], target: i0.ɵɵFactoryTarget.Component });
285
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: FrTooltipRoot, isStandalone: true, selector: "frame-tooltip", inputs: { openDelay: { classPropertyName: "openDelay", publicName: "openDelay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, debugVisible: { classPropertyName: "debugVisible", publicName: "debugVisible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openChange: "openChange" }, host: { properties: { "attr.data-state": "isOpen() ? \"open\" : \"closed\"" }, classAttribute: "frame-tooltip" }, providers: [
286
- {
287
- provide: FR_TOOLTIP_CONTROLLER,
288
- useExisting: FrTooltipRoot,
289
- },
290
- ], exportAs: ["frTooltip"], ngImport: i0, template: `
291
- <span cdkOverlayOrigin #origin="cdkOverlayOrigin" class="frame-tooltip__anchor">
292
- <ng-content />
293
- </span>
294
-
295
- <ng-template
296
- cdkConnectedOverlay
297
- [cdkConnectedOverlayOrigin]="origin"
298
- [cdkConnectedOverlayOpen]="isOpen()"
299
- [cdkConnectedOverlayPositions]="positions()"
300
- [cdkConnectedOverlayPanelClass]="overlayPanelClasses()"
301
- [cdkConnectedOverlayPush]="true"
302
- [cdkConnectedOverlayViewportMargin]="8"
303
- (detach)="close()"
304
- (overlayKeydown)="handleOverlayKeydown($event)"
305
- (positionChange)="handlePositionChange($event)"
306
- >
307
- <ng-container [ngTemplateOutlet]="content()?.templateRef ?? null" />
308
- </ng-template>
309
- `, isInline: true, dependencies: [{ kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
296
+ listen(target, eventName, listener) {
297
+ target.addEventListener(eventName, listener);
298
+ return () => target.removeEventListener(eventName, listener);
299
+ }
300
+ cancelOpen() {
301
+ if (this.openTimer) {
302
+ clearTimeout(this.openTimer);
303
+ this.openTimer = null;
304
+ }
305
+ }
306
+ cancelClose() {
307
+ if (this.closeTimer) {
308
+ clearTimeout(this.closeTimer);
309
+ this.closeTimer = null;
310
+ }
311
+ }
312
+ destroy() {
313
+ this.close();
314
+ this.overlayRef?.dispose();
315
+ this.overlayRef = null;
316
+ this.disabledObserver?.disconnect();
317
+ this.disabledObserver = null;
318
+ this.teardownTriggerListeners();
319
+ }
320
+ teardownTriggerListeners() {
321
+ for (const teardown of this.teardownListeners) {
322
+ teardown();
323
+ }
324
+ this.teardownListeners = [];
325
+ }
326
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
327
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.16", type: FrTooltipDirective, isStandalone: true, selector: "[frTooltip]", inputs: { content: { classPropertyName: "content", publicName: "frTooltip", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "frTooltipAlign", isSignal: true, isRequired: false, transformFunction: null }, alignOffset: { classPropertyName: "alignOffset", publicName: "frTooltipAlignOffset", isSignal: true, isRequired: false, transformFunction: null }, arrow: { classPropertyName: "arrow", publicName: "frTooltipArrow", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "frTooltipCloseDelay", isSignal: true, isRequired: false, transformFunction: null }, openDelay: { classPropertyName: "openDelay", publicName: "frTooltipOpenDelay", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "frTooltipSide", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "frTooltipSideOffset", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.aria-describedby": "isOpen() ? tooltipId : null", "attr.data-state": "isOpen() ? \"open\" : \"closed\"" }, classAttribute: "frame-tooltip__trigger" }, ngImport: i0 });
310
328
  }
311
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipRoot, decorators: [{
312
- type: Component,
329
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipDirective, decorators: [{
330
+ type: Directive,
313
331
  args: [{
314
- selector: 'frame-tooltip',
315
- exportAs: 'frTooltip',
316
- imports: [CdkConnectedOverlay, CdkOverlayOrigin, NgTemplateOutlet],
317
- providers: [
318
- {
319
- provide: FR_TOOLTIP_CONTROLLER,
320
- useExisting: FrTooltipRoot,
321
- },
322
- ],
323
- changeDetection: ChangeDetectionStrategy.OnPush,
332
+ selector: '[frTooltip]',
324
333
  host: {
325
- class: 'frame-tooltip',
334
+ class: 'frame-tooltip__trigger',
335
+ '[attr.aria-describedby]': 'isOpen() ? tooltipId : null',
326
336
  '[attr.data-state]': 'isOpen() ? "open" : "closed"',
327
337
  },
328
- template: `
329
- <span cdkOverlayOrigin #origin="cdkOverlayOrigin" class="frame-tooltip__anchor">
330
- <ng-content />
331
- </span>
332
-
333
- <ng-template
334
- cdkConnectedOverlay
335
- [cdkConnectedOverlayOrigin]="origin"
336
- [cdkConnectedOverlayOpen]="isOpen()"
337
- [cdkConnectedOverlayPositions]="positions()"
338
- [cdkConnectedOverlayPanelClass]="overlayPanelClasses()"
339
- [cdkConnectedOverlayPush]="true"
340
- [cdkConnectedOverlayViewportMargin]="8"
341
- (detach)="close()"
342
- (overlayKeydown)="handleOverlayKeydown($event)"
343
- (positionChange)="handlePositionChange($event)"
344
- >
345
- <ng-container [ngTemplateOutlet]="content()?.templateRef ?? null" />
346
- </ng-template>
347
- `,
348
338
  }]
349
- }], ctorParameters: () => [], propDecorators: { openDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "openDelay", required: false }] }], closeDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeDelay", required: false }] }], defaultOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultOpen", required: false }] }], debugVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "debugVisible", required: false }] }], openChange: [{ type: i0.Output, args: ["openChange"] }] } });
350
-
351
- class FrTooltipTrigger {
352
- content = input(null, { ...(ngDevMode ? { debugName: "content" } : /* istanbul ignore next */ {}), alias: 'frTooltipTrigger' });
353
- root = inject(FR_TOOLTIP_CONTROLLER);
354
- elementRef = inject(ElementRef);
339
+ }], ctorParameters: () => [], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "frTooltip", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "frTooltipAlign", required: false }] }], alignOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "frTooltipAlignOffset", required: false }] }], arrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "frTooltipArrow", required: false }] }], closeDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "frTooltipCloseDelay", required: false }] }], openDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "frTooltipOpenDelay", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "frTooltipSide", required: false }] }], sideOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "frTooltipSideOffset", required: false }] }] } });
340
+ class FrTooltipShortcut {
341
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipShortcut, deps: [], target: i0.ɵɵFactoryTarget.Directive });
342
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.16", type: FrTooltipShortcut, isStandalone: true, selector: "[frTooltipShortcut]", host: { classAttribute: "frame-tooltip__shortcut" }, ngImport: i0 });
343
+ }
344
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipShortcut, decorators: [{
345
+ type: Directive,
346
+ args: [{
347
+ selector: '[frTooltipShortcut]',
348
+ host: {
349
+ class: 'frame-tooltip__shortcut',
350
+ },
351
+ }]
352
+ }] });
353
+ class FrTooltipInlinePanel {
354
+ arrow = input(false, { ...(ngDevMode ? { debugName: "arrow" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
355
+ content = input('', ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
356
+ id = input.required(...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
357
+ side = input('top', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
358
+ templateContent = signal(null, ...(ngDevMode ? [{ debugName: "templateContent" }] : /* istanbul ignore next */ []));
359
+ textContent = signal('', ...(ngDevMode ? [{ debugName: "textContent" }] : /* istanbul ignore next */ []));
355
360
  constructor() {
356
- this.root.registerTrigger(this.elementRef.nativeElement);
357
361
  effect(() => {
358
362
  const content = this.content();
359
- if (content) {
360
- this.root.setContent(content);
363
+ if (content instanceof TemplateRef) {
364
+ this.templateContent.set(content);
365
+ this.textContent.set('');
366
+ return;
361
367
  }
368
+ this.templateContent.set(null);
369
+ this.textContent.set(content ?? '');
362
370
  });
363
371
  }
364
- handleMouseEnter() {
365
- this.root.setContent(this.content());
366
- this.root.openWithDelay();
367
- }
368
- handleMouseLeave() {
369
- this.root.closeWithDelay();
370
- }
371
- handleFocusIn() {
372
- this.root.setContent(this.content());
373
- this.root.openWithDelay();
374
- }
375
- handleFocusOut() {
376
- this.root.closeWithDelay();
377
- }
378
- handleKeydown(event) {
379
- if (event.key === 'Escape') {
380
- event.preventDefault();
381
- this.root.close();
382
- }
383
- }
384
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
385
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.16", type: FrTooltipTrigger, isStandalone: true, selector: "[frTooltipTrigger]", inputs: { content: { classPropertyName: "content", publicName: "frTooltipTrigger", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "handleMouseEnter()", "mouseleave": "handleMouseLeave()", "focusin": "handleFocusIn()", "focusout": "handleFocusOut()", "keydown": "handleKeydown($event)" }, properties: { "attr.aria-describedby": "root.isOpen() ? content()?.id : null", "attr.data-state": "root.isOpen() ? \"open\" : \"closed\"" }, classAttribute: "frame-tooltip__trigger" }, ngImport: i0 });
372
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipInlinePanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
373
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FrTooltipInlinePanel, isStandalone: true, selector: "frame-tooltip-inline-panel", inputs: { arrow: { classPropertyName: "arrow", publicName: "arrow", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
374
+ <div
375
+ class="frame-tooltip__content"
376
+ role="tooltip"
377
+ [id]="id()"
378
+ [attr.data-side]="side()"
379
+ [attr.data-arrow]="arrow() ? '' : null"
380
+ >
381
+ @if (templateContent(); as template) {
382
+ <ng-container [ngTemplateOutlet]="template" />
383
+ } @else {
384
+ {{ textContent() }}
385
+ }
386
+ </div>
387
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
386
388
  }
387
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipTrigger, decorators: [{
388
- type: Directive,
389
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipInlinePanel, decorators: [{
390
+ type: Component,
389
391
  args: [{
390
- selector: '[frTooltipTrigger]',
391
- host: {
392
- class: 'frame-tooltip__trigger',
393
- '[attr.aria-describedby]': 'root.isOpen() ? content()?.id : null',
394
- '[attr.data-state]': 'root.isOpen() ? "open" : "closed"',
395
- '(mouseenter)': 'handleMouseEnter()',
396
- '(mouseleave)': 'handleMouseLeave()',
397
- '(focusin)': 'handleFocusIn()',
398
- '(focusout)': 'handleFocusOut()',
399
- '(keydown)': 'handleKeydown($event)',
400
- },
392
+ selector: 'frame-tooltip-inline-panel',
393
+ imports: [NgTemplateOutlet],
394
+ changeDetection: ChangeDetectionStrategy.OnPush,
395
+ template: `
396
+ <div
397
+ class="frame-tooltip__content"
398
+ role="tooltip"
399
+ [id]="id()"
400
+ [attr.data-side]="side()"
401
+ [attr.data-arrow]="arrow() ? '' : null"
402
+ >
403
+ @if (templateContent(); as template) {
404
+ <ng-container [ngTemplateOutlet]="template" />
405
+ } @else {
406
+ {{ textContent() }}
407
+ }
408
+ </div>
409
+ `,
401
410
  }]
402
- }], ctorParameters: () => [], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "frTooltipTrigger", required: false }] }] } });
411
+ }], ctorParameters: () => [], propDecorators: { arrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "arrow", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }] } });
403
412
 
404
413
  const FR_TOOLTIP_SIDES = ['top', 'right', 'bottom', 'left'];
405
414
  const FR_TOOLTIP_ALIGNMENTS = ['start', 'center', 'end'];
406
415
 
407
416
  class FrTooltipModule {
408
417
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
409
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipModule, imports: [FrTooltipRoot, FrTooltipTrigger, FrTooltipContent, FrTooltipPanel, FrTooltipShortcut], exports: [FrTooltipRoot, FrTooltipTrigger, FrTooltipContent, FrTooltipPanel, FrTooltipShortcut] });
418
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipModule, imports: [FrTooltipDirective, FrTooltipShortcut], exports: [FrTooltipDirective, FrTooltipShortcut] });
410
419
  static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipModule });
411
420
  }
412
421
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrTooltipModule, decorators: [{
413
422
  type: NgModule,
414
423
  args: [{
415
- imports: [FrTooltipRoot, FrTooltipTrigger, FrTooltipContent, FrTooltipPanel, FrTooltipShortcut],
416
- exports: [FrTooltipRoot, FrTooltipTrigger, FrTooltipContent, FrTooltipPanel, FrTooltipShortcut],
424
+ imports: [FrTooltipDirective, FrTooltipShortcut],
425
+ exports: [FrTooltipDirective, FrTooltipShortcut],
417
426
  }]
418
427
  }] });
419
428
 
@@ -421,5 +430,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
421
430
  * Generated bundle index. Do not edit.
422
431
  */
423
432
 
424
- export { FR_TOOLTIP_ALIGNMENTS, FR_TOOLTIP_SIDES, FrTooltipRoot as FrTooltip, FrTooltipContent, FrTooltipModule, FrTooltipPanel, FrTooltipShortcut, FrTooltipTrigger };
433
+ export { FR_TOOLTIP_ALIGNMENTS, FR_TOOLTIP_SIDES, FrTooltipDirective, FrTooltipModule, FrTooltipShortcut };
425
434
  //# sourceMappingURL=frame-ui-ng-components-tooltip.mjs.map