@fivem-nui/svelte 0.0.0-stage → 1.0.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 (222) hide show
  1. package/README.md +284 -2
  2. package/dist/actions/clickOutside/clickOutside.d.ts +24 -0
  3. package/dist/actions/clickOutside/clickOutside.d.ts.map +1 -0
  4. package/dist/actions/clickOutside/clickOutside.js +62 -0
  5. package/dist/actions/clickOutside/clickOutside.js.map +1 -0
  6. package/dist/actions/clickOutside/handler.d.ts +11 -0
  7. package/dist/actions/clickOutside/handler.d.ts.map +1 -0
  8. package/dist/actions/clickOutside/handler.js +45 -0
  9. package/dist/actions/clickOutside/handler.js.map +1 -0
  10. package/dist/actions/clickOutside/index.d.ts +4 -0
  11. package/dist/actions/clickOutside/index.d.ts.map +1 -0
  12. package/dist/actions/clickOutside/index.js +4 -0
  13. package/dist/actions/clickOutside/index.js.map +1 -0
  14. package/dist/actions/clickOutside/types.d.ts +36 -0
  15. package/dist/actions/clickOutside/types.d.ts.map +1 -0
  16. package/dist/actions/clickOutside/types.js +6 -0
  17. package/dist/actions/clickOutside/types.js.map +1 -0
  18. package/dist/actions/clickOutside.d.ts +63 -0
  19. package/dist/actions/clickOutside.d.ts.map +1 -0
  20. package/dist/actions/clickOutside.js +106 -0
  21. package/dist/actions/clickOutside.js.map +1 -0
  22. package/dist/actions/escape/escape.d.ts +26 -0
  23. package/dist/actions/escape/escape.d.ts.map +1 -0
  24. package/dist/actions/escape/escape.js +74 -0
  25. package/dist/actions/escape/escape.js.map +1 -0
  26. package/dist/actions/escape/handler.d.ts +11 -0
  27. package/dist/actions/escape/handler.d.ts.map +1 -0
  28. package/dist/actions/escape/handler.js +50 -0
  29. package/dist/actions/escape/handler.js.map +1 -0
  30. package/dist/actions/escape/index.d.ts +4 -0
  31. package/dist/actions/escape/index.d.ts.map +1 -0
  32. package/dist/actions/escape/index.js +4 -0
  33. package/dist/actions/escape/index.js.map +1 -0
  34. package/dist/actions/escape/types.d.ts +70 -0
  35. package/dist/actions/escape/types.d.ts.map +1 -0
  36. package/dist/actions/escape/types.js +12 -0
  37. package/dist/actions/escape/types.js.map +1 -0
  38. package/dist/actions/escape.d.ts +99 -0
  39. package/dist/actions/escape.d.ts.map +1 -0
  40. package/dist/actions/escape.js +128 -0
  41. package/dist/actions/escape.js.map +1 -0
  42. package/dist/actions/focusTrap/focusTrap.d.ts +19 -0
  43. package/dist/actions/focusTrap/focusTrap.d.ts.map +1 -0
  44. package/dist/actions/focusTrap/focusTrap.js +198 -0
  45. package/dist/actions/focusTrap/focusTrap.js.map +1 -0
  46. package/dist/actions/focusTrap/focusables.d.ts +39 -0
  47. package/dist/actions/focusTrap/focusables.d.ts.map +1 -0
  48. package/dist/actions/focusTrap/focusables.js +142 -0
  49. package/dist/actions/focusTrap/focusables.js.map +1 -0
  50. package/dist/actions/focusTrap/index.d.ts +5 -0
  51. package/dist/actions/focusTrap/index.d.ts.map +1 -0
  52. package/dist/actions/focusTrap/index.js +5 -0
  53. package/dist/actions/focusTrap/index.js.map +1 -0
  54. package/dist/actions/focusTrap/trapStack.d.ts +33 -0
  55. package/dist/actions/focusTrap/trapStack.d.ts.map +1 -0
  56. package/dist/actions/focusTrap/trapStack.js +84 -0
  57. package/dist/actions/focusTrap/trapStack.js.map +1 -0
  58. package/dist/actions/focusTrap/types.d.ts +50 -0
  59. package/dist/actions/focusTrap/types.d.ts.map +1 -0
  60. package/dist/actions/focusTrap/types.js +10 -0
  61. package/dist/actions/focusTrap/types.js.map +1 -0
  62. package/dist/actions/focusTrap.d.ts +24 -0
  63. package/dist/actions/focusTrap.d.ts.map +1 -0
  64. package/dist/actions/focusTrap.js +201 -0
  65. package/dist/actions/focusTrap.js.map +1 -0
  66. package/dist/actions/focusTrap.types.d.ts +50 -0
  67. package/dist/actions/focusTrap.types.d.ts.map +1 -0
  68. package/dist/actions/focusTrap.types.js +10 -0
  69. package/dist/actions/focusTrap.types.js.map +1 -0
  70. package/dist/actions/focusables.d.ts +39 -0
  71. package/dist/actions/focusables.d.ts.map +1 -0
  72. package/dist/actions/focusables.js +142 -0
  73. package/dist/actions/focusables.js.map +1 -0
  74. package/dist/actions/index.d.ts +5 -0
  75. package/dist/actions/index.d.ts.map +1 -0
  76. package/dist/actions/index.js +5 -0
  77. package/dist/actions/index.js.map +1 -0
  78. package/dist/actions/layer/index.d.ts +4 -0
  79. package/dist/actions/layer/index.d.ts.map +1 -0
  80. package/dist/actions/layer/index.js +4 -0
  81. package/dist/actions/layer/index.js.map +1 -0
  82. package/dist/actions/layer/layer.d.ts +28 -0
  83. package/dist/actions/layer/layer.d.ts.map +1 -0
  84. package/dist/actions/layer/layer.js +118 -0
  85. package/dist/actions/layer/layer.js.map +1 -0
  86. package/dist/actions/layer/layerStack.d.ts +10 -0
  87. package/dist/actions/layer/layerStack.d.ts.map +1 -0
  88. package/dist/actions/layer/layerStack.js +153 -0
  89. package/dist/actions/layer/layerStack.js.map +1 -0
  90. package/dist/actions/layer/types.d.ts +105 -0
  91. package/dist/actions/layer/types.d.ts.map +1 -0
  92. package/dist/actions/layer/types.js +14 -0
  93. package/dist/actions/layer/types.js.map +1 -0
  94. package/dist/actions/layer.d.ts +133 -0
  95. package/dist/actions/layer.d.ts.map +1 -0
  96. package/dist/actions/layer.js +269 -0
  97. package/dist/actions/layer.js.map +1 -0
  98. package/dist/actions/trapStack.d.ts +33 -0
  99. package/dist/actions/trapStack.d.ts.map +1 -0
  100. package/dist/actions/trapStack.js +84 -0
  101. package/dist/actions/trapStack.js.map +1 -0
  102. package/dist/client.d.ts +179 -0
  103. package/dist/client.d.ts.map +1 -0
  104. package/dist/client.js +176 -0
  105. package/dist/client.js.map +1 -0
  106. package/dist/context/index.d.ts +68 -0
  107. package/dist/context/index.d.ts.map +1 -0
  108. package/dist/context/index.js +112 -0
  109. package/dist/context/index.js.map +1 -0
  110. package/dist/index.d.ts +22 -0
  111. package/dist/index.d.ts.map +1 -0
  112. package/dist/index.js +30 -0
  113. package/dist/index.js.map +1 -0
  114. package/dist/mock/index.d.ts +27 -0
  115. package/dist/mock/index.d.ts.map +1 -0
  116. package/dist/mock/index.js +137 -0
  117. package/dist/mock/index.js.map +1 -0
  118. package/dist/mock/interceptor.d.ts +19 -0
  119. package/dist/mock/interceptor.d.ts.map +1 -0
  120. package/dist/mock/interceptor.js +128 -0
  121. package/dist/mock/interceptor.js.map +1 -0
  122. package/dist/mock/types.d.ts +100 -0
  123. package/dist/mock/types.d.ts.map +1 -0
  124. package/dist/mock/types.js +27 -0
  125. package/dist/mock/types.js.map +1 -0
  126. package/dist/mock/url.d.ts +14 -0
  127. package/dist/mock/url.d.ts.map +1 -0
  128. package/dist/mock/url.js +38 -0
  129. package/dist/mock/url.js.map +1 -0
  130. package/dist/runes/clickOutside.svelte.d.ts +29 -0
  131. package/dist/runes/clickOutside.svelte.d.ts.map +1 -0
  132. package/dist/runes/clickOutside.svelte.js +42 -0
  133. package/dist/runes/clickOutside.svelte.js.map +1 -0
  134. package/dist/runes/escape.svelte.d.ts +34 -0
  135. package/dist/runes/escape.svelte.d.ts.map +1 -0
  136. package/dist/runes/escape.svelte.js +44 -0
  137. package/dist/runes/escape.svelte.js.map +1 -0
  138. package/dist/runes/focusTrap.svelte.d.ts +21 -0
  139. package/dist/runes/focusTrap.svelte.d.ts.map +1 -0
  140. package/dist/runes/focusTrap.svelte.js +37 -0
  141. package/dist/runes/focusTrap.svelte.js.map +1 -0
  142. package/dist/runes/index.svelte.d.ts +8 -0
  143. package/dist/runes/index.svelte.d.ts.map +1 -0
  144. package/dist/runes/index.svelte.js +8 -0
  145. package/dist/runes/index.svelte.js.map +1 -0
  146. package/dist/runes/layer.svelte.d.ts +36 -0
  147. package/dist/runes/layer.svelte.d.ts.map +1 -0
  148. package/dist/runes/layer.svelte.js +48 -0
  149. package/dist/runes/layer.svelte.js.map +1 -0
  150. package/dist/runes/query.svelte.d.ts +104 -0
  151. package/dist/runes/query.svelte.d.ts.map +1 -0
  152. package/dist/runes/query.svelte.js +179 -0
  153. package/dist/runes/query.svelte.js.map +1 -0
  154. package/dist/runes/state.svelte.d.ts +72 -0
  155. package/dist/runes/state.svelte.d.ts.map +1 -0
  156. package/dist/runes/state.svelte.js +98 -0
  157. package/dist/runes/state.svelte.js.map +1 -0
  158. package/dist/runes/window.svelte.d.ts +120 -0
  159. package/dist/runes/window.svelte.d.ts.map +1 -0
  160. package/dist/runes/window.svelte.js +196 -0
  161. package/dist/runes/window.svelte.js.map +1 -0
  162. package/dist/types/index.d.ts +2 -0
  163. package/dist/types/index.d.ts.map +1 -0
  164. package/dist/types/index.js +3 -0
  165. package/dist/types/index.js.map +1 -0
  166. package/dist/types/nui.d.ts +34 -0
  167. package/dist/types/nui.d.ts.map +1 -0
  168. package/dist/types/nui.js +17 -0
  169. package/dist/types/nui.js.map +1 -0
  170. package/dist/utils/env.d.ts +21 -0
  171. package/dist/utils/env.d.ts.map +1 -0
  172. package/dist/utils/env.js +36 -0
  173. package/dist/utils/env.js.map +1 -0
  174. package/dist/utils/error.d.ts +11 -0
  175. package/dist/utils/error.d.ts.map +1 -0
  176. package/dist/utils/error.js +30 -0
  177. package/dist/utils/error.js.map +1 -0
  178. package/dist/utils/index.d.ts +3 -0
  179. package/dist/utils/index.d.ts.map +1 -0
  180. package/dist/utils/index.js +3 -0
  181. package/dist/utils/index.js.map +1 -0
  182. package/dist/utils/keyboard.d.ts +127 -0
  183. package/dist/utils/keyboard.d.ts.map +1 -0
  184. package/dist/utils/keyboard.js +152 -0
  185. package/dist/utils/keyboard.js.map +1 -0
  186. package/package.json +76 -4
  187. package/src/actions/clickOutside/clickOutside.ts +78 -0
  188. package/src/actions/clickOutside/handler.ts +49 -0
  189. package/src/actions/clickOutside/index.ts +11 -0
  190. package/src/actions/clickOutside/types.ts +54 -0
  191. package/src/actions/escape/escape.ts +90 -0
  192. package/src/actions/escape/handler.ts +52 -0
  193. package/src/actions/escape/index.ts +11 -0
  194. package/src/actions/escape/types.ts +88 -0
  195. package/src/actions/focusTrap/focusTrap.ts +228 -0
  196. package/src/actions/focusTrap/focusables.ts +155 -0
  197. package/src/actions/focusTrap/index.ts +22 -0
  198. package/src/actions/focusTrap/trapStack.ts +109 -0
  199. package/src/actions/focusTrap/types.ts +64 -0
  200. package/src/actions/index.ts +35 -0
  201. package/src/actions/layer/index.ts +13 -0
  202. package/src/actions/layer/layer.ts +140 -0
  203. package/src/actions/layer/layerStack.ts +169 -0
  204. package/src/actions/layer/types.ts +132 -0
  205. package/src/client.ts +323 -0
  206. package/src/context/index.ts +127 -0
  207. package/src/index.ts +53 -0
  208. package/src/mock/index.ts +176 -0
  209. package/src/mock/interceptor.ts +177 -0
  210. package/src/mock/types.ts +125 -0
  211. package/src/mock/url.ts +37 -0
  212. package/src/runes/clickOutside.svelte.ts +53 -0
  213. package/src/runes/escape.svelte.ts +71 -0
  214. package/src/runes/focusTrap.svelte.ts +56 -0
  215. package/src/runes/index.svelte.ts +38 -0
  216. package/src/runes/layer.svelte.ts +74 -0
  217. package/src/runes/query.svelte.ts +313 -0
  218. package/src/runes/state.svelte.ts +175 -0
  219. package/src/runes/window.svelte.ts +308 -0
  220. package/src/utils/env.ts +36 -0
  221. package/src/utils/index.ts +2 -0
  222. package/src/utils/keyboard.ts +244 -0
@@ -0,0 +1,128 @@
1
+ import { isNuiUrl, parseNuiUrl } from './url';
2
+ /**
3
+ * Extracts the body payload from a `fetch` invocation, supporting both `init.body`
4
+ * and body text inside a `Request` instance.
5
+ */
6
+ export async function extractRequestBody(input, init) {
7
+ let bodyText = typeof init?.body === 'string' ? init.body : null;
8
+ if (!bodyText && typeof Request !== 'undefined' && input instanceof Request) {
9
+ try {
10
+ bodyText = await input.clone().text();
11
+ }
12
+ catch {
13
+ // body already consumed or unreadable
14
+ }
15
+ }
16
+ if (bodyText) {
17
+ try {
18
+ return JSON.parse(bodyText);
19
+ }
20
+ catch {
21
+ return bodyText;
22
+ }
23
+ }
24
+ return null;
25
+ }
26
+ /**
27
+ * Creates the `window.fetch` interceptor function that simulates FiveM CEF transport.
28
+ */
29
+ export function createFetchInterceptor(ctx) {
30
+ const { targetResource, latencyMs, log, activeRequests, activeCallbacks, activeSendHandlers, originalFetch } = ctx;
31
+ return async (input, init) => {
32
+ const url = typeof input === 'string'
33
+ ? input
34
+ : input instanceof URL
35
+ ? input.toString()
36
+ : input.url;
37
+ if (!isNuiUrl(url, targetResource)) {
38
+ return originalFetch(input, init);
39
+ }
40
+ const { resourceName, callbackName } = parseNuiUrl(url);
41
+ const bodyObj = await extractRequestBody(input, init);
42
+ const eventName = bodyObj?.event;
43
+ const correlationId = bodyObj?.id;
44
+ const payload = bodyObj?.payload ?? bodyObj?.data;
45
+ const messageType = bodyObj?.type;
46
+ if (log) {
47
+ console.debug(`[NUI Mock] -> POST https://${resourceName}/${callbackName} type='${messageType ?? 'event'}' event='${eventName ?? callbackName}' id=${correlationId ?? '-'}`, payload);
48
+ }
49
+ // Simulate consistent transport latency across all NUI operations
50
+ if (latencyMs > 0) {
51
+ await new Promise((resolve) => setTimeout(resolve, latencyMs));
52
+ }
53
+ let handled = false;
54
+ // Check callback notifications
55
+ if (activeCallbacks[callbackName]) {
56
+ handled = true;
57
+ try {
58
+ activeCallbacks[callbackName](payload);
59
+ }
60
+ catch (e) {
61
+ console.error(`[NUI Mock] Error in callback handler '${callbackName}':`, e);
62
+ }
63
+ }
64
+ // Check send handlers
65
+ if (eventName && activeSendHandlers[eventName]) {
66
+ handled = true;
67
+ try {
68
+ activeSendHandlers[eventName](payload);
69
+ }
70
+ catch (e) {
71
+ console.error(`[NUI Mock] Error in send handler '${eventName}':`, e);
72
+ }
73
+ }
74
+ // Handle correlated request/response
75
+ if (eventName && activeRequests[eventName]) {
76
+ handled = true;
77
+ try {
78
+ const result = await activeRequests[eventName](payload);
79
+ // In FiveM CEF, HTTP POST to https://<resource>/<callback> is strictly an outgoing transport ACK;
80
+ // the native C# backend delivers the correlated response envelope asynchronously via
81
+ // SendNuiMessage -> window.postMessage.
82
+ if (correlationId) {
83
+ window.postMessage({
84
+ type: 'response',
85
+ id: correlationId,
86
+ success: true,
87
+ payload: result,
88
+ data: result
89
+ }, '*');
90
+ }
91
+ return new Response(JSON.stringify({ ok: true }), {
92
+ status: 200,
93
+ headers: { 'Content-Type': 'application/json' }
94
+ });
95
+ }
96
+ catch (err) {
97
+ const errorEnvelope = {
98
+ code: err?.code ?? 'MOCK_ERROR',
99
+ message: err instanceof Error ? err.message : String(err)
100
+ };
101
+ if (correlationId) {
102
+ window.postMessage({
103
+ type: 'response',
104
+ id: correlationId,
105
+ success: false,
106
+ error: errorEnvelope
107
+ }, '*');
108
+ }
109
+ return new Response(JSON.stringify({
110
+ success: false,
111
+ error: errorEnvelope
112
+ }), {
113
+ status: 500,
114
+ headers: { 'Content-Type': 'application/json' }
115
+ });
116
+ }
117
+ }
118
+ if (!handled && log) {
119
+ const targetEvent = eventName ?? callbackName;
120
+ console.warn(`[NUI Mock] Unhandled NUI message: no mock handler registered for '${targetEvent}'.`);
121
+ }
122
+ return new Response(JSON.stringify({ ok: true }), {
123
+ status: 200,
124
+ headers: { 'Content-Type': 'application/json' }
125
+ });
126
+ };
127
+ }
128
+ //# sourceMappingURL=interceptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptor.js","sourceRoot":"","sources":["../../src/mock/interceptor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ import type { NuiWindowAction } from '@fivem-nui/core';
2
+ /**
3
+ * Message types for synthetic NUI postMessage envelopes in the mock environment.
4
+ */
5
+ export declare enum NuiMessageType {
6
+ /**
7
+ * Standard event message.
8
+ */
9
+ Event = "event",
10
+ /**
11
+ * RPC request message.
12
+ */
13
+ Request = "request",
14
+ /**
15
+ * RPC response message.
16
+ */
17
+ Response = "response"
18
+ }
19
+ /**
20
+ * Configuration options for {@link setupNuiMock}.
21
+ */
22
+ export interface NuiMockOptions {
23
+ /**
24
+ * Expected FiveM resource name to intercept.
25
+ * If omitted, falls back to `getResourceName('')` or `'nui'`.
26
+ */
27
+ resourceName?: string;
28
+ /**
29
+ * Mock handlers for requests sent via `nui.request(eventName, payload)`.
30
+ * Return the response payload or a Promise resolving to it.
31
+ */
32
+ requests?: Record<string, (payload: any) => Promise<any> | any>;
33
+ /**
34
+ * Mock callbacks registered with `nui.notify(callbackName, payload)`.
35
+ */
36
+ callbacks?: Record<string, (payload: any) => void>;
37
+ /**
38
+ * Listeners invoked when UI sends fire-and-forget messages (`nui.send`).
39
+ */
40
+ onSend?: Record<string, (payload: any) => void>;
41
+ /**
42
+ * Delay in milliseconds to simulate network latency in the browser.
43
+ * @defaultValue 50
44
+ */
45
+ latencyMs?: number;
46
+ /**
47
+ * Whether to log mock events and requests in the browser console.
48
+ * @defaultValue true
49
+ */
50
+ log?: boolean;
51
+ }
52
+ /**
53
+ * Controller interface returned by {@link setupNuiMock} for controlling the mock runtime.
54
+ */
55
+ export interface NuiMockController {
56
+ /**
57
+ * Simulates an event dispatched from C#/server to NUI.
58
+ *
59
+ * @param eventName - Name of the simulated event.
60
+ * @param payload - Optional data payload.
61
+ * @param delayMs - Optional delay in milliseconds before dispatching.
62
+ */
63
+ emitEvent(eventName: string, payload?: unknown, delayMs?: number): void;
64
+ /**
65
+ * Simulates a window lifecycle action (`'open'`, `'close'`, `'focus'`, `'blur'`).
66
+ *
67
+ * @param action - The window lifecycle action.
68
+ * @param windowName - Optional target window identifier.
69
+ * @param delayMs - Optional delay in milliseconds before dispatching.
70
+ */
71
+ emitWindow(action: NuiWindowAction, windowName?: string, delayMs?: number): void;
72
+ /**
73
+ * Dynamically adds or updates a request mock handler.
74
+ *
75
+ * @param eventName - RPC request event name to intercept.
76
+ * @param handler - Handler function returning the mock response.
77
+ * @returns Unsubscribe function to remove the mock handler.
78
+ */
79
+ mockRequest<TRequest = unknown, TResponse = unknown>(eventName: string, handler: (payload: TRequest) => Promise<TResponse> | TResponse): () => void;
80
+ /**
81
+ * Removes a mock request handler.
82
+ *
83
+ * @param eventName - Name of the request to remove.
84
+ */
85
+ removeRequest(eventName: string): void;
86
+ /**
87
+ * Dynamically adds a listener for UI-sent messages (`nui.send`).
88
+ *
89
+ * @param eventName - Event name to listen for.
90
+ * @param handler - Callback invoked with the sent payload.
91
+ * @returns Unsubscribe function to remove the listener.
92
+ */
93
+ onSend<T = unknown>(eventName: string, handler: (payload: T) => void): () => void;
94
+ /**
95
+ * Restores original window.fetch and cleans up mock handlers.
96
+ */
97
+ destroy(): void;
98
+ }
99
+ export declare const NOOP_CONTROLLER: NuiMockController;
100
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mock/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;GAEG;AACH,oBAAY,cAAc;IACxB;;OAEG;IACH,KAAK,UAAU;IAEf;;OAEG;IACH,OAAO,YAAY;IAEnB;;OAEG;IACH,QAAQ,aAAa;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAEhE;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC;IAEnD;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC;IAEhD;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExE;;;;;;OAMG;IACH,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjF;;;;;;OAMG;IACH,WAAW,CAAC,QAAQ,GAAG,OAAO,EAAE,SAAS,GAAG,OAAO,EACjD,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,GAC7D,MAAM,IAAI,CAAC;IAEd;;;;OAIG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvC;;;;;;OAMG;IACH,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAElF;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,eAAO,MAAM,eAAe,EAAE,iBAO7B,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Message types for synthetic NUI postMessage envelopes in the mock environment.
3
+ */
4
+ export var NuiMessageType;
5
+ (function (NuiMessageType) {
6
+ /**
7
+ * Standard event message.
8
+ */
9
+ NuiMessageType["Event"] = "event";
10
+ /**
11
+ * RPC request message.
12
+ */
13
+ NuiMessageType["Request"] = "request";
14
+ /**
15
+ * RPC response message.
16
+ */
17
+ NuiMessageType["Response"] = "response";
18
+ })(NuiMessageType || (NuiMessageType = {}));
19
+ export const NOOP_CONTROLLER = {
20
+ emitEvent: () => { },
21
+ emitWindow: () => { },
22
+ mockRequest: () => () => { },
23
+ removeRequest: () => { },
24
+ onSend: () => () => { },
25
+ destroy: () => { }
26
+ };
27
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mock/types.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAN,IAAY,cAeX;AAfD,WAAY,cAAc;IACxB;;OAEG;IACH,iCAAe,CAAA;IAEf;;OAEG;IACH,qCAAmB,CAAA;IAEnB;;OAEG;IACH,uCAAqB,CAAA;AACvB,CAAC,EAfW,cAAc,KAAd,cAAc,QAezB;AAiGD,MAAM,CAAC,MAAM,eAAe,GAAsB;IAChD,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC;IACnB,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC;IACpB,WAAW,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC;IAC3B,aAAa,EAAE,GAAG,EAAE,GAAE,CAAC;IACvB,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC;IACtB,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;CAClB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Checks whether a given URL matches a targeted FiveM NUI endpoint:
3
+ * `https://<resourceName>/<callback>` or `https://cfx-nui-<resourceName>/<callback>`.
4
+ * Rejects localhost, IP addresses, ports, and external domains.
5
+ */
6
+ export declare function isNuiUrl(url: string, targetResource: string): boolean;
7
+ /**
8
+ * Extracts and safely decodes the resource name and callback endpoint from a NUI URL.
9
+ */
10
+ export declare function parseNuiUrl(url: string): {
11
+ resourceName: string;
12
+ callbackName: string;
13
+ };
14
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/mock/url.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAgBrE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAUvF"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Checks whether a given URL matches a targeted FiveM NUI endpoint:
3
+ * `https://<resourceName>/<callback>` or `https://cfx-nui-<resourceName>/<callback>`.
4
+ * Rejects localhost, IP addresses, ports, and external domains.
5
+ */
6
+ export function isNuiUrl(url, targetResource) {
7
+ try {
8
+ const parsed = new URL(url);
9
+ if (parsed.protocol !== 'https:' || parsed.port) {
10
+ return false;
11
+ }
12
+ const host = parsed.hostname.toLowerCase();
13
+ if (host === 'localhost' || host === '127.0.0.1' || host === '::1' || host.includes('.')) {
14
+ return false;
15
+ }
16
+ const expected = targetResource.toLowerCase();
17
+ return host === expected || host === `cfx-nui-${expected}`;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ /**
24
+ * Extracts and safely decodes the resource name and callback endpoint from a NUI URL.
25
+ */
26
+ export function parseNuiUrl(url) {
27
+ const urlParts = url.replace('https://', '').split('/');
28
+ const resourceName = urlParts[0];
29
+ let callbackName = urlParts[1] ?? 'nui';
30
+ try {
31
+ callbackName = decodeURIComponent(callbackName);
32
+ }
33
+ catch {
34
+ // malformed URI sequence, keep raw callbackName
35
+ }
36
+ return { resourceName, callbackName };
37
+ }
38
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/mock/url.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,cAAsB;IAC1D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC3C,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACzF,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,QAAQ,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;QAC9C,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,WAAW,QAAQ,EAAE,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxD,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,YAAY,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;IACxC,IAAI,CAAC;QACH,YAAY,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;IACD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AACxC,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { type ClickOutsideTarget, type NuiClickOutsideParameter } from '../actions/clickOutside';
2
+ export type { ClickOutsideTarget, NuiClickOutsideParameter };
3
+ /**
4
+ * Detects clicks outside a target element and invokes a callback.
5
+ * Automatically cleans up listeners on unmount.
6
+ *
7
+ * @param target - Getter returning the target DOM element.
8
+ * @param getOptions - Getter returning options (onClickOutside, ignore, enabled).
9
+ *
10
+ * @example
11
+ * ```svelte
12
+ * <script>
13
+ * let panelEl = $state<HTMLElement>();
14
+ * let triggerEl = $state<HTMLElement>();
15
+ * let isOpen = $state(false);
16
+ *
17
+ * useClickOutside(
18
+ * () => panelEl,
19
+ * () => ({
20
+ * onClickOutside: () => { isOpen = false; },
21
+ * ignore: [triggerEl],
22
+ * enabled: isOpen
23
+ * })
24
+ * );
25
+ * </script>
26
+ * ```
27
+ */
28
+ export declare function useClickOutside(target: () => Element | null | undefined, getOptions: () => NuiClickOutsideParameter): void;
29
+ //# sourceMappingURL=clickOutside.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clickOutside.svelte.d.ts","sourceRoot":"","sources":["../../src/runes/clickOutside.svelte.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC9B,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,OAAO,GAAG,IAAI,GAAG,SAAS,EACxC,UAAU,EAAE,MAAM,wBAAwB,GACzC,IAAI,CAeN"}
@@ -0,0 +1,42 @@
1
+ import { untrack } from 'svelte';
2
+ import { createClickOutsideHandler } from '../actions/clickOutside';
3
+ /**
4
+ * Detects clicks outside a target element and invokes a callback.
5
+ * Automatically cleans up listeners on unmount.
6
+ *
7
+ * @param target - Getter returning the target DOM element.
8
+ * @param getOptions - Getter returning options (onClickOutside, ignore, enabled).
9
+ *
10
+ * @example
11
+ * ```svelte
12
+ * <script>
13
+ * let panelEl = $state<HTMLElement>();
14
+ * let triggerEl = $state<HTMLElement>();
15
+ * let isOpen = $state(false);
16
+ *
17
+ * useClickOutside(
18
+ * () => panelEl,
19
+ * () => ({
20
+ * onClickOutside: () => { isOpen = false; },
21
+ * ignore: [triggerEl],
22
+ * enabled: isOpen
23
+ * })
24
+ * );
25
+ * </script>
26
+ * ```
27
+ */
28
+ export function useClickOutside(target, getOptions) {
29
+ const handler = createClickOutsideHandler(target, getOptions);
30
+ $effect(() => {
31
+ if (!target())
32
+ return;
33
+ const capture = untrack(() => getOptions().capture ?? true);
34
+ const ac = new AbortController();
35
+ document.addEventListener('pointerdown', handler, {
36
+ capture,
37
+ signal: ac.signal
38
+ });
39
+ return () => ac.abort();
40
+ });
41
+ }
42
+ //# sourceMappingURL=clickOutside.svelte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clickOutside.svelte.js","sourceRoot":"","sources":["../../src/runes/clickOutside.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,EACL,yBAAyB,EAG1B,MAAM,yBAAyB,CAAC;AAIjC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAwC,EACxC,UAA0C;IAE1C,MAAM,OAAO,GAAG,yBAAyB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAE9D,OAAO,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO;QAEtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;QAC5D,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,OAAO,EAAE;YAChD,OAAO;YACP,MAAM,EAAE,EAAE,CAAC,MAAM;SAClB,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { type NuiEscapeParameter, NuiEscapeTarget } from '../actions/escape';
2
+ export { NuiEscapeTarget };
3
+ export type NuiEscapeComposableParameter = Omit<NuiEscapeParameter, 'target'> & {
4
+ /**
5
+ * Where to attach the global listener:
6
+ * - `'document'` / `NuiEscapeTarget.Document`: listens globally on the document (default)
7
+ * - `'window'` / `NuiEscapeTarget.Window`: listens globally on the window
8
+ *
9
+ * Note: To scope Escape to a specific DOM element with focus, use the `nuiEscapeAction` action instead.
10
+ * @defaultValue NuiEscapeTarget.Document
11
+ */
12
+ target?: NuiEscapeTarget.Window | NuiEscapeTarget.Document;
13
+ };
14
+ export type NuiEscapeComposableInput = ((event: KeyboardEvent) => void) | NuiEscapeComposableParameter;
15
+ /**
16
+ * Listens for the Escape key and invokes a callback.
17
+ * Automatically cleans up listeners on unmount.
18
+ *
19
+ * @param getOptions - Getter returning options or an onEscape callback.
20
+ *
21
+ * @example
22
+ * ```svelte
23
+ * <script>
24
+ * let isOpen = $state(false);
25
+ *
26
+ * useEscape(() => ({
27
+ * onEscape: () => { isOpen = false; },
28
+ * enabled: isOpen
29
+ * }));
30
+ * </script>
31
+ * ```
32
+ */
33
+ export declare function useEscape(getOptions: () => NuiEscapeComposableInput): void;
34
+ //# sourceMappingURL=escape.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.svelte.d.ts","sourceRoot":"","sources":["../../src/runes/escape.svelte.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,kBAAkB,EACvB,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAAG;IAC9E;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC;CAC5D,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAChC,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC,GAChC,4BAA4B,CAAC;AAEjC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,wBAAwB,GACzC,IAAI,CAwBN"}
@@ -0,0 +1,44 @@
1
+ import { untrack } from 'svelte';
2
+ import { createEscapeHandler, toEscapeOptions, NuiEscapeTarget } from '../actions/escape';
3
+ export { NuiEscapeTarget };
4
+ /**
5
+ * Listens for the Escape key and invokes a callback.
6
+ * Automatically cleans up listeners on unmount.
7
+ *
8
+ * @param getOptions - Getter returning options or an onEscape callback.
9
+ *
10
+ * @example
11
+ * ```svelte
12
+ * <script>
13
+ * let isOpen = $state(false);
14
+ *
15
+ * useEscape(() => ({
16
+ * onEscape: () => { isOpen = false; },
17
+ * enabled: isOpen
18
+ * }));
19
+ * </script>
20
+ * ```
21
+ */
22
+ export function useEscape(getOptions) {
23
+ const normalized = () => toEscapeOptions(getOptions());
24
+ const handler = createEscapeHandler(normalized);
25
+ $effect(() => {
26
+ // Intentionally untracked: attach the DOM listener once upon mount,
27
+ // preserving event listener order. Reactive state (`enabled`, `onEscape`, etc.)
28
+ // is read lazily on each keydown event. Cleanup is called on component unmount.
29
+ const { target, capture } = untrack(() => {
30
+ const o = normalized();
31
+ return {
32
+ target: o?.target === NuiEscapeTarget.Window ? window : document,
33
+ capture: o?.capture ?? false
34
+ };
35
+ });
36
+ const ac = new AbortController();
37
+ target.addEventListener('keydown', handler, {
38
+ capture,
39
+ signal: ac.signal
40
+ });
41
+ return () => ac.abort();
42
+ });
43
+ }
44
+ //# sourceMappingURL=escape.svelte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.svelte.js","sourceRoot":"","sources":["../../src/runes/escape.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,EACL,mBAAmB,EACnB,eAAe,EAEf,eAAe,EAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,CAAC;AAkB3B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,SAAS,CACvB,UAA0C;IAE1C,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,eAAe,CAA+B,UAAU,EAAE,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAEhD,OAAO,CAAC,GAAG,EAAE;QACX,oEAAoE;QACpE,gFAAgF;QAChF,gFAAgF;QAChF,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;YACvC,MAAM,CAAC,GAAG,UAAU,EAAE,CAAC;YACvB,OAAO;gBACL,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;gBAChE,OAAO,EAAE,CAAC,EAAE,OAAO,IAAI,KAAK;aAC7B,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAwB,EAAE;YAC3D,OAAO;YACP,MAAM,EAAE,EAAE,CAAC,MAAM;SAClB,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type NuiFocusTrapInput, type NuiFocusTrapOptions, type FocusTrapAllowOutsideTarget, type FocusTrapAllowOutside } from '../actions/focusTrap';
2
+ export type { NuiFocusTrapInput, NuiFocusTrapOptions, FocusTrapAllowOutsideTarget, FocusTrapAllowOutside };
3
+ /**
4
+ * Traps Tab key navigation inside a container element.
5
+ * Automatically activates and tears down as the target element mounts/unmounts.
6
+ *
7
+ * @param target - Getter returning the container element.
8
+ * @param getOptions - Optional getter returning options or boolean enabled flag.
9
+ *
10
+ * @example
11
+ * ```svelte
12
+ * <script>
13
+ * let modalEl = $state<HTMLElement>();
14
+ * let isOpen = $state(false);
15
+ *
16
+ * useFocusTrap(() => modalEl, () => isOpen);
17
+ * </script>
18
+ * ```
19
+ */
20
+ export declare function useFocusTrap(target: () => HTMLElement | null | undefined, getOptions?: () => NuiFocusTrapInput): void;
21
+ //# sourceMappingURL=focusTrap.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focusTrap.svelte.d.ts","sourceRoot":"","sources":["../../src/runes/focusTrap.svelte.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC3B,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,2BAA2B,EAC3B,qBAAqB,EACtB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,EAC5C,UAAU,CAAC,EAAE,MAAM,iBAAiB,GACnC,IAAI,CAmBN"}
@@ -0,0 +1,37 @@
1
+ import { untrack } from 'svelte';
2
+ import { nuiFocusTrap } from '../actions/focusTrap';
3
+ /**
4
+ * Traps Tab key navigation inside a container element.
5
+ * Automatically activates and tears down as the target element mounts/unmounts.
6
+ *
7
+ * @param target - Getter returning the container element.
8
+ * @param getOptions - Optional getter returning options or boolean enabled flag.
9
+ *
10
+ * @example
11
+ * ```svelte
12
+ * <script>
13
+ * let modalEl = $state<HTMLElement>();
14
+ * let isOpen = $state(false);
15
+ *
16
+ * useFocusTrap(() => modalEl, () => isOpen);
17
+ * </script>
18
+ * ```
19
+ */
20
+ export function useFocusTrap(target, getOptions) {
21
+ let action;
22
+ $effect(() => {
23
+ const node = target();
24
+ if (!node)
25
+ return;
26
+ action = nuiFocusTrap(node, untrack(() => getOptions?.() ?? true));
27
+ return () => {
28
+ action?.destroy?.();
29
+ action = undefined;
30
+ };
31
+ });
32
+ $effect(() => {
33
+ const opts = getOptions?.() ?? true;
34
+ action?.update?.(opts);
35
+ });
36
+ }
37
+ //# sourceMappingURL=focusTrap.svelte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focusTrap.svelte.js","sourceRoot":"","sources":["../../src/runes/focusTrap.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjC,OAAO,EACL,YAAY,EAKb,MAAM,sBAAsB,CAAC;AAS9B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,YAAY,CAC1B,MAA4C,EAC5C,UAAoC;IAEpC,IAAI,MAAmD,CAAC;IAExD,OAAO,CAAC,GAAG,EAAE;QACX,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC;QAEnE,OAAO,GAAG,EAAE;YACV,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC;YACpB,MAAM,GAAG,SAAS,CAAC;QACrB,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,EAAE;QACX,MAAM,IAAI,GAAG,UAAU,EAAE,EAAE,IAAI,IAAI,CAAC;QACpC,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { useNuiState, NuiStateController, type NuiState, type NuiStateOptions } from './state.svelte';
2
+ export { useNuiQuery, NuiQueryController, type NuiQuery, type NuiQueryOptions, NuiQueryStatus } from './query.svelte';
3
+ export { useNuiWindow, NuiWindowController, type NuiWindow, type NuiWindowOptions, NuiWindowActionType, NuiWindowNotification } from './window.svelte';
4
+ export { useClickOutside } from './clickOutside.svelte';
5
+ export { useEscape, type NuiEscapeComposableParameter, type NuiEscapeComposableInput } from './escape.svelte';
6
+ export { useFocusTrap } from './focusTrap.svelte';
7
+ export { useLayer, type NuiLayerComposableInput } from './layer.svelte';
8
+ //# sourceMappingURL=index.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.svelte.d.ts","sourceRoot":"","sources":["../../src/runes/index.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,KAAK,QAAQ,EACb,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,cAAc,EACf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EACL,SAAS,EACT,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC9B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EACL,QAAQ,EACR,KAAK,uBAAuB,EAC7B,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { useNuiState, NuiStateController } from './state.svelte';
2
+ export { useNuiQuery, NuiQueryController, NuiQueryStatus } from './query.svelte';
3
+ export { useNuiWindow, NuiWindowController, NuiWindowActionType, NuiWindowNotification } from './window.svelte';
4
+ export { useClickOutside } from './clickOutside.svelte';
5
+ export { useEscape } from './escape.svelte';
6
+ export { useFocusTrap } from './focusTrap.svelte';
7
+ export { useLayer } from './layer.svelte';
8
+ //# sourceMappingURL=index.svelte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.svelte.js","sourceRoot":"","sources":["../../src/runes/index.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,kBAAkB,EAGnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,WAAW,EACX,kBAAkB,EAGlB,cAAc,EACf,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,YAAY,EACZ,mBAAmB,EAGnB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EACL,SAAS,EAGV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EACL,QAAQ,EAET,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { NuiLayerDismissReason, type NuiLayerInput, type NuiLayerOptions, type LayerInstance } from '../actions/layer';
2
+ export { NuiLayerDismissReason };
3
+ export type { NuiLayerInput, NuiLayerOptions, LayerInstance };
4
+ /**
5
+ * Reactive options getter for `useLayer`.
6
+ */
7
+ export type NuiLayerComposableInput = () => NuiLayerOptions;
8
+ /**
9
+ * Manages an overlay layer (modal, dialog, drawer) in FiveM NUI.
10
+ * Coordinates Escape key, outside click, and focus trapping through a central layer stack.
11
+ *
12
+ * @param target - Getter returning the container element.
13
+ * @param getOptions - Optional getter returning layer options.
14
+ *
15
+ * @example
16
+ * ```svelte
17
+ * <script>
18
+ * let modalEl = $state<HTMLElement>();
19
+ * let isOpen = $state(false);
20
+ *
21
+ * useLayer(
22
+ * () => modalEl,
23
+ * () => ({ onDismiss: () => { isOpen = false; }, enabled: isOpen })
24
+ * );
25
+ * </script>
26
+ *
27
+ * {#if isOpen}
28
+ * <div bind:this={modalEl} class="modal">
29
+ * <h2>Modal</h2>
30
+ * <button onclick={() => { isOpen = false; }}>Close</button>
31
+ * </div>
32
+ * {/if}
33
+ * ```
34
+ */
35
+ export declare function useLayer(target: () => HTMLElement | null | undefined, getOptions?: () => NuiLayerOptions): void;
36
+ //# sourceMappingURL=layer.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layer.svelte.d.ts","sourceRoot":"","sources":["../../src/runes/layer.svelte.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,qBAAqB,EACtB,CAAC;AAEF,YAAY,EACV,aAAa,EACb,eAAe,EACf,aAAa,EACd,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,eAAe,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS,EAC5C,UAAU,CAAC,EAAE,MAAM,eAAe,GACjC,IAAI,CAmBN"}