@marianmeres/stuic 2.19.0 → 2.21.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.
@@ -24,8 +24,11 @@ export declare function isPopoverSupported(): boolean;
24
24
  export type PopoverPosition = "top" | "top-left" | "top-right" | "top-span-left" | "top-span-right" | "bottom" | "bottom-left" | "bottom-right" | "bottom-span-left" | "bottom-span-right" | "left" | "right";
25
25
  /**
26
26
  * Trigger mode for the popover.
27
+ * - "click": Opens/closes on click (default)
28
+ * - "hover": Opens on hover/focus, closes on leave/blur
29
+ * - "hover-or-click": Hover primary, click as fallback (for touch devices)
27
30
  */
28
- export type PopoverTrigger = "click" | "hover";
31
+ export type PopoverTrigger = "click" | "hover" | "hover-or-click";
29
32
  /**
30
33
  * Options for the popover action.
31
34
  */
@@ -36,7 +39,7 @@ export interface PopoverOptions {
36
39
  content?: THC | null;
37
40
  /** Preferred position relative to anchor */
38
41
  position?: PopoverPosition;
39
- /** Trigger mode: "click" (default) or "hover" */
42
+ /** Trigger mode: "click" (default), "hover", or "hover-or-click" (both, click as touch fallback) */
40
43
  trigger?: PopoverTrigger;
41
44
  /** Delay before showing (ms), mainly for hover mode */
42
45
  showDelay?: number;
@@ -95,6 +98,18 @@ export interface PopoverOptions {
95
98
  *
96
99
  * @example
97
100
  * ```svelte
101
+ * <!-- Hover with click fallback (for touch devices) -->
102
+ * <button use:popover={() => ({
103
+ * content: "Works on hover and touch!",
104
+ * trigger: "hover-or-click",
105
+ * position: "top"
106
+ * })}>
107
+ * Hover or Tap
108
+ * </button>
109
+ * ```
110
+ *
111
+ * @example
112
+ * ```svelte
98
113
  * <!-- With component content -->
99
114
  * <button use:popover={() => ({
100
115
  * content: { component: MyComponent, props: { foo: "bar" } }
@@ -117,6 +117,18 @@ function getStringContent(content) {
117
117
  *
118
118
  * @example
119
119
  * ```svelte
120
+ * <!-- Hover with click fallback (for touch devices) -->
121
+ * <button use:popover={() => ({
122
+ * content: "Works on hover and touch!",
123
+ * trigger: "hover-or-click",
124
+ * position: "top"
125
+ * })}>
126
+ * Hover or Tap
127
+ * </button>
128
+ * ```
129
+ *
130
+ * @example
131
+ * ```svelte
120
132
  * <!-- With component content -->
121
133
  * <button use:popover={() => ({
122
134
  * content: { component: MyComponent, props: { foo: "bar" } }
@@ -191,11 +203,18 @@ export function popover(anchorEl, fn) {
191
203
  }
192
204
  function onClickTrigger(e) {
193
205
  e.stopPropagation();
194
- if (isVisible) {
195
- hide();
206
+ const trigger = currentOptions.trigger || "click";
207
+ if (trigger === "hover-or-click") {
208
+ // Click only opens, doesn't close (fallback for touch)
209
+ if (!isVisible)
210
+ show();
196
211
  }
197
212
  else {
198
- show();
213
+ // Normal click toggle behavior
214
+ if (isVisible)
215
+ hide();
216
+ else
217
+ show();
199
218
  }
200
219
  }
201
220
  // Render content into popover element
@@ -324,10 +343,8 @@ export function popover(anchorEl, fn) {
324
343
  popoverEl.addEventListener("mouseenter", cancelHide);
325
344
  popoverEl.addEventListener("mouseleave", scheduleHide);
326
345
  }
327
- // For click mode with closeOnClickOutside
328
- if (currentOptions.trigger === "click" &&
329
- currentOptions.closeOnClickOutside !== false &&
330
- useAnchorPositioning) {
346
+ // For click or hover mode with closeOnClickOutside
347
+ if (currentOptions.closeOnClickOutside !== false && useAnchorPositioning) {
331
348
  // Delay adding click listener to avoid immediate close
332
349
  setTimeout(() => {
333
350
  document.addEventListener("click", onClickOutside);
@@ -418,12 +435,19 @@ export function popover(anchorEl, fn) {
418
435
  if (trigger === "click") {
419
436
  anchorEl.addEventListener("click", onClickTrigger);
420
437
  }
421
- else {
422
- // hover mode
438
+ else if (trigger === "hover") {
439
+ anchorEl.addEventListener("mouseenter", scheduleShow);
440
+ anchorEl.addEventListener("mouseleave", scheduleHide);
441
+ anchorEl.addEventListener("focus", scheduleShow);
442
+ anchorEl.addEventListener("blur", scheduleHide);
443
+ }
444
+ else if (trigger === "hover-or-click") {
445
+ // Both: hover primary, click fallback for touch
423
446
  anchorEl.addEventListener("mouseenter", scheduleShow);
424
447
  anchorEl.addEventListener("mouseleave", scheduleHide);
425
448
  anchorEl.addEventListener("focus", scheduleShow);
426
449
  anchorEl.addEventListener("blur", scheduleHide);
450
+ anchorEl.addEventListener("click", onClickTrigger);
427
451
  }
428
452
  return () => {
429
453
  anchorEl.removeEventListener("click", onClickTrigger);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "2.19.0",
3
+ "version": "2.21.0",
4
4
  "files": [
5
5
  "dist",
6
6
  "!dist/**/*.test.*",