@marianmeres/stuic 2.25.0 → 2.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
import type { THC } from "../../components/Thc/Thc.svelte";
|
|
2
2
|
import "./index.css";
|
|
3
|
+
/**
|
|
4
|
+
* Open a popover by its registered ID.
|
|
5
|
+
*
|
|
6
|
+
* @param id - The popover ID to open
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```svelte
|
|
10
|
+
* <script>
|
|
11
|
+
* import { openPopover } from './';
|
|
12
|
+
* </script>
|
|
13
|
+
* <button onclick={() => openPopover('my-popover')}>Open</button>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function openPopover(id: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Close a popover by its registered ID.
|
|
19
|
+
*
|
|
20
|
+
* @param id - The popover ID to close
|
|
21
|
+
*/
|
|
22
|
+
export declare function closePopover(id: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Toggle a popover by its registered ID.
|
|
25
|
+
*
|
|
26
|
+
* @param id - The popover ID to toggle
|
|
27
|
+
*/
|
|
28
|
+
export declare function togglePopover(id: string): void;
|
|
3
29
|
/**
|
|
4
30
|
* Checks if the browser supports CSS Anchor Positioning for popovers.
|
|
5
31
|
*
|
|
@@ -67,6 +93,8 @@ export interface PopoverOptions {
|
|
|
67
93
|
debug?: boolean;
|
|
68
94
|
/** Programmatically control open state (reactive) */
|
|
69
95
|
open?: boolean;
|
|
96
|
+
/** Unique ID for registry-based programmatic control (use with openPopover/closePopover/togglePopover) */
|
|
97
|
+
id?: string;
|
|
70
98
|
}
|
|
71
99
|
/**
|
|
72
100
|
* A Svelte action that displays a popover anchored to an element using CSS Anchor Positioning.
|
|
@@ -6,6 +6,54 @@ import PopoverContent from "./PopoverContent.svelte";
|
|
|
6
6
|
import "./index.css";
|
|
7
7
|
// Registry of open popover hide functions for closeOthers feature
|
|
8
8
|
const openPopovers = new Set();
|
|
9
|
+
// Registry of popovers by ID for programmatic control
|
|
10
|
+
const popoverRegistry = new Map();
|
|
11
|
+
// Track if an open was just requested (to prevent same-click outside close)
|
|
12
|
+
let openRequestedThisCycle = false;
|
|
13
|
+
/**
|
|
14
|
+
* Open a popover by its registered ID.
|
|
15
|
+
*
|
|
16
|
+
* @param id - The popover ID to open
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```svelte
|
|
20
|
+
* <script>
|
|
21
|
+
* import { openPopover } from './';
|
|
22
|
+
* </script>
|
|
23
|
+
* <button onclick={() => openPopover('my-popover')}>Open</button>
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function openPopover(id) {
|
|
27
|
+
const entry = popoverRegistry.get(id);
|
|
28
|
+
if (entry) {
|
|
29
|
+
openRequestedThisCycle = true;
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
openRequestedThisCycle = false;
|
|
32
|
+
}, 0);
|
|
33
|
+
// Close all other open popovers first
|
|
34
|
+
openPopovers.forEach((hideFn) => {
|
|
35
|
+
if (hideFn !== entry.hide)
|
|
36
|
+
hideFn();
|
|
37
|
+
});
|
|
38
|
+
entry.show();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Close a popover by its registered ID.
|
|
43
|
+
*
|
|
44
|
+
* @param id - The popover ID to close
|
|
45
|
+
*/
|
|
46
|
+
export function closePopover(id) {
|
|
47
|
+
popoverRegistry.get(id)?.hide();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Toggle a popover by its registered ID.
|
|
51
|
+
*
|
|
52
|
+
* @param id - The popover ID to toggle
|
|
53
|
+
*/
|
|
54
|
+
export function togglePopover(id) {
|
|
55
|
+
popoverRegistry.get(id)?.toggle();
|
|
56
|
+
}
|
|
9
57
|
const SHOW_DELAY = 100;
|
|
10
58
|
const HIDE_DELAY = 200;
|
|
11
59
|
const TRANSITION = 200;
|
|
@@ -201,11 +249,20 @@ export function popover(anchorEl, fn) {
|
|
|
201
249
|
if (popoverEl &&
|
|
202
250
|
!popoverEl.contains(e.target) &&
|
|
203
251
|
!anchorEl.contains(e.target)) {
|
|
252
|
+
// Skip if an open was just requested via registry (same click event)
|
|
253
|
+
if (openRequestedThisCycle) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
204
256
|
hide();
|
|
205
257
|
}
|
|
206
258
|
}
|
|
207
259
|
function onClickTrigger(e) {
|
|
208
260
|
e.stopPropagation();
|
|
261
|
+
// Close all other open popovers (since stopPropagation prevents onClickOutside from firing)
|
|
262
|
+
openPopovers.forEach((hideFn) => {
|
|
263
|
+
if (hideFn !== hide)
|
|
264
|
+
hideFn();
|
|
265
|
+
});
|
|
209
266
|
if (isVisible)
|
|
210
267
|
hide();
|
|
211
268
|
else
|
|
@@ -409,8 +466,22 @@ export function popover(anchorEl, fn) {
|
|
|
409
466
|
onShow: opts.onShow,
|
|
410
467
|
onHide: opts.onHide,
|
|
411
468
|
debug: opts.debug,
|
|
469
|
+
id: opts.id,
|
|
412
470
|
};
|
|
413
471
|
do_debug = !!opts.debug;
|
|
472
|
+
// Register in global registry if id provided
|
|
473
|
+
if (opts.id) {
|
|
474
|
+
popoverRegistry.set(opts.id, {
|
|
475
|
+
show,
|
|
476
|
+
hide,
|
|
477
|
+
toggle: () => {
|
|
478
|
+
if (isVisible)
|
|
479
|
+
hide();
|
|
480
|
+
else
|
|
481
|
+
show();
|
|
482
|
+
},
|
|
483
|
+
});
|
|
484
|
+
}
|
|
414
485
|
// Update popover if visible
|
|
415
486
|
if (isVisible && popoverEl) {
|
|
416
487
|
// Update position (only in anchor positioning mode)
|
|
@@ -473,6 +544,10 @@ export function popover(anchorEl, fn) {
|
|
|
473
544
|
clearTimers();
|
|
474
545
|
// Unregister from open popovers
|
|
475
546
|
openPopovers.delete(hide);
|
|
547
|
+
// Unregister from popover registry
|
|
548
|
+
if (currentOptions.id) {
|
|
549
|
+
popoverRegistry.delete(currentOptions.id);
|
|
550
|
+
}
|
|
476
551
|
document.removeEventListener("keydown", onEscape);
|
|
477
552
|
document.removeEventListener("click", onClickOutside);
|
|
478
553
|
};
|
|
@@ -43,8 +43,9 @@
|
|
|
43
43
|
border-button-border dark:border-button-border-dark
|
|
44
44
|
rounded-md
|
|
45
45
|
inline-flex items-center justify-center gap-x-2
|
|
46
|
-
px-
|
|
46
|
+
px-4 py-3
|
|
47
47
|
select-none
|
|
48
|
+
min-h-[44px] min-w-[44px]
|
|
48
49
|
|
|
49
50
|
hover:brightness-105
|
|
50
51
|
active:brightness-95
|
|
@@ -59,7 +60,7 @@
|
|
|
59
60
|
|
|
60
61
|
export const BUTTON_STUIC_PRESET_CLASSES: ButtonPresetClasses = {
|
|
61
62
|
size: {
|
|
62
|
-
sm: `text-sm rounded-sm px-
|
|
63
|
+
sm: `text-sm rounded-sm px-3 py-2 min-h-none min-w-none`,
|
|
63
64
|
lg: `text-base rounded-md`,
|
|
64
65
|
},
|
|
65
66
|
variant: {
|
|
@@ -31,7 +31,7 @@ export interface ButtonPresetClasses {
|
|
|
31
31
|
shadow: string;
|
|
32
32
|
inverse: string;
|
|
33
33
|
}
|
|
34
|
-
export declare const BUTTON_STUIC_BASE_CLASSES = "\n\t\tbg-button-bg text-button-text\n\t\tdark:bg-button-bg-dark dark:text-button-text-dark\n\t\tfont-mono text-sm text-center\n\t\tleading-none\n\t\tborder-1\n\t\tborder-button-border dark:border-button-border-dark\n\t\trounded-md\n\t\tinline-flex items-center justify-center gap-x-2\n\t\tpx-
|
|
34
|
+
export declare const BUTTON_STUIC_BASE_CLASSES = "\n\t\tbg-button-bg text-button-text\n\t\tdark:bg-button-bg-dark dark:text-button-text-dark\n\t\tfont-mono text-sm text-center\n\t\tleading-none\n\t\tborder-1\n\t\tborder-button-border dark:border-button-border-dark\n\t\trounded-md\n\t\tinline-flex items-center justify-center gap-x-2\n\t\tpx-4 py-3\n\t\tselect-none\n\t\tmin-h-[44px] min-w-[44px]\n\n\t\thover:brightness-105\n\t\tactive:brightness-95\n\t\tdisabled:hover:brightness-100 disabled:opacity-50\n\n\t\tfocus:brightness-105\n\t\tfocus:border-button-border-focus focus:dark:border-button-border-focus-dark\n\n\t\t focus:outline-4 focus:outline-black/10 focus:dark:outline-white/20\n\t\tfocus-visible:outline-4 focus-visible:outline-black/10 focus-visible:dark:outline-white/20\n\t";
|
|
35
35
|
export declare const BUTTON_STUIC_PRESET_CLASSES: ButtonPresetClasses;
|
|
36
36
|
import "./index.css";
|
|
37
37
|
import { type TooltipConfig } from "../../actions/index.js";
|