@makigamestudio/ui-ionic 0.6.1 → 0.8.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,7 +1,17 @@
1
- import * as _makigamestudio_ui_core from '@makigamestudio/ui-core';
2
- import { ActionButton, ActionButtonConfig, ActionButtonType } from '@makigamestudio/ui-core';
1
+ import { ActionButton, ActionButtonConfig, ActionButtonType, TooltipPlacement } from '@makigamestudio/ui-core';
3
2
  import * as _angular_core from '@angular/core';
4
- import { Signal } from '@angular/core';
3
+ import { Signal, OnDestroy, TemplateRef } from '@angular/core';
4
+
5
+ /**
6
+ * @file IonicColor type
7
+ * @description Ionic color names for use in components and configs.
8
+ *
9
+ * This type centralizes all valid Ionic color names for use in the ui-ionic library.
10
+ *
11
+ * @example
12
+ * const color: IonicColor = 'primary';
13
+ */
14
+ type IonicColor = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
5
15
 
6
16
  /**
7
17
  * @file Ionic Action Button Types
@@ -47,7 +57,7 @@ type IonicPopoverAlignment = 'start' | 'center' | 'end';
47
57
  * const config: IonicActionButtonConfig = {
48
58
  * fill: 'solid', // Type-checked: 'clear' | 'outline' | 'solid' | 'default'
49
59
  * size: 'large', // Type-checked: 'small' | 'default' | 'large'
50
- * color: 'primary', // Any string (Ionic color names or custom)
60
+ * color: 'primary', // IonicColor (Ionic color names)
51
61
  * shape: 'round', // Type-checked: 'round' | undefined
52
62
  * expand: 'block', // Type-checked: 'block' | 'full' | undefined
53
63
  * dropdownAlignment: 'end' // Type-checked: 'start' | 'center' | 'end'
@@ -103,7 +113,14 @@ type IonicActionButtonConfig = ActionButtonConfig<IonicButtonFill, IonicButtonSi
103
113
  * };
104
114
  * ```
105
115
  */
106
- type IonicActionButton<T = void> = ActionButton<T, IonicActionButtonConfig>;
116
+ type IonicActionButton<T = void> = Omit<ActionButton<T, IonicActionButtonConfig>, 'config' | 'tooltipColor' | 'children'> & {
117
+ /** Optional configuration for button styling. */
118
+ readonly config?: IonicActionButtonConfig;
119
+ /** Optional color for the tooltip background. */
120
+ readonly tooltipColor?: IonicColor;
121
+ /** Child action buttons for dropdown menus. */
122
+ readonly children?: readonly IonicActionButton<T>[];
123
+ };
107
124
 
108
125
  /**
109
126
  * Component that renders a list of action buttons for use in popovers/dropdowns.
@@ -131,10 +148,10 @@ type IonicActionButton<T = void> = ActionButton<T, IonicActionButtonConfig>;
131
148
  *
132
149
  * @usageNotes
133
150
  * ### Inputs
134
- * - `buttons` (required): Array of `ActionButton` objects to display
151
+ * - `buttons` (required): Array of `IonicActionButton` objects to display
135
152
  *
136
153
  * ### Outputs
137
- * - `buttonSelect`: Emits the selected `ActionButton` when clicked
154
+ * - `buttonSelect`: Emits the selected `IonicActionButton` when clicked
138
155
  */
139
156
  declare class ActionButtonListComponent {
140
157
  /** Reference to ActionButtonType.Dropdown for template comparison. */
@@ -148,38 +165,38 @@ declare class ActionButtonListComponent {
148
165
  /** Internal signal to store the Set of currently loading child button IDs. */
149
166
  private readonly _loadingChildIdsFromProps;
150
167
  /** The list of action buttons to display (when used via template binding). */
151
- readonly buttons: _angular_core.InputSignal<readonly ActionButton<void, _makigamestudio_ui_core.ActionButtonConfig<string, string, string, string, string>>[]>;
168
+ readonly buttons: _angular_core.InputSignal<readonly IonicActionButton[]>;
152
169
  /** Emits when a button is selected from the list. */
153
- readonly buttonSelect: _angular_core.OutputEmitterRef<ActionButton<void, _makigamestudio_ui_core.ActionButtonConfig<string, string, string, string, string>>>;
170
+ readonly buttonSelect: _angular_core.OutputEmitterRef<IonicActionButton>;
154
171
  /** Computed button list that works with both signal input and componentProps. */
155
- protected readonly buttonList: Signal<readonly ActionButton<void, _makigamestudio_ui_core.ActionButtonConfig<string, string, string, string, string>>[]>;
172
+ protected readonly buttonList: Signal<readonly IonicActionButton[]>;
156
173
  /**
157
174
  * Setter to capture buttons passed via PopoverController.create({ componentProps }).
158
175
  * This is called when Ionic sets the property directly on the component instance.
159
176
  */
160
- set buttonsFromPopover(value: readonly ActionButton[]);
177
+ set buttonsFromPopover(value: readonly IonicActionButton[]);
161
178
  /**
162
179
  * Setter to capture loading child IDs signal passed via PopoverController.create({ componentProps }).
163
180
  */
164
181
  set loadingChildIds(value: Signal<ReadonlySet<string>>);
165
182
  /** Checks if a button can be selected. */
166
- protected canSelectButton(button: ActionButton): boolean;
183
+ protected canSelectButton(button: IonicActionButton): boolean;
167
184
  /** Checks if a button should show its loading spinner. */
168
- protected shouldShowSpinner(button: ActionButton): boolean;
185
+ protected shouldShowSpinner(button: IonicActionButton): boolean;
169
186
  /**
170
187
  * Handles click on a button item.
171
188
  * Emits the selected button and dismisses the popover.
172
189
  *
173
190
  * @param button - The clicked action button
174
191
  */
175
- protected onButtonClick(button: ActionButton): void;
192
+ protected onButtonClick(button: IonicActionButton): void;
176
193
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ActionButtonListComponent, never>;
177
194
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ActionButtonListComponent, "maki-action-button-list", never, { "buttons": { "alias": "buttons"; "required": false; "isSignal": true; }; }, { "buttonSelect": "buttonSelect"; }, never, never, true, never>;
178
195
  }
179
196
 
180
197
  /**
181
198
  * A configurable button component that renders an `ion-button` based on
182
- * an `ActionButton` configuration object.
199
+ * an `IonicActionButton` configuration object.
183
200
  *
184
201
  * Features:
185
202
  * - Two button types: Default and Dropdown
@@ -202,26 +219,54 @@ declare class ActionButtonListComponent {
202
219
  *
203
220
  * <!-- Dropdown button -->
204
221
  * <maki-button [button]="menuButton" />
222
+ *
223
+ * <!-- Button with tooltip -->
224
+ * <maki-button [button]="buttonWithTooltip" />
205
225
  * ```
206
226
  *
207
227
  * @example
208
228
  * ```typescript
209
229
  * // In your component
210
- * import { ActionButton, ActionButtonType } from '@makigamestudio/ui-core';
230
+ * import { ActionButtonType } from '@makigamestudio/ui-core';
211
231
  * import { IonicActionButton } from '@makigamestudio/ui-ionic';
232
+ * import { TemplateRef, ViewChild } from '@angular/core';
212
233
  *
213
- * // Generic ActionButton (loose typing)
214
- * saveButton: ActionButton = {
234
+ * // Button with string tooltip
235
+ * saveButton: IonicActionButton = {
215
236
  * id: 'save',
216
237
  * label: 'Save',
217
238
  * icon: 'save-outline',
218
239
  * type: ActionButtonType.Default,
240
+ * tooltip: 'Save your changes',
219
241
  * config: { fill: 'solid', color: 'primary' },
220
242
  * handler: async () => {
221
243
  * await this.saveData();
222
244
  * }
223
245
  * };
224
246
  *
247
+ * // Button with colored tooltip
248
+ * deleteButton: IonicActionButton = {
249
+ * id: 'delete',
250
+ * icon: 'trash-outline',
251
+ * type: ActionButtonType.Default,
252
+ * tooltip: 'Permanently delete this item',
253
+ * tooltipColor: 'danger',
254
+ * config: { fill: 'clear', color: 'danger' },
255
+ * handler: () => this.deleteItem()
256
+ * };
257
+ *
258
+ * // Button with template tooltip
259
+ * @ViewChild('richTooltip') richTooltipTemplate!: TemplateRef<unknown>;
260
+ *
261
+ * infoButton: IonicActionButton = {
262
+ * id: 'info',
263
+ * icon: 'information-circle-outline',
264
+ * type: ActionButtonType.Default,
265
+ * tooltip: this.richTooltipTemplate,
266
+ * tooltipColor: 'primary',
267
+ * handler: () => {}
268
+ * };
269
+ *
225
270
  * // IonicActionButton (strict typing for Ionic-specific config)
226
271
  * ionicButton: IonicActionButton = {
227
272
  * id: 'ionic',
@@ -234,7 +279,7 @@ declare class ActionButtonListComponent {
234
279
  * }
235
280
  * };
236
281
  *
237
- * menuButton: ActionButton = {
282
+ * menuButton: IonicActionButton = {
238
283
  * id: 'menu',
239
284
  * label: 'Actions',
240
285
  * type: ActionButtonType.Dropdown,
@@ -248,7 +293,7 @@ declare class ActionButtonListComponent {
248
293
  *
249
294
  * @usageNotes
250
295
  * ### Inputs
251
- * - `button` (required): The `ActionButton` configuration object
296
+ * - `button` (required): The `IonicActionButton` configuration object
252
297
  *
253
298
  * ### Outputs
254
299
  * - `buttonClick`: Emits the button configuration when clicked (for non-dropdown buttons)
@@ -274,11 +319,11 @@ declare class ButtonComponent {
274
319
  /** Service for handler execution. */
275
320
  private readonly handlerService;
276
321
  /** The action button configuration. */
277
- readonly button: _angular_core.InputSignal<ActionButton<void, _makigamestudio_ui_core.ActionButtonConfig<string, string, string, string, string>>>;
322
+ readonly button: _angular_core.InputSignal<IonicActionButton>;
278
323
  /** Emits when the button is clicked (for non-dropdown buttons). */
279
- readonly buttonClick: _angular_core.OutputEmitterRef<ActionButton<void, _makigamestudio_ui_core.ActionButtonConfig<string, string, string, string, string>>>;
324
+ readonly buttonClick: _angular_core.OutputEmitterRef<IonicActionButton>;
280
325
  /** Emits when a child button is selected from a dropdown. */
281
- readonly childSelect: _angular_core.OutputEmitterRef<ActionButton<void, _makigamestudio_ui_core.ActionButtonConfig<string, string, string, string, string>>>;
326
+ readonly childSelect: _angular_core.OutputEmitterRef<IonicActionButton>;
282
327
  /** Whether the button is in a loading state. */
283
328
  readonly isLoading: _angular_core.Signal<boolean>;
284
329
  /** Whether to display the loading spinner. */
@@ -310,5 +355,244 @@ declare class ButtonComponent {
310
355
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<ButtonComponent, "maki-button", never, { "button": { "alias": "button"; "required": true; "isSignal": true; }; }, { "buttonClick": "buttonClick"; "childSelect": "childSelect"; }, never, never, true, never>;
311
356
  }
312
357
 
313
- export { ActionButtonListComponent, ButtonComponent };
314
- export type { IonicActionButton, IonicActionButtonConfig, IonicButtonExpand, IonicButtonFill, IonicButtonShape, IonicButtonSize, IonicPopoverAlignment };
358
+ /**
359
+ * Directive for displaying contextual tooltips with device-aware behavior.
360
+ *
361
+ * The directive automatically adapts its behavior based on device type:
362
+ * - **Desktop**: Shows tooltip on hover after 500ms delay, hides on mouse leave
363
+ * - **Mobile**: Shows/hides tooltip on click (suppressed for interactive elements)
364
+ *
365
+ * Tooltips are positioned intelligently to avoid viewport overflow, appearing
366
+ * above or to the left of the element when necessary.
367
+ *
368
+ * @usageNotes
369
+ *
370
+ * ### Basic String Tooltip
371
+ * ```html
372
+ * <button makiTooltip="Click to save">Save</button>
373
+ * ```
374
+ *
375
+ * ### Colored Tooltip
376
+ * ```html
377
+ * <ion-button makiTooltip="Permanently delete" makiTooltipColor="danger">
378
+ * Delete
379
+ * </ion-button>
380
+ * ```
381
+ *
382
+ * ### Template Tooltip
383
+ * ```html
384
+ * <ng-template #richTooltip>
385
+ * <div class="custom-tooltip">
386
+ * <h4>Title</h4>
387
+ * <p>Description</p>
388
+ * </div>
389
+ * </ng-template>
390
+ * <div [makiTooltip]="richTooltip">Hover for details</div>
391
+ * ```
392
+ *
393
+ * ### Live Updates with Signals
394
+ * ```html
395
+ * <span [makiTooltip]="statusTooltip()">Hover</span>
396
+ * ```
397
+ * ```typescript
398
+ * readonly statusTooltip = signal('Status: Ready');
399
+ *
400
+ * // Tooltip updates live while open
401
+ * this.statusTooltip.set('Status: Processing');
402
+ * ```
403
+ *
404
+ * ### Mobile Behavior
405
+ * On mobile devices, tooltips are suppressed for interactive elements
406
+ * (button, ion-button, ion-select, a) to avoid interfering with their
407
+ * primary click handlers.
408
+ */
409
+ declare class MakiTooltipDirective implements OnDestroy {
410
+ private readonly el;
411
+ private readonly renderer;
412
+ private readonly appRef;
413
+ private readonly destroyRef;
414
+ private readonly tooltipService;
415
+ private readonly scheduler;
416
+ private readonly deviceDetection;
417
+ /**
418
+ * Tooltip content - can be a string or a template reference.
419
+ *
420
+ * If the input is signal-driven, an open tooltip will update live
421
+ * when the signal value changes.
422
+ *
423
+ * @example
424
+ * ```html
425
+ * <!-- String content -->
426
+ * <button makiTooltip="Save changes">Save</button>
427
+ *
428
+ * <!-- Template content -->
429
+ * <ng-template #tooltip>Rich content</ng-template>
430
+ * <div [makiTooltip]="tooltip">Hover</div>
431
+ * ```
432
+ */
433
+ readonly content: _angular_core.InputSignal<string | TemplateRef<unknown>>;
434
+ /**
435
+ * Optional color for the tooltip background.
436
+ * Accepts Ionic color names or null for default styling.
437
+ *
438
+ * @example
439
+ * ```html
440
+ * <button makiTooltip="Delete" makiTooltipColor="danger">Delete</button>
441
+ * ```
442
+ */
443
+ readonly color: _angular_core.InputSignal<IonicColor | null>;
444
+ /**
445
+ * Preferred tooltip placement. If provided, the directive will attempt to
446
+ * position the tooltip on the specified side before falling back.
447
+ */
448
+ readonly position: _angular_core.InputSignal<TooltipPlacement | undefined>;
449
+ /**
450
+ * Optional context object for TemplateRef tooltips.
451
+ * Supports signal inputs so templates can react to changes.
452
+ * Open tooltips update live as the context signal changes.
453
+ *
454
+ * The context is exposed as both named properties and `$implicit`.
455
+ *
456
+ * @example
457
+ * ```html
458
+ * <ng-template #tooltip let-title="title" let-data>
459
+ * <strong>{{ title }}</strong>
460
+ * <span>{{ data?.title }}</span>
461
+ * </ng-template>
462
+ * <span [makiTooltip]="tooltip" [makiTooltipContext]="{ title: 'Info' }">Hover</span>
463
+ * ```
464
+ */
465
+ readonly context: _angular_core.InputSignal<unknown>;
466
+ /**
467
+ * Reference to the tooltip DOM element.
468
+ */
469
+ private tooltip;
470
+ /**
471
+ * Timeout handle for hover delay.
472
+ */
473
+ /**
474
+ * Reference to the embedded view when using template content.
475
+ */
476
+ private viewRef;
477
+ /**
478
+ * Tracks the current template reference to detect swaps.
479
+ */
480
+ private currentTemplateRef;
481
+ /**
482
+ * Cleanup function for document touch listener.
483
+ */
484
+ private touchListenerCleanup;
485
+ /**
486
+ * Animation frame ID for tooltip follow loop.
487
+ */
488
+ private positionAnimationFrame;
489
+ /**
490
+ * Timeout handle for fade-out removal.
491
+ */
492
+ private fadeTimeout;
493
+ /**
494
+ * Scheduler handle for this directive instance (isolated timers).
495
+ * */
496
+ private readonly schedulerHandle;
497
+ /**
498
+ * Indicates whether the directive has been destroyed.
499
+ */
500
+ private isDestroyed;
501
+ /**
502
+ * Latest resolved TemplateRef context.
503
+ */
504
+ private latestTemplateContext;
505
+ constructor();
506
+ /**
507
+ * Shows tooltip on mouse enter (desktop only).
508
+ * Adds a 500ms delay to avoid showing tooltips during quick mouse movements.
509
+ */
510
+ protected onMouseEnter(): void;
511
+ protected onMouseLeave(): void;
512
+ /**
513
+ * Toggles tooltip on click (all devices).
514
+ * On mobile, skips interactive elements. On desktop, acts as a toggle.
515
+ */
516
+ protected onClick(): void;
517
+ /**
518
+ * Checks if tooltip can be shown using TooltipService logic.
519
+ *
520
+ * @returns `true` if tooltip can be shown, `false` otherwise
521
+ */
522
+ private canShowTooltip;
523
+ private resolveTemplateContext;
524
+ private unwrapSignal;
525
+ /**
526
+ * Clears the hover timeout if it exists.
527
+ */
528
+ /**
529
+ * Creates and displays the tooltip element.
530
+ *
531
+ * The tooltip is created as a fixed-position element appended to the document body.
532
+ * Content can be either plain text or a rendered template.
533
+ */
534
+ private showTooltip;
535
+ /**
536
+ * Positions the tooltip using TooltipService calculations.
537
+ */
538
+ private positionTooltip;
539
+ /**
540
+ * Adds a document-level touch listener to hide tooltip on any touch outside.
541
+ * Only used on mobile devices.
542
+ */
543
+ private addDocumentTouchListener;
544
+ /**
545
+ * Removes the document-level touch listener.
546
+ */
547
+ private removeDocumentTouchListener;
548
+ /**
549
+ * Removes the tooltip from the DOM and cleans up resources.
550
+ */
551
+ private hideTooltip;
552
+ private clearFadeTimeout;
553
+ private updateTooltipContent;
554
+ private updateTemplateContent;
555
+ private updateStringContent;
556
+ private clearTooltipContent;
557
+ /**
558
+ * Añade listeners de interacción al tooltip para mantenerlo abierto mientras se interactúa.
559
+ */
560
+ private addTooltipInteractionListeners;
561
+ /**
562
+ * Elimina listeners de interacción del tooltip.
563
+ */
564
+ private removeTooltipInteractionListeners;
565
+ /**
566
+ * Handler: mouse entra en el tooltip (desktop).
567
+ */
568
+ private readonly onTooltipMouseEnter;
569
+ /**
570
+ * Handler: mouse sale del tooltip (desktop).
571
+ */
572
+ private readonly onTooltipMouseLeave;
573
+ /**
574
+ * Handler: touchstart en el tooltip (mobile).
575
+ */
576
+ private readonly onTooltipTouchStart;
577
+ /**
578
+ * Handler: touchend en el tooltip (mobile).
579
+ */
580
+ private readonly onTooltipTouchEnd;
581
+ /**
582
+ * Starts a high-performance animation frame loop to keep the tooltip positioned with its trigger.
583
+ */
584
+ private startTooltipFollowLoop;
585
+ /**
586
+ * Stops the animation frame loop for tooltip positioning.
587
+ */
588
+ private stopTooltipFollowLoop;
589
+ /**
590
+ * Cleanup on directive destruction.
591
+ */
592
+ ngOnDestroy(): void;
593
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MakiTooltipDirective, never>;
594
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MakiTooltipDirective, "[makiTooltip]", never, { "content": { "alias": "makiTooltip"; "required": true; "isSignal": true; }; "color": { "alias": "makiTooltipColor"; "required": false; "isSignal": true; }; "position": { "alias": "makiTooltipPosition"; "required": false; "isSignal": true; }; "context": { "alias": "makiTooltipContext"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
595
+ }
596
+
597
+ export { ActionButtonListComponent, ButtonComponent, MakiTooltipDirective };
598
+ export type { IonicActionButton, IonicActionButtonConfig, IonicButtonExpand, IonicButtonFill, IonicButtonShape, IonicButtonSize, IonicColor, IonicPopoverAlignment };