epic-modals 0.0.4
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.
- package/LICENSE +93 -0
- package/README.md +287 -0
- package/dist/core/config.svelte.d.ts +85 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/stacking.svelte.d.ts +19 -0
- package/dist/core/state.svelte.d.ts +321 -0
- package/dist/core/types.d.ts +98 -0
- package/dist/core/viewport.d.ts +92 -0
- package/dist/core/viewport.test.d.ts +2 -0
- package/dist/epic-modals.css +9 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/react/Dock.d.ts +13 -0
- package/dist/react/Modal.d.ts +11 -0
- package/dist/react/ModalProvider.d.ts +11 -0
- package/dist/react/context.d.ts +4 -0
- package/dist/react/index.d.ts +15 -0
- package/dist/react/svelte-bridge.d.ts +18 -0
- package/dist/react/useModal.d.ts +27 -0
- package/dist/react/useModalZIndex.d.ts +35 -0
- package/dist/react.d.ts +11 -0
- package/dist/react.js +1 -0
- package/dist/styles/animations.css +1 -0
- package/dist/styles/dock.css +1 -0
- package/dist/styles/index.css +1 -0
- package/dist/styles/modal.css +1 -0
- package/dist/styles/themes/dark.css +1 -0
- package/dist/styles/themes/light.css +1 -0
- package/dist/styles/variables.css +1 -0
- package/dist/svelte/context.d.ts +8 -0
- package/dist/svelte/hooks/index.d.ts +13 -0
- package/dist/svelte/hooks/useFocusTrap.svelte.d.ts +20 -0
- package/dist/svelte/hooks/useModal.svelte.d.ts +41 -0
- package/dist/svelte/hooks/useModalAnimation.svelte.d.ts +16 -0
- package/dist/svelte/hooks/useModalDrag.svelte.d.ts +16 -0
- package/dist/svelte/hooks/useModalResize.svelte.d.ts +18 -0
- package/dist/svelte/hooks/useModalZIndex.svelte.d.ts +30 -0
- package/dist/svelte/hooks/usePortal.svelte.d.ts +13 -0
- package/dist/svelte/hooks/useWindowEvent.svelte.d.ts +12 -0
- package/dist/svelte/index.d.ts +14 -0
- package/dist/svelte.d.ts +10 -0
- package/dist/svelte.js +1 -0
- package/dist/vanilla/index.d.ts +51 -0
- package/dist/vanilla.d.ts +10 -0
- package/dist/vanilla.js +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { ModalState, ModalId, Position, Dimensions, AnimationTransform } from './types';
|
|
2
|
+
/** URL state callbacks for browser integration */
|
|
3
|
+
interface URLStateCallbacks {
|
|
4
|
+
push: (id: ModalId) => void;
|
|
5
|
+
replace: (id: ModalId) => void;
|
|
6
|
+
pop: () => void;
|
|
7
|
+
}
|
|
8
|
+
/** Dock position getter function */
|
|
9
|
+
type DockPositionGetter = () => {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
|
15
|
+
/** Modal registry interface for static modal lookup (kept for API compatibility) */
|
|
16
|
+
interface ModalRegistry {
|
|
17
|
+
has(id: ModalId): boolean;
|
|
18
|
+
get(id: ModalId): {
|
|
19
|
+
title: string;
|
|
20
|
+
icon: string;
|
|
21
|
+
closeOnOutsideClick?: boolean;
|
|
22
|
+
} | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Store type for modals collection */
|
|
25
|
+
export type ModalsStore = ReturnType<typeof createModalsStore>;
|
|
26
|
+
/**
|
|
27
|
+
* Subscribe to state changes (for React integration)
|
|
28
|
+
* @returns Unsubscribe function
|
|
29
|
+
*/
|
|
30
|
+
export declare function subscribe(callback: () => void): () => void;
|
|
31
|
+
declare function createModalsStore(): {
|
|
32
|
+
readonly modals: Map<ModalId, ModalState>;
|
|
33
|
+
readonly pendingMinimize: ModalId[];
|
|
34
|
+
readonly pendingOpen: ModalId[];
|
|
35
|
+
readonly pendingClose: ModalId[];
|
|
36
|
+
readonly pendingRestore: ModalId[];
|
|
37
|
+
readonly dockOrder: ModalId[];
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Register a new modal in the system
|
|
41
|
+
* If modal already exists, merges new props with existing state to preserve
|
|
42
|
+
* saved position, size, and other runtime state
|
|
43
|
+
*/
|
|
44
|
+
export declare function registerModal(modal: Omit<ModalState, 'zIndex' | 'isAnimating'>): void;
|
|
45
|
+
/**
|
|
46
|
+
* Unregister a modal from the system
|
|
47
|
+
*/
|
|
48
|
+
export declare function unregisterModal(id: ModalId): void;
|
|
49
|
+
/**
|
|
50
|
+
* Minimize a modal with genie animation to dock
|
|
51
|
+
* If this is a child modal, redirects to minimize parent (they act as unit)
|
|
52
|
+
* Both parent and child minimize together
|
|
53
|
+
*/
|
|
54
|
+
export declare function minimizeModal(id: ModalId): void;
|
|
55
|
+
/**
|
|
56
|
+
* Restore a minimized modal from dock
|
|
57
|
+
* Also restores child modal if one was hidden with parent
|
|
58
|
+
*/
|
|
59
|
+
export declare function restoreModal(id: ModalId): void;
|
|
60
|
+
/**
|
|
61
|
+
* Restore all minimized modals (called when dock feature is disabled)
|
|
62
|
+
*/
|
|
63
|
+
export declare function restoreAllMinimizedModals(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Restore a child modal that was hidden with parent
|
|
66
|
+
*/
|
|
67
|
+
export declare function restoreChildModal(id: ModalId): void;
|
|
68
|
+
/**
|
|
69
|
+
* Update modal position (called during drag)
|
|
70
|
+
* Also syncs linked modal positions:
|
|
71
|
+
* - If this modal has a child, the child moves with it
|
|
72
|
+
* - If this modal is a child, the parent moves with it
|
|
73
|
+
*/
|
|
74
|
+
export declare function updateModalPosition(id: ModalId, position: Position, options?: {
|
|
75
|
+
constrain?: boolean;
|
|
76
|
+
drag?: boolean;
|
|
77
|
+
size?: Dimensions;
|
|
78
|
+
}): void;
|
|
79
|
+
/**
|
|
80
|
+
* Update modal size
|
|
81
|
+
*/
|
|
82
|
+
export declare function updateModalSize(id: ModalId, size: Dimensions): void;
|
|
83
|
+
/**
|
|
84
|
+
* Update multiple modal properties at once
|
|
85
|
+
*/
|
|
86
|
+
export declare function updateModal(id: ModalId, updates: Partial<ModalState>): void;
|
|
87
|
+
/**
|
|
88
|
+
* Bring a modal to the front (highest z-index)
|
|
89
|
+
* Maintains parent-child z-index relationship: child always above parent
|
|
90
|
+
*/
|
|
91
|
+
export declare function bringToFront(id: ModalId): void;
|
|
92
|
+
/**
|
|
93
|
+
* Check if a modal is the top-most modal
|
|
94
|
+
*/
|
|
95
|
+
export declare function isTopModal(id: ModalId): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Reorder dock items (drag and drop)
|
|
98
|
+
*/
|
|
99
|
+
export declare function reorderDock(newOrder: ModalId[]): void;
|
|
100
|
+
/**
|
|
101
|
+
* Open a modal by ID (for already-registered modals)
|
|
102
|
+
*
|
|
103
|
+
* @param id - Modal ID to open
|
|
104
|
+
* @param sourceElement - Source element for genie animation. REQUIRED - the animation
|
|
105
|
+
* needs a source position to animate from. For modals that open without user interaction,
|
|
106
|
+
* use the `autoOpen` prop on the Modal component instead.
|
|
107
|
+
* @param options - Optional settings like parentId for child modals
|
|
108
|
+
*/
|
|
109
|
+
export interface OpenModalOptions {
|
|
110
|
+
/** Parent modal ID to link this modal as a child */
|
|
111
|
+
parentId?: ModalId;
|
|
112
|
+
}
|
|
113
|
+
export declare function openModal(id: ModalId, sourceElement: HTMLElement, options?: OpenModalOptions): void;
|
|
114
|
+
/**
|
|
115
|
+
* Create and open a new modal (registers and opens in one call)
|
|
116
|
+
* @param modal - Full modal state to register and open
|
|
117
|
+
*/
|
|
118
|
+
export declare function createModal(modal: Omit<ModalState, 'zIndex' | 'isAnimating'>): void;
|
|
119
|
+
/**
|
|
120
|
+
* Close a modal
|
|
121
|
+
*/
|
|
122
|
+
export declare function closeModal(id: ModalId, force?: boolean): void;
|
|
123
|
+
/**
|
|
124
|
+
* Close all modals
|
|
125
|
+
*/
|
|
126
|
+
export declare function closeAllModals(): void;
|
|
127
|
+
/**
|
|
128
|
+
* Finalize modal close after animation completes
|
|
129
|
+
* Resets modal to minimal closed state to free memory (position, size, etc.)
|
|
130
|
+
* but keeps registration so the modal can be reopened
|
|
131
|
+
*/
|
|
132
|
+
export declare function finalizeModalClose(id: ModalId): void;
|
|
133
|
+
/**
|
|
134
|
+
* Get list of modals to close (for cascade)
|
|
135
|
+
*/
|
|
136
|
+
export declare function getModalsToClose(fromId: ModalId): ModalId[];
|
|
137
|
+
/**
|
|
138
|
+
* Open a child modal linked to a parent
|
|
139
|
+
*/
|
|
140
|
+
export declare function openChildModal(child: {
|
|
141
|
+
id: ModalId;
|
|
142
|
+
} & Partial<Omit<ModalState, 'zIndex' | 'isAnimating' | 'parentId'>>, parentId: ModalId, sourceElement?: HTMLElement): void;
|
|
143
|
+
/**
|
|
144
|
+
* Link two modals as parent-child
|
|
145
|
+
* Calculates and stores the offset from parent position for linked movement
|
|
146
|
+
*/
|
|
147
|
+
export declare function linkModals(parentId: ModalId, childId: ModalId): void;
|
|
148
|
+
/**
|
|
149
|
+
* Hide a child modal when its parent is minimized
|
|
150
|
+
*/
|
|
151
|
+
export declare function hideChildWithParent(parentId: ModalId): void;
|
|
152
|
+
/**
|
|
153
|
+
* Update child modal position when parent moves
|
|
154
|
+
* Maintains the offsetFromParent relationship
|
|
155
|
+
*/
|
|
156
|
+
export declare function updateChildPosition(parentId: ModalId, parentPosition: Position): void;
|
|
157
|
+
/**
|
|
158
|
+
* Calculate and set child's offset from parent
|
|
159
|
+
* Called when child modal is first opened centered on parent
|
|
160
|
+
*/
|
|
161
|
+
export declare function setChildOffsetFromParent(childId: ModalId, parentId: ModalId): void;
|
|
162
|
+
/** Check if modal has pending minimize */
|
|
163
|
+
export declare function hasPendingMinimize(id: ModalId): boolean;
|
|
164
|
+
/** Consume pending minimize flag */
|
|
165
|
+
export declare function consumePendingMinimize(id: ModalId): boolean;
|
|
166
|
+
/** Check if any modal has pending minimize */
|
|
167
|
+
export declare function hasAnyPendingMinimize(): boolean;
|
|
168
|
+
/** Get all registered modal IDs */
|
|
169
|
+
export declare function getRegisteredModalIds(): ModalId[];
|
|
170
|
+
/** Get modal state */
|
|
171
|
+
export declare function getModalState(id: ModalId): ModalState | undefined;
|
|
172
|
+
/**
|
|
173
|
+
* Get bounds of all open, visible modals with their IDs (for rearrangement).
|
|
174
|
+
* Excludes minimized modals and the modal being positioned.
|
|
175
|
+
* Returns bounds from DOM if position/size not tracked in state.
|
|
176
|
+
*/
|
|
177
|
+
export declare function getOpenModalBoundsWithIds(excludeId?: ModalId): Array<{
|
|
178
|
+
id: string;
|
|
179
|
+
x: number;
|
|
180
|
+
y: number;
|
|
181
|
+
width: number;
|
|
182
|
+
height: number;
|
|
183
|
+
}>;
|
|
184
|
+
/**
|
|
185
|
+
* Get bounds of all open, visible modals (for smart positioning).
|
|
186
|
+
* Excludes minimized modals and the modal being positioned.
|
|
187
|
+
* Returns bounds from DOM if position/size not tracked in state.
|
|
188
|
+
*/
|
|
189
|
+
export declare function getOpenModalBounds(excludeId?: ModalId): Array<{
|
|
190
|
+
x: number;
|
|
191
|
+
y: number;
|
|
192
|
+
width: number;
|
|
193
|
+
height: number;
|
|
194
|
+
}>;
|
|
195
|
+
/** Get state version for reactive tracking in components */
|
|
196
|
+
export declare function getStateVersion(): number;
|
|
197
|
+
/** Consume pending minimize target */
|
|
198
|
+
export declare function consumePendingMinimizeTarget(): AnimationTransform | null;
|
|
199
|
+
/** Check if modal has pending open */
|
|
200
|
+
export declare function hasPendingOpen(id: ModalId): boolean;
|
|
201
|
+
/** Consume pending open flag */
|
|
202
|
+
export declare function consumePendingOpen(id: ModalId): boolean;
|
|
203
|
+
/** Check if modal has pending close */
|
|
204
|
+
export declare function hasPendingClose(id: ModalId): boolean;
|
|
205
|
+
/** Consume pending close flag */
|
|
206
|
+
export declare function consumePendingClose(id: ModalId): boolean;
|
|
207
|
+
/** Check if modal has pending force close */
|
|
208
|
+
export declare function hasPendingForceClose(id: ModalId): boolean;
|
|
209
|
+
/** Consume pending force close flag */
|
|
210
|
+
export declare function consumePendingForceClose(id: ModalId): boolean;
|
|
211
|
+
/** Check if modal has pending restore */
|
|
212
|
+
export declare function hasPendingRestore(id: ModalId): boolean;
|
|
213
|
+
/** Consume pending restore flag */
|
|
214
|
+
export declare function consumePendingRestore(id: ModalId): boolean;
|
|
215
|
+
/** Check if modal has pending child restore */
|
|
216
|
+
export declare function hasPendingChildRestore(id: ModalId): boolean;
|
|
217
|
+
/** Consume pending child restore flag */
|
|
218
|
+
export declare function consumePendingChildRestore(id: ModalId): boolean;
|
|
219
|
+
/** Check if modal has pending attention (shake/glow effect) */
|
|
220
|
+
export declare function hasPendingAttention(id: ModalId): boolean;
|
|
221
|
+
/** Consume pending attention flag */
|
|
222
|
+
export declare function consumePendingAttention(id: ModalId): boolean;
|
|
223
|
+
/** Trigger attention effect on a modal (shake + glow) */
|
|
224
|
+
export declare function triggerAttention(id: ModalId): void;
|
|
225
|
+
/** Start attention animation (called when animation begins) */
|
|
226
|
+
export declare function startAttentionAnimation(id: ModalId): void;
|
|
227
|
+
/** End attention animation (called when animation completes) */
|
|
228
|
+
export declare function endAttentionAnimation(id: ModalId): void;
|
|
229
|
+
/** Get pending parent link (without consuming) */
|
|
230
|
+
export declare function getPendingParentLink(): {
|
|
231
|
+
parentId: ModalId;
|
|
232
|
+
childId: ModalId;
|
|
233
|
+
} | null;
|
|
234
|
+
/** Consume pending parent link for a specific child */
|
|
235
|
+
export declare function consumePendingParentLink(childId: ModalId): {
|
|
236
|
+
parentId: ModalId;
|
|
237
|
+
childId: ModalId;
|
|
238
|
+
} | null;
|
|
239
|
+
/** Store source position for open animation */
|
|
240
|
+
export declare function storeOpenSourcePosition(id: ModalId, pos: Position): void;
|
|
241
|
+
/** Consume open source position for a specific modal */
|
|
242
|
+
export declare function consumeOpenSourcePosition(id: ModalId): Position | null;
|
|
243
|
+
/** Set modal animating state */
|
|
244
|
+
export declare function setModalAnimating(id: ModalId, animating: boolean): void;
|
|
245
|
+
/** Check if modal is animating */
|
|
246
|
+
export declare function isModalAnimating(id: ModalId): boolean;
|
|
247
|
+
/** Check if modal is open (not minimized and not hidden) */
|
|
248
|
+
export declare function isModalOpen(id: ModalId): boolean;
|
|
249
|
+
/** Check if modal is registered */
|
|
250
|
+
export declare function isModalRegistered(id: ModalId): boolean;
|
|
251
|
+
/** Get store reference */
|
|
252
|
+
export declare function getModalsStore(): ModalsStore;
|
|
253
|
+
/** Toggle modal transparency */
|
|
254
|
+
export declare function toggleModalTransparency(id: ModalId): void;
|
|
255
|
+
/** Reset modal transparency */
|
|
256
|
+
export declare function resetModalTransparency(id: ModalId): void;
|
|
257
|
+
/**
|
|
258
|
+
* Shake element (visual feedback for invalid actions)
|
|
259
|
+
*/
|
|
260
|
+
export declare function shakeElement(element: HTMLElement): void;
|
|
261
|
+
/**
|
|
262
|
+
* Animate parent modal to its target position (for animated movement mode)
|
|
263
|
+
*/
|
|
264
|
+
export declare function animateParentToPosition(parentId: ModalId): void;
|
|
265
|
+
/**
|
|
266
|
+
* Clear the animation flag after animation completes
|
|
267
|
+
*/
|
|
268
|
+
export declare function clearParentAnimationFlag(parentId: ModalId): void;
|
|
269
|
+
/**
|
|
270
|
+
* Check if parent has a pending animation
|
|
271
|
+
*/
|
|
272
|
+
export declare function hasPendingParentAnimation(parentId: ModalId): boolean;
|
|
273
|
+
/**
|
|
274
|
+
* Clear pending parent animation
|
|
275
|
+
*/
|
|
276
|
+
export declare function clearPendingParentAnimation(parentId: ModalId): void;
|
|
277
|
+
/**
|
|
278
|
+
* Move multiple modals to new positions with animation.
|
|
279
|
+
* Uses the same animation mechanism as parent-child movement.
|
|
280
|
+
* @param moves - Map of modal IDs to their target positions
|
|
281
|
+
*/
|
|
282
|
+
export declare function animateModalsToPositions(moves: Map<ModalId, Position>): void;
|
|
283
|
+
/**
|
|
284
|
+
* Trigger cascading parent animations up the chain.
|
|
285
|
+
* Each parent animates after the previous one finishes, creating a waterfall effect.
|
|
286
|
+
* Positions are recalculated dynamically at animation time based on the child's current position.
|
|
287
|
+
* @param childId - The ID of the modal that was dragged
|
|
288
|
+
*/
|
|
289
|
+
export declare function triggerCascadingParentAnimations(childId: ModalId): void;
|
|
290
|
+
/**
|
|
291
|
+
* Set registry functions for static modal lookup
|
|
292
|
+
* NOTE: Currently unused but kept for API compatibility
|
|
293
|
+
*/
|
|
294
|
+
export declare function setRegistryFunctions(_registry: ModalRegistry): void;
|
|
295
|
+
/**
|
|
296
|
+
* Set URL state callbacks for browser integration
|
|
297
|
+
*/
|
|
298
|
+
export declare function setURLStateCallbacks(callbacks: URLStateCallbacks): void;
|
|
299
|
+
/**
|
|
300
|
+
* Set dock position getter for animations
|
|
301
|
+
*/
|
|
302
|
+
export declare function setDockPositionGetter(getter: DockPositionGetter): void;
|
|
303
|
+
/**
|
|
304
|
+
* Get internal state (for testing only)
|
|
305
|
+
*/
|
|
306
|
+
export declare function _getInternalState(): {
|
|
307
|
+
modals: Map<ModalId, ModalState>;
|
|
308
|
+
pendingMinimize: ModalId[];
|
|
309
|
+
pendingOpen: ModalId[];
|
|
310
|
+
pendingClose: ModalId[];
|
|
311
|
+
pendingRestore: ModalId[];
|
|
312
|
+
dockOrder: ModalId[];
|
|
313
|
+
animatingModals: Set<ModalId>;
|
|
314
|
+
transparentModals: Set<ModalId>;
|
|
315
|
+
};
|
|
316
|
+
/**
|
|
317
|
+
* Reset internal state (for testing only)
|
|
318
|
+
*/
|
|
319
|
+
export declare function _resetInternalState(): void;
|
|
320
|
+
export {};
|
|
321
|
+
//# sourceMappingURL=state.svelte.d.ts.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for the modal library
|
|
3
|
+
*/
|
|
4
|
+
export type ModalId = string | symbol;
|
|
5
|
+
export interface Position {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
}
|
|
9
|
+
export interface Dimensions {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
}
|
|
13
|
+
export interface Bounds extends Position, Dimensions {
|
|
14
|
+
}
|
|
15
|
+
export interface ModalGlow {
|
|
16
|
+
color: string;
|
|
17
|
+
intensity: 'low' | 'medium' | 'high';
|
|
18
|
+
}
|
|
19
|
+
export interface ModalState {
|
|
20
|
+
id: ModalId;
|
|
21
|
+
title: string;
|
|
22
|
+
icon: string;
|
|
23
|
+
isOpen: boolean;
|
|
24
|
+
isMinimized: boolean;
|
|
25
|
+
isHiddenWithParent: boolean;
|
|
26
|
+
isTransparent: boolean;
|
|
27
|
+
isAnimating: boolean;
|
|
28
|
+
isAnimatingPosition?: boolean;
|
|
29
|
+
isRejected: boolean;
|
|
30
|
+
zIndex: number;
|
|
31
|
+
position: Position | null;
|
|
32
|
+
size: Dimensions | null;
|
|
33
|
+
hasBeenDragged: boolean;
|
|
34
|
+
dockPosition: number;
|
|
35
|
+
glow: ModalGlow | null;
|
|
36
|
+
content?: unknown;
|
|
37
|
+
contentBg?: string;
|
|
38
|
+
parentId?: ModalId;
|
|
39
|
+
childId?: ModalId;
|
|
40
|
+
offsetFromParent?: Position;
|
|
41
|
+
lastChildId?: ModalId;
|
|
42
|
+
}
|
|
43
|
+
export interface AnimationTransform {
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
originX: number;
|
|
47
|
+
originY: number;
|
|
48
|
+
}
|
|
49
|
+
export type DockPosition = 'left' | 'right' | 'bottom' | 'free';
|
|
50
|
+
export type DockOrientation = 'horizontal' | 'vertical';
|
|
51
|
+
export type DockLabelMode = 'hidden' | 'beside' | 'below';
|
|
52
|
+
export type HeaderLayout = 'macos' | 'windows' | 'none';
|
|
53
|
+
export type StackingLayerName = 'BASE' | 'DROPDOWN' | 'STICKY' | 'OVERLAY' | 'MODAL' | 'DOCK' | 'TOAST';
|
|
54
|
+
/** Feature toggles */
|
|
55
|
+
export interface ModalFeatures {
|
|
56
|
+
dock: boolean;
|
|
57
|
+
minimize: boolean;
|
|
58
|
+
transparency: boolean;
|
|
59
|
+
resize: boolean;
|
|
60
|
+
drag: boolean;
|
|
61
|
+
focusTrap: boolean;
|
|
62
|
+
animations: boolean;
|
|
63
|
+
backdrop: boolean;
|
|
64
|
+
parentChild: boolean;
|
|
65
|
+
}
|
|
66
|
+
/** Appearance configuration */
|
|
67
|
+
export interface AppearanceConfig {
|
|
68
|
+
headerLayout: HeaderLayout;
|
|
69
|
+
defaultWidth: string;
|
|
70
|
+
defaultHeight: string;
|
|
71
|
+
minWidth: number;
|
|
72
|
+
minHeight: number;
|
|
73
|
+
}
|
|
74
|
+
/** Deep partial utility type */
|
|
75
|
+
export type DeepPartial<T> = {
|
|
76
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
77
|
+
};
|
|
78
|
+
/** Per-modal config overrides - deep partial of features and appearance */
|
|
79
|
+
export interface ModalConfigOverrides {
|
|
80
|
+
features?: DeepPartial<ModalFeatures>;
|
|
81
|
+
appearance?: DeepPartial<AppearanceConfig>;
|
|
82
|
+
}
|
|
83
|
+
export interface BaseModalProps {
|
|
84
|
+
id: ModalId;
|
|
85
|
+
title: string;
|
|
86
|
+
/** Icon identifier string (used by renderIcon in modal header and dock) */
|
|
87
|
+
icon?: string;
|
|
88
|
+
maxWidth?: string;
|
|
89
|
+
preferredHeight?: string;
|
|
90
|
+
autoOpen?: boolean;
|
|
91
|
+
openSourcePosition?: Position | null;
|
|
92
|
+
glow?: ModalGlow;
|
|
93
|
+
/** Per-modal config overrides (takes precedence over global config) */
|
|
94
|
+
config?: ModalConfigOverrides;
|
|
95
|
+
closeOnEscape?: boolean;
|
|
96
|
+
onClose?: () => void;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Position, Bounds } from './types';
|
|
2
|
+
/** Bounds of an existing modal for overlap calculation */
|
|
3
|
+
export interface ModalBounds {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ViewportConstraintOptions {
|
|
10
|
+
/** Margin from viewport edges (default: 8) */
|
|
11
|
+
margin?: number;
|
|
12
|
+
/** Allow element to go partially off-screen if larger than viewport */
|
|
13
|
+
allowPartialVisibility?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Constrain a position to keep an element within viewport bounds
|
|
17
|
+
*/
|
|
18
|
+
export declare function constrainToViewport(x: number, y: number, width: number, height: number, options?: ViewportConstraintOptions): Position;
|
|
19
|
+
/**
|
|
20
|
+
* Constrain size and position to fit within viewport
|
|
21
|
+
*/
|
|
22
|
+
export declare function constrainSizeToViewport(x: number, y: number, width: number, height: number, options?: ViewportConstraintOptions): Bounds;
|
|
23
|
+
/**
|
|
24
|
+
* Calculate overlap area between two rectangles
|
|
25
|
+
* @internal Exported for testing
|
|
26
|
+
*/
|
|
27
|
+
export declare function calculateOverlap(a: {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
width: number;
|
|
31
|
+
height: number;
|
|
32
|
+
}, b: {
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
}): number;
|
|
38
|
+
/**
|
|
39
|
+
* Calculate total overlap of a modal at a given position with all existing modals
|
|
40
|
+
* @internal Exported for testing
|
|
41
|
+
*/
|
|
42
|
+
export declare function calculateTotalOverlap(x: number, y: number, width: number, height: number, existingModals: ModalBounds[], gap: number): number;
|
|
43
|
+
export interface SmartPositionOptions {
|
|
44
|
+
/** Minimum gap between modals (default: 16). Also used as viewport edge margin unless `margin` is set. */
|
|
45
|
+
modalGap?: number;
|
|
46
|
+
/** Margin from viewport edges (default: uses modalGap value) */
|
|
47
|
+
margin?: number;
|
|
48
|
+
/** Number of positions to test along each axis */
|
|
49
|
+
gridResolution?: number;
|
|
50
|
+
/** Additional bounds to avoid (e.g., navigation bars, toolbars) */
|
|
51
|
+
avoidBounds?: ModalBounds[];
|
|
52
|
+
/** Margin to add around avoidBounds elements (default: 16) */
|
|
53
|
+
avoidMargin?: number;
|
|
54
|
+
}
|
|
55
|
+
/** Modal with ID for rearrangement tracking */
|
|
56
|
+
export interface ModalBoundsWithId extends ModalBounds {
|
|
57
|
+
id: string;
|
|
58
|
+
}
|
|
59
|
+
/** Result of rearrangement calculation */
|
|
60
|
+
export interface RearrangementResult {
|
|
61
|
+
/** New position for the new modal */
|
|
62
|
+
newModalPosition: Position;
|
|
63
|
+
/** Map of modal IDs to their new positions */
|
|
64
|
+
existingModalMoves: Map<string, Position>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get bounds of elements matching the given CSS selectors
|
|
68
|
+
*/
|
|
69
|
+
export declare function getElementBounds(selectors: string[]): ModalBounds[];
|
|
70
|
+
/**
|
|
71
|
+
* Calculate position quality score (0 = best/center, 1 = worst/corner)
|
|
72
|
+
* Considers both distance from center and proximity to edges
|
|
73
|
+
* @internal Exported for testing
|
|
74
|
+
*/
|
|
75
|
+
export declare function calculatePositionScore(x: number, y: number, width: number, height: number, vw: number, vh: number, margin: number): number;
|
|
76
|
+
/**
|
|
77
|
+
* Find the best position for a new modal that minimizes overlap with existing modals.
|
|
78
|
+
* Prefers positions closer to center - corners are only used as last resort.
|
|
79
|
+
* Tests positions in a grid pattern and returns the best one.
|
|
80
|
+
* Falls back to center if no existing modals.
|
|
81
|
+
*
|
|
82
|
+
* Note: avoidBounds are treated as STRICT - positions that overlap them are filtered out.
|
|
83
|
+
* Modal-to-modal overlap is treated more leniently (up to 30% acceptable for better centering).
|
|
84
|
+
*/
|
|
85
|
+
export declare function findSmartPosition(width: number, height: number, existingModals: ModalBounds[], options?: SmartPositionOptions): Position;
|
|
86
|
+
/**
|
|
87
|
+
* Calculate rearrangement of existing modals to make room for a new modal.
|
|
88
|
+
* Distributes modals evenly across the viewport width.
|
|
89
|
+
* Returns null if rearrangement is not possible (not enough space).
|
|
90
|
+
*/
|
|
91
|
+
export declare function calculateRearrangement(newModalWidth: number, newModalHeight: number, existingModals: ModalBoundsWithId[], options?: SmartPositionOptions): RearrangementResult | null;
|
|
92
|
+
//# sourceMappingURL=viewport.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
.modal-backdrop.svelte-1d3nq4t {
|
|
3
|
+
position: fixed;
|
|
4
|
+
inset: 0;
|
|
5
|
+
background: var(--modal-backdrop-bg, rgba(0, 0, 0, 0.5));
|
|
6
|
+
backdrop-filter: blur(var(--modal-backdrop-blur, 4px));
|
|
7
|
+
-webkit-backdrop-filter: blur(var(--modal-backdrop-blur, 4px));
|
|
8
|
+
pointer-events: all; /* Block clicks on content behind modals */
|
|
9
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as t from"svelte/internal/client";const e={BASE:0,DROPDOWN:100,STICKY:200,OVERLAY:300,MODAL:400,DOCK:8e3,TOAST:9e3};let n=t.state(t.proxy(e.MODAL));function i(){t.set(n,oe().zIndex.base,!0)}function o(){const e=t.get(n);return t.set(n,t.get(n)+2),e}function r(t){const n=oe();return"MODAL"===t?n.zIndex.base:"DOCK"===t?n.zIndex.dock:"TOAST"===t?n.zIndex.toast:e[t]}function s(){t.set(n,oe().zIndex.base,!0)}const d=8;function a(t,e,n,i,o={}){const{margin:r=d,allowPartialVisibility:s=!1}=o,a="undefined"!=typeof window?window.innerWidth:1920,c="undefined"!=typeof window?window.innerHeight:1080;let u,l,f,g;return s&&n>a-2*r?(u=40-n,l=a-40):(u=r,l=Math.max(r,a-n-r)),s&&i>c-2*r?(f=40-i,g=c-40):(f=r,g=Math.max(r,c-i-r)),{x:Math.max(u,Math.min(l,t)),y:Math.max(f,Math.min(g,e))}}function c(t,e,n,i,o={}){const{margin:r=d}=o,s=("undefined"!=typeof window?window.innerWidth:1920)-2*r,c=("undefined"!=typeof window?window.innerHeight:1080)-2*r,u=Math.min(n,s),l=Math.min(i,c),f=a(t,e,u,l,o);return{x:f.x,y:f.y,width:u,height:l}}function u(t,e){return Math.max(0,Math.min(t.x+t.width,e.x+e.width)-Math.max(t.x,e.x))*Math.max(0,Math.min(t.y+t.height,e.y+e.height)-Math.max(t.y,e.y))}function l(t,e,n,i,o,r){const s={x:t-r,y:e-r,width:n+2*r,height:i+2*r};let d=0;for(const t of o)d+=u(s,t);return d}function f(t){if("undefined"==typeof document)return[];const e=[];for(const n of t)try{const t=document.querySelectorAll(n);for(const n of t){const t=n.getBoundingClientRect();t.width>0&&t.height>0&&e.push({x:t.left,y:t.top,width:t.width,height:t.height})}}catch{}return e}function g(t,e,n,i,o,r,s){const d=(o-n)/2,a=(r-i)/2,c=d-s,u=a-s,l=Math.abs(t-d)/(c||1),f=Math.abs(e-a)/(u||1),g=Math.sqrt(l*l+f*f)/Math.SQRT2,h=50,p=t-s,m=o-n-s-t,x=e-s,I=r-i-s-e;let y=0;return p<h&&(y+=.3*(1-p/h)),m<h&&(y+=.3*(1-m/h)),x<h&&(y+=.2*(1-x/h)),I<h&&(y+=.2*(1-I/h)),Math.min(1,g+y)}function h(t,e,n,i={}){const{modalGap:o=16,gridResolution:r=10,avoidBounds:s=[],avoidMargin:d=16}=i,a=i.margin??o,c="undefined"!=typeof window?window.innerWidth:1920,u="undefined"!=typeof window?window.innerHeight:1080,f=s.map(t=>({x:t.x-d,y:t.y-d,width:t.width+2*d,height:t.height+2*d})),h={x:(c-t)/2,y:(u-e)/2};if(0===n.length&&0===f.length)return h;const p=a,m=Math.max(a,c-t-a),x=a,I=Math.max(a,u-e-a);if(m<=p||I<=x)return h;const y=l(h.x,h.y,t,e,n,o),w=l(h.x,h.y,t,e,f,0);if(0===y&&0===w)return h;const z=[],M=(m-p)/r,v=(I-x)/r;for(let i=0;i<=r;i++)for(let s=0;s<=r;s++){const r=p+i*M,d=x+s*v,h=l(r,d,t,e,n,o),m=l(r,d,t,e,f,0),I=g(r,d,t,e,c,u,a);z.push({pos:{x:r,y:d},modalOverlap:h,avoidOverlap:m,centerDist:I})}const O=z.filter(t=>0===t.avoidOverlap),P=O.length>0?O:z,C=t*e,D=Math.min(...P.map(t=>t.modalOverlap))/C;return P.sort((t,e)=>{if(0===O.length&&t.avoidOverlap!==e.avoidOverlap)return t.avoidOverlap-e.avoidOverlap;const n=t.modalOverlap/C,i=e.modalOverlap/C;if(D<.3){const o=.3,r=n<=o,s=i<=o;if(r&&s)return t.centerDist+.3*n-(e.centerDist+.3*i);if(r)return-1;if(s)return 1}return.6*n+.4*t.centerDist-(.6*i+.4*e.centerDist)}),P[0].pos}function p(t,e,n,i={}){const{modalGap:o=16}=i,r=i.margin??o,s="undefined"!=typeof window?window.innerWidth:1920,d="undefined"!=typeof window?window.innerHeight:1080,a=n.reduce((t,e)=>t+e.width,0)+t,c=n.length*o,u=s-2*r;if(a+c>u)return null;const l=u-a-c;n.length;const f=l/2,g=s/2,h=[...n.map(t=>({id:t.id,width:t.width,height:t.height,currentX:t.x+t.width/2,currentY:t.y,isNew:!1})),{id:"__new__",width:t,height:e,currentX:g,currentY:(d-e)/2,isNew:!0}];h.sort((t,e)=>t.currentX-e.currentX);let p=r+f;const m=new Map;let x=null;for(const t of h){const e=p;if(t.isNew)x={x:Math.round(e),y:Math.round(t.currentY)};else{const i=n.find(e=>e.id===t.id);Math.abs(e-i.x)>5&&m.set(t.id,{x:Math.round(e),y:Math.round(i.y)})}p+=t.width+o}return x?{newModalPosition:x,existingModalMoves:m}:null}let m=t.proxy(new Map),x=t.state(0);const I=new Set;function y(){t.update(x),queueMicrotask(()=>{I.forEach(t=>t())})}function w(t){return I.add(t),()=>I.delete(t)}let z=t.state(t.proxy([])),M=t.state(t.proxy([])),v=t.state(t.proxy([])),O=t.state(t.proxy([])),P=t.state(t.proxy([])),C=t.state(t.proxy([])),D=t.state(t.proxy([])),k=t.state(t.proxy([])),T=t.state(null),b=t.proxy(new Map),A=t.state(null),F=t.proxy(new Map),W=t.proxy(new Set),H=t.proxy(new Set),B=t.state(t.proxy([])),S=null,R=null;function X(e){const n=m.get(e.id),i=(null==n?void 0:n.zIndex)??o();n?m.set(e.id,{...n,title:e.title,icon:e.icon,glow:e.glow,zIndex:i}):m.set(e.id,{...e,zIndex:i,isAnimating:!1}),y(),e.isMinimized&&!t.get(B).includes(e.id)&&t.get(B).push(e.id)}function E(e){const n=m.get(e);if(n){if(t.set(B,t.get(B).filter(t=>t!==e),!0),n.childId){const t=m.get(n.childId);t&&m.set(n.childId,{...t,parentId:void 0})}if(n.parentId){const t=m.get(n.parentId);t&&m.set(n.parentId,{...t,childId:void 0,lastChildId:n.id})}m.delete(e),y(),H.delete(e),W.delete(e)}}function Y(e){const n=m.get(e);if(!n||n.isMinimized)return;if(Kt(e),n.parentId){const t=m.get(n.parentId);if(t&&!t.isMinimized)return void Y(n.parentId)}if(t.set(z,[...t.get(z),e],!0),n.position&&n.size&&R){const i=R(),o=t.get(B).indexOf(e),r=i.x+o*(i.height+8),s=i.y;t.set(T,{x:r,y:s,originX:n.position.x+n.size.width/2,originY:n.position.y+n.size.height/2},!0)}const i=n.childId;m.set(e,{...n,isMinimized:!0,lastChildId:i}),y(),t.get(B).includes(e)||t.get(B).push(e),n.childId&&ot(e)}function q(e){const n=m.get(e);if(!n||!n.isMinimized)return;m.set(e,{...n,isMinimized:!1,isOpen:!0}),y(),t.set(P,[...t.get(P),e],!0),V(e);const i=n.lastChildId||n.childId;i&&N(i)}function L(){Array.from(m.values()).filter(t=>t.isMinimized).map(t=>t.id).forEach(e=>{const n=m.get(e);if(n){m.set(e,{...n,isMinimized:!1,isOpen:!0}),t.set(P,[...t.get(P),e],!0),V(e);const i=n.lastChildId||n.childId;i&&N(i)}}),t.set(B,[],!0),y()}function N(e){const n=m.get(e);n&&n.isHiddenWithParent&&(m.set(e,{...n,isHiddenWithParent:!1}),y(),t.set(C,[...t.get(C),e],!0))}function _(t,e,n){const i=m.get(t);if(!i)return;let o=e;if((null==n?void 0:n.constrain)&&i.size&&(o=a(e.x,e.y,i.size.width,i.size.height)),m.set(t,{...i,position:o,size:(null==n?void 0:n.size)??i.size,hasBeenDragged:i.hasBeenDragged||(null==n?void 0:n.drag)||!1}),i.childId){let e=t,n=o;for(;;){const t=m.get(e);if(!(null==t?void 0:t.childId))break;const i=m.get(t.childId);if(!(null==i?void 0:i.offsetFromParent))break;const o={x:n.x+i.offsetFromParent.x,y:n.y+i.offsetFromParent.y};m.set(t.childId,{...i,position:o,hasBeenDragged:!0}),e=t.childId,n=o}}if(i.parentId&&i.offsetFromParent){const e=oe();let n=t,r=i;for(;r.parentId&&r.offsetFromParent;){const i=m.get(r.parentId);if(!i)break;const s=n===t?o:m.get(n).position,d={x:s.x-r.offsetFromParent.x,y:s.y-r.offsetFromParent.y};"animated"===e.parentChild.movementMode?F.set(r.parentId,d):m.set(r.parentId,{...i,position:d,hasBeenDragged:!0}),n=r.parentId,r=i}}y()}function G(t,e){const n=m.get(t);n&&(m.set(t,{...n,size:e}),y())}function K(t,e){const n=m.get(t);n&&(m.set(t,{...n,...e}),y())}function V(t){var e;const n=m.get(t);if(!n)return;const i=Math.max(...Array.from(m.values()).map(t=>t.zIndex),0);if(n.parentId){const o=m.get(n.parentId);o&&o.zIndex<i&&m.set(n.parentId,{...o,zIndex:i+2});const r=(null==(e=m.get(n.parentId))?void 0:e.zIndex)??i+2;return n.zIndex<=r&&m.set(t,{...n,zIndex:r+2}),void y()}if(n.zIndex<i&&(m.set(t,{...n,zIndex:i+2}),y()),n.childId){const e=m.get(n.childId),i=m.get(t);e&&i&&e.zIndex<=i.zIndex&&(m.set(n.childId,{...e,zIndex:i.zIndex+2}),y())}}function $(t){const e=m.get(t);if(!e)return!1;const n=Math.max(...Array.from(m.values()).map(t=>t.zIndex),0);return e.zIndex===n&&!e.isMinimized&&!e.isHiddenWithParent}function j(e){t.set(B,e,!0)}function Q(e,n,i){const o=n.getBoundingClientRect();b.set(e,{x:o.left+o.width/2,y:o.top+o.height/2});const r=oe();(null==i?void 0:i.parentId)&&r.features.parentChild&&t.set(A,{parentId:i.parentId,childId:e},!0),t.get(M).includes(e)||t.set(M,[...t.get(M),e],!0),y();const s=m.get(e);if(s){if(s.isOpen&&!s.isMinimized&&!s.isHiddenWithParent)return t.set(M,t.get(M).filter(t=>t!==e),!0),kt(e),void V(e);if(s.isMinimized)return t.set(M,t.get(M).filter(t=>t!==e),!0),void q(e);m.set(e,{...s,isOpen:!0}),V(e),null==S||S.push(e)}}function J(e){X(e);const n=m.get(e.id);n&&(m.set(e.id,{...n,isOpen:!0}),y()),t.set(M,[...t.get(M),e.id],!0),y(),V(e.id),null==S||S.push(e.id)}function U(e,n=!1){const i=m.get(e);i&&(Kt(e),n?t.set(O,[...t.get(O),e],!0):t.set(v,[...t.get(v),e],!0),y(),i.childId&&U(i.childId,n),null==S||S.pop())}function Z(){Array.from(m.keys()).forEach(t=>U(t,!0))}function tt(t){const e=m.get(t);if(e){if(e.parentId){const n=m.get(e.parentId);n&&n.childId===t&&m.set(e.parentId,{...n,childId:void 0,lastChildId:t})}m.set(t,{...e,isOpen:!1,isMinimized:!1,isHiddenWithParent:!1,isTransparent:!1,position:null,size:null,hasBeenDragged:!1,parentId:void 0,childId:void 0,offsetFromParent:void 0}),y()}}function et(t){const e=m.get(t);if(!e)return[t];const n=[t];return e.childId&&n.push(...et(e.childId)),n}function nt(e,n,i){const o=oe();if(i&&!b.has(e.id)){const t=i.getBoundingClientRect();b.set(e.id,{x:t.left+t.width/2,y:t.top+t.height/2})}const r={id:e.id,title:e.title??"",icon:e.icon??"",isOpen:!0,isMinimized:!1,isHiddenWithParent:!1,isTransparent:e.isTransparent??!1,isRejected:!1,position:e.position??null,size:e.size??null,hasBeenDragged:e.hasBeenDragged??!1,dockPosition:e.dockPosition??-1,glow:e.glow??null};if(!o.features.parentChild){X(r);const n=m.get(e.id);return n&&m.set(e.id,{...n,isOpen:!0}),t.set(M,[...t.get(M),e.id],!0),y(),void V(e.id)}const s=m.get(n);if(!s)return;s.childId&&U(s.childId,!0),X({...r,parentId:n});const d=m.get(e.id);d&&m.set(e.id,{...d,isOpen:!0,parentId:n}),t.set(M,[...t.get(M),e.id],!0),y(),V(e.id),t.set(A,{parentId:n,childId:e.id},!0)}function it(t,e){if(!oe().features.parentChild)return;const n=m.get(t),i=m.get(e);if(!n||!i)return;let o={x:40,y:40};n.position&&i.position&&(o={x:i.position.x-n.position.x,y:i.position.y-n.position.y});const r=Math.max(i.zIndex,n.zIndex+1);m.set(t,{...n,childId:e,lastChildId:e}),m.set(e,{...i,parentId:t,offsetFromParent:o,zIndex:r}),y()}function ot(t){const e=m.get(t);if(!(null==e?void 0:e.childId))return;const n=m.get(e.childId);n&&(m.set(e.childId,{...n,isHiddenWithParent:!0}),y())}function rt(t,e){const n=m.get(t);if(!(null==n?void 0:n.childId))return;const i=m.get(n.childId);if(!i||!i.offsetFromParent)return;const o={x:e.x+i.offsetFromParent.x,y:e.y+i.offsetFromParent.y};m.set(n.childId,{...i,position:o}),y()}function st(t,e){const n=m.get(t),i=m.get(e);if(!(null==n?void 0:n.position)||!(null==i?void 0:i.position))return;const o={x:n.position.x-i.position.x,y:n.position.y-i.position.y};m.set(t,{...n,offsetFromParent:o}),y()}function dt(e){return t.get(z).includes(e)}function at(e){return!!t.get(z).includes(e)&&(t.set(z,t.get(z).filter(t=>t!==e),!0),!0)}function ct(){return t.get(z).length>0}function ut(){return Array.from(m.keys())}function lt(t){return m.get(t)}function ft(t){const e=[];for(const[n,i]of m.entries())if(n!==t&&i.isOpen&&!i.isMinimized&&!i.isHiddenWithParent&&!i.parentId)if(i.position&&i.size)e.push({id:String(n),x:i.position.x,y:i.position.y,width:i.size.width,height:i.size.height});else{const t=document.querySelector(`[data-modal-id="${String(n)}"]`);if(t){const i=t.getBoundingClientRect();e.push({id:String(n),x:i.left,y:i.top,width:i.width,height:i.height})}}return e}function gt(t){const e=[];for(const[n,i]of m.entries())if(n!==t&&i.isOpen&&!i.isMinimized&&!i.isHiddenWithParent)if(i.position&&i.size)e.push({x:i.position.x,y:i.position.y,width:i.size.width,height:i.size.height});else{const t=document.querySelector(`[data-modal-id="${String(n)}"]`);if(t){const n=t.getBoundingClientRect();e.push({x:n.left,y:n.top,width:n.width,height:n.height})}}return e}function ht(){return t.get(x)}function pt(){const e=t.get(T);return t.set(T,null),e}function mt(e){return t.get(M).includes(e)}function xt(e){return!!t.get(M).includes(e)&&(t.set(M,t.get(M).filter(t=>t!==e),!0),!0)}function It(e){return t.get(v).includes(e)}function yt(e){return!!t.get(v).includes(e)&&(t.set(v,t.get(v).filter(t=>t!==e),!0),!0)}function wt(e){return t.get(O).includes(e)}function zt(e){return!!t.get(O).includes(e)&&(t.set(O,t.get(O).filter(t=>t!==e),!0),!0)}function Mt(e){return t.get(P).includes(e)}function vt(e){return!!t.get(P).includes(e)&&(t.set(P,t.get(P).filter(t=>t!==e),!0),!0)}function Ot(e){return t.get(C).includes(e)}function Pt(e){return!!t.get(C).includes(e)&&(t.set(C,t.get(C).filter(t=>t!==e),!0),!0)}function Ct(e){return t.get(D).includes(e)}function Dt(e){return!!t.get(D).includes(e)&&(t.set(D,t.get(D).filter(t=>t!==e),!0),!0)}function kt(e){m.get(e)&&(t.get(D).includes(e)||t.get(k).includes(e)||(t.set(D,[...t.get(D),e],!0),y()))}function Tt(e){t.get(k).includes(e)||t.set(k,[...t.get(k),e],!0)}function bt(e){t.set(k,t.get(k).filter(t=>t!==e),!0)}function At(){return t.get(A)}function Ft(e){if(!t.get(A)||t.get(A).childId!==e)return null;const n=t.get(A);return t.set(A,null),n}function Wt(t,e){b.set(t,e)}function Ht(t){const e=b.get(t);return e&&b.delete(t),e??null}function Bt(t,e){e?W.add(t):W.delete(t)}function St(t){return W.has(t)}function Rt(t){const e=m.get(t);return void 0!==e&&e.isOpen&&!e.isMinimized&&!e.isHiddenWithParent}function Xt(t){return m.has(t)}function Et(){return{get modals(){return m},get pendingMinimize(){return t.get(z)},get pendingOpen(){return t.get(M)},get pendingClose(){return t.get(v)},get pendingRestore(){return t.get(P)},get dockOrder(){return t.get(B)}}}function Yt(t){H.has(t)?H.delete(t):H.add(t);const e=m.get(t);e&&(m.set(t,{...e,isTransparent:H.has(t)}),y())}function qt(t){H.delete(t);const e=m.get(t);e&&(m.set(t,{...e,isTransparent:!1}),y())}function Lt(t){t.animate([{transform:"translateX(0)"},{transform:"translateX(-6px)"},{transform:"translateX(6px)"},{transform:"translateX(-6px)"},{transform:"translateX(6px)"},{transform:"translateX(0)"}],{duration:300,easing:"ease-in-out"})}function Nt(t){const e=F.get(t);if(!e)return;const n=m.get(t);n&&(m.set(t,{...n,isAnimatingPosition:!0,position:e}),F.delete(t),y())}function _t(t){const e=m.get(t);e&&(m.set(t,{...e,isAnimatingPosition:!1}),y())}function Gt(t){return F.has(t)}function Kt(t){F.delete(t)}function Vt(t){const e=oe().parentChild.animationDuration;for(const[e,n]of t){const t=m.get(e);t&&m.set(e,{...t,position:n,isAnimatingPosition:!0,hasBeenDragged:!0})}y(),setTimeout(()=>{for(const e of t.keys()){const t=m.get(e);t&&m.set(e,{...t,isAnimatingPosition:!1})}y()},e)}function $t(t){const e=oe();if("animated"!==e.parentChild.movementMode)return;const n=e.parentChild.animationDuration,i=[];let o=t;for(;;){const t=m.get(o);if(!(null==t?void 0:t.parentId))break;i.push({parentId:t.parentId,childId:o}),o=t.parentId}i.forEach(({parentId:t,childId:e},i)=>{setTimeout(()=>{const i=m.get(e),o=m.get(t);if(!(null==i?void 0:i.position)||!i.offsetFromParent||!o)return;const r={x:i.position.x-i.offsetFromParent.x,y:i.position.y-i.offsetFromParent.y};F.set(t,r),Nt(t),setTimeout(()=>_t(t),n)},i*n)})}function jt(t){}function Qt(t){S=t}function Jt(t){R=t}function Ut(){return{modals:m,pendingMinimize:t.get(z),pendingOpen:t.get(M),pendingClose:t.get(v),pendingRestore:t.get(P),dockOrder:t.get(B),animatingModals:W,transparentModals:H}}function Zt(){m.clear(),t.get(z).length=0,t.get(M).length=0,t.get(v).length=0,t.get(O).length=0,t.get(P).length=0,t.get(C).length=0,t.set(T,null),b.clear(),t.set(A,null),F.clear(),W.clear(),H.clear(),t.get(B).length=0,S=null,R=null}const te={features:{dock:!0,minimize:!0,transparency:!0,resize:!0,drag:!0,focusTrap:!0,animations:!0,backdrop:!0,parentChild:!0},dock:{position:"bottom",labelMode:"beside",enableReorder:!0,enableFreeDrag:!0},animations:{open:400,close:250,minimize:500,restore:400},appearance:{headerLayout:"macos",defaultWidth:"480px",defaultHeight:"auto",minWidth:280,minHeight:200},zIndex:{base:400,dock:8e3,toast:9e3},parentChild:{movementMode:"animated",animationDuration:300},positioning:{strategy:"smart",modalGap:16,avoidElements:[]},portalTarget:"#modal-portal"};let ee={...te},ne=t.state(0);function ie(){return t.get(ne)}function oe(){return ee}function re(e){const n=ee;ee=de(te,e),t.update(ne),n.features.dock&&!ee.features.dock&&L()}function se(){ee={...te},t.update(ne)}function de(t,e){return{features:{...t.features,...e.features},dock:{...t.dock,...e.dock},animations:{...t.animations,...e.animations},appearance:{...t.appearance,...e.appearance},zIndex:{...t.zIndex,...e.zIndex},parentChild:{...t.parentChild,...e.parentChild},positioning:{...t.positioning,...e.positioning},portalTarget:e.portalTarget??t.portalTarget}}function ae(t){return ee.features[t]}export{Ut as _getInternalState,Zt as _resetInternalState,o as acquireModalZIndex,Vt as animateModalsToPositions,Nt as animateParentToPosition,V as bringToFront,u as calculateOverlap,g as calculatePositionScore,p as calculateRearrangement,l as calculateTotalOverlap,_t as clearParentAnimationFlag,Kt as clearPendingParentAnimation,Z as closeAllModals,U as closeModal,c as constrainSizeToViewport,a as constrainToViewport,Ht as consumeOpenSourcePosition,Dt as consumePendingAttention,Pt as consumePendingChildRestore,yt as consumePendingClose,zt as consumePendingForceClose,at as consumePendingMinimize,pt as consumePendingMinimizeTarget,xt as consumePendingOpen,Ft as consumePendingParentLink,vt as consumePendingRestore,J as createModal,te as defaultConfig,bt as endAttentionAnimation,tt as finalizeModalClose,h as findSmartPosition,oe as getConfig,ie as getConfigVersion,f as getElementBounds,r as getLayerZIndex,lt as getModalState,Et as getModalsStore,et as getModalsToClose,gt as getOpenModalBounds,ft as getOpenModalBoundsWithIds,At as getPendingParentLink,ut as getRegisteredModalIds,ht as getStateVersion,ct as hasAnyPendingMinimize,Ct as hasPendingAttention,Ot as hasPendingChildRestore,It as hasPendingClose,wt as hasPendingForceClose,dt as hasPendingMinimize,mt as hasPendingOpen,Gt as hasPendingParentAnimation,Mt as hasPendingRestore,ot as hideChildWithParent,i as initializeStacking,ae as isFeatureEnabled,St as isModalAnimating,Rt as isModalOpen,Xt as isModalRegistered,$ as isTopModal,it as linkModals,de as mergeConfig,Y as minimizeModal,nt as openChildModal,Q as openModal,X as registerModal,j as reorderDock,se as resetConfig,qt as resetModalTransparency,s as resetStacking,L as restoreAllMinimizedModals,N as restoreChildModal,q as restoreModal,st as setChildOffsetFromParent,re as setConfig,Jt as setDockPositionGetter,Bt as setModalAnimating,jt as setRegistryFunctions,Qt as setURLStateCallbacks,Lt as shakeElement,Tt as startAttentionAnimation,Wt as storeOpenSourcePosition,w as subscribe,Yt as toggleModalTransparency,kt as triggerAttention,$t as triggerCascadingParentAnimations,E as unregisterModal,rt as updateChildPosition,K as updateModal,_ as updateModalPosition,G as updateModalSize};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { default as React, ReactNode } from 'react';
|
|
2
|
+
export interface DockProps {
|
|
3
|
+
/** Custom icon renderer - receives icon name, returns React element */
|
|
4
|
+
renderIcon?: (props: {
|
|
5
|
+
icon: string;
|
|
6
|
+
}) => ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare function Dock({ renderIcon }: DockProps): React.ReactElement<{
|
|
9
|
+
ref: React.RefObject<HTMLDivElement | null>;
|
|
10
|
+
'data-dock-bridge': boolean;
|
|
11
|
+
}, string | React.JSXElementConstructor<any>>;
|
|
12
|
+
export default Dock;
|
|
13
|
+
//# sourceMappingURL=Dock.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as React, ReactNode } from 'react';
|
|
2
|
+
import { BaseModalProps } from '../core/types';
|
|
3
|
+
export interface ModalProps extends BaseModalProps {
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
footer?: ReactNode;
|
|
6
|
+
/** Custom icon as React element (overrides icon string if provided) */
|
|
7
|
+
customIcon?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function Modal({ id, title, icon, customIcon, maxWidth, preferredHeight, autoOpen, openSourcePosition, glow, config, closeOnEscape, onClose, children, footer, }: ModalProps): React.FunctionComponentElement<React.ProviderProps<import('..').ModalId | null>>;
|
|
10
|
+
export default Modal;
|
|
11
|
+
//# sourceMappingURL=Modal.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as React, ReactNode } from 'react';
|
|
2
|
+
import { ModalLibraryConfig } from '../core/config.svelte';
|
|
3
|
+
export interface ModalProviderProps {
|
|
4
|
+
/** Configuration overrides */
|
|
5
|
+
config?: Partial<ModalLibraryConfig>;
|
|
6
|
+
/** Children to render */
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function ModalProvider({ config: configOverride, children }: ModalProviderProps): React.FunctionComponentElement<React.FragmentProps>;
|
|
10
|
+
export default ModalProvider;
|
|
11
|
+
//# sourceMappingURL=ModalProvider.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { Modal } from './Modal';
|
|
2
|
+
export type { ModalProps } from './Modal';
|
|
3
|
+
export { ModalProvider } from './ModalProvider';
|
|
4
|
+
export type { ModalProviderProps } from './ModalProvider';
|
|
5
|
+
export { Dock } from './Dock';
|
|
6
|
+
export type { DockProps } from './Dock';
|
|
7
|
+
export { useModal, useModals } from './useModal';
|
|
8
|
+
export { useModalZIndex } from './useModalZIndex';
|
|
9
|
+
export type { UseModalZIndexReturn } from './useModalZIndex';
|
|
10
|
+
export { ModalIdContext } from './context';
|
|
11
|
+
export { createSvelteBridge, reactChildrenToSvelteSnippet } from './svelte-bridge';
|
|
12
|
+
export { openModal, closeModal, minimizeModal, restoreModal, bringToFront, isModalOpen, isModalRegistered, openChildModal, triggerAttention, } from '../core/state.svelte';
|
|
13
|
+
export { init, createBackdrop, createDock } from '../vanilla/index';
|
|
14
|
+
export type { InitOptions, InitControl, BackdropControl, DockControl } from '../vanilla/index';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { default as React, ReactNode } from 'react';
|
|
2
|
+
import { Component, Snippet } from 'svelte';
|
|
3
|
+
/**
|
|
4
|
+
* Create a React wrapper for a Svelte component
|
|
5
|
+
*/
|
|
6
|
+
export declare function createSvelteBridge<P extends Record<string, unknown>>(SvelteComponent: Component<any>): (props: P & {
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}) => React.ReactElement<{
|
|
9
|
+
ref: React.RefObject<HTMLDivElement | null>;
|
|
10
|
+
'data-svelte-bridge': string;
|
|
11
|
+
}, string | React.JSXElementConstructor<any>>;
|
|
12
|
+
/**
|
|
13
|
+
* Convert React children to a Svelte-compatible format
|
|
14
|
+
* Note: This is a basic implementation. Complex React children
|
|
15
|
+
* may require a portal-based approach.
|
|
16
|
+
*/
|
|
17
|
+
export declare function reactChildrenToSvelteSnippet(children: ReactNode): Snippet | undefined;
|
|
18
|
+
//# sourceMappingURL=svelte-bridge.d.ts.map
|