dirk-cfx-react 1.1.52 → 1.1.54

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/dist/index.js CHANGED
@@ -1,13 +1,14 @@
1
- import React3, { createContext, useEffect, useRef, useState, useContext, useLayoutEffect, useMemo } from 'react';
1
+ import { Flex, Text, Image as Image$1, createTheme, Box, Stack, Title as Title$1, Code, TextInput, Select, useMantineTheme, alpha, Progress, RingProgress, Portal, Button, Loader, MantineProvider, BackgroundImage, Group, JsonInput } from '@mantine/core';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import React4, { createContext, useContext, useEffect, useRef, useState, useMemo, useLayoutEffect } from 'react';
2
4
  import { create, useStore, createStore } from 'zustand';
3
5
  import axios from 'axios';
4
6
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
5
- import { Flex, Text, Image as Image$1, createTheme, Box, Stack, Title as Title$1, Code, useMantineTheme, alpha, Progress, RingProgress, Button, MantineProvider, BackgroundImage } from '@mantine/core';
6
- import { jsx, jsxs } from 'react/jsx-runtime';
7
7
  import { motion, AnimatePresence, useMotionValue } from 'framer-motion';
8
8
  import clickSoundUrl from './click_sound-PNCRRTM4.mp3';
9
9
  import hoverSoundUrl from './hover_sound-NBUA222C.mp3';
10
- import { useClickOutside } from '@mantine/hooks';
10
+ import { X, AlertTriangle, Trash2, Check, Undo2, Redo2, Save, History, XCircle, Code2, RotateCcw, Search, Filter, User, ChevronDown } from 'lucide-react';
11
+ import { QueryClient, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query';
11
12
  import '@mantine/core/styles.css';
12
13
  import '@mantine/notifications/styles.css';
13
14
  import './styles/fonts.css';
@@ -22,6 +23,1053 @@ import { fas } from '@fortawesome/free-solid-svg-icons';
22
23
  var __defProp = Object.defineProperty;
23
24
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
24
25
  var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value);
26
+ var BLIP_ENTRIES = [
27
+ [0, "radar_higher", "gif"],
28
+ [1, "radar_level", "png"],
29
+ [2, "radar_lower", "gif"],
30
+ [3, "radar_police_ped", "gif"],
31
+ [4, "radar_wanted_radius", "png"],
32
+ [5, "radar_area_blip", "png"],
33
+ [6, "radar_centre", "png"],
34
+ [7, "radar_north", "png"],
35
+ [8, "radar_waypoint", "png"],
36
+ [9, "radar_radius_blip", "png"],
37
+ [10, "radar_radius_outline_blip", "png"],
38
+ [11, "radar_weapon_higher", "gif"],
39
+ [12, "radar_weapon_lower", "gif"],
40
+ [13, "radar_higher_ai", "gif"],
41
+ [14, "radar_lower_ai", "gif"],
42
+ [15, "radar_police_heli_spin", "gif"],
43
+ [16, "radar_police_plane_move", "png"],
44
+ [27, "radar_mp_crew", "png"],
45
+ [28, "radar_mp_friendlies", "png"],
46
+ [36, "radar_cable_car", "png"],
47
+ [37, "radar_activities", "png"],
48
+ [38, "radar_raceflag", "png"],
49
+ [40, "radar_safehouse", "png"],
50
+ [41, "radar_police", "gif"],
51
+ [42, "radar_police_chase", "gif"],
52
+ [43, "radar_police_heli", "png"],
53
+ [44, "radar_bomb_a", "png"],
54
+ [47, "radar_snitch", "png"],
55
+ [48, "radar_planning_locations", "png"],
56
+ [50, "radar_crim_carsteal", "png"],
57
+ [51, "radar_crim_drugs", "png"],
58
+ [52, "radar_crim_holdups", "png"],
59
+ [54, "radar_crim_player", "png"],
60
+ [56, "radar_cop_patrol", "png"],
61
+ [57, "radar_cop_player", "png"],
62
+ [58, "radar_crim_wanted", "png"],
63
+ [59, "radar_heist", "png"],
64
+ [60, "radar_police_station", "png"],
65
+ [61, "radar_hospital", "png"],
66
+ [62, "radar_assassins_mark", "png"],
67
+ [63, "radar_elevator", "png"],
68
+ [64, "radar_helicopter", "png"],
69
+ [66, "radar_random_character", "png"],
70
+ [67, "radar_security_van", "png"],
71
+ [68, "radar_tow_truck", "png"],
72
+ [70, "radar_illegal_parking", "png"],
73
+ [71, "radar_barber", "png"],
74
+ [72, "radar_car_mod_shop", "png"],
75
+ [73, "radar_clothes_store", "png"],
76
+ [75, "radar_tattoo", "png"],
77
+ [76, "radar_armenian_family", "png"],
78
+ [77, "radar_lester_family", "png"],
79
+ [78, "radar_michael_family", "png"],
80
+ [79, "radar_trevor_family", "png"],
81
+ [80, "radar_jewelry_heist", "png"],
82
+ [82, "radar_drag_race_finish", "png"],
83
+ [84, "radar_rampage", "png"],
84
+ [85, "radar_vinewood_tours", "png"],
85
+ [86, "radar_lamar_family", "png"],
86
+ [88, "radar_franklin_family", "png"],
87
+ [89, "radar_chinese_strand", "png"],
88
+ [90, "radar_flight_school", "png"],
89
+ [91, "radar_eye_sky", "png"],
90
+ [92, "radar_air_hockey", "png"],
91
+ [93, "radar_bar", "png"],
92
+ [94, "radar_base_jump", "png"],
93
+ [95, "radar_basketball", "png"],
94
+ [96, "radar_biolab_heist", "png"],
95
+ [99, "radar_cabaret_club", "png"],
96
+ [100, "radar_car_wash", "png"],
97
+ [102, "radar_comedy_club", "png"],
98
+ [103, "radar_darts", "png"],
99
+ [104, "radar_docks_heist", "png"],
100
+ [105, "radar_fbi_heist", "png"],
101
+ [106, "radar_fbi_officers_strand", "png"],
102
+ [107, "radar_finale_bank_heist", "png"],
103
+ [108, "radar_financier_strand", "png"],
104
+ [109, "radar_golf", "png"],
105
+ [110, "radar_gun_shop", "png"],
106
+ [111, "radar_internet_cafe", "png"],
107
+ [112, "radar_michael_family_exile", "png"],
108
+ [113, "radar_nice_house_heist", "png"],
109
+ [114, "radar_random_female", "png"],
110
+ [115, "radar_random_male", "png"],
111
+ [118, "radar_rural_bank_heist", "png"],
112
+ [119, "radar_shooting_range", "png"],
113
+ [120, "radar_solomon_strand", "png"],
114
+ [121, "radar_strip_club", "png"],
115
+ [122, "radar_tennis", "png"],
116
+ [123, "radar_trevor_family_exile", "png"],
117
+ [124, "radar_michael_trevor_family", "png"],
118
+ [126, "radar_triathlon", "png"],
119
+ [127, "radar_off_road_racing", "png"],
120
+ [128, "radar_gang_cops", "png"],
121
+ [129, "radar_gang_mexicans", "png"],
122
+ [130, "radar_gang_bikers", "png"],
123
+ [133, "radar_snitch_red", "png"],
124
+ [134, "radar_crim_cuff_keys", "png"],
125
+ [135, "radar_cinema", "png"],
126
+ [136, "radar_music_venue", "png"],
127
+ [137, "radar_police_station_blue", "png"],
128
+ [138, "radar_airport", "png"],
129
+ [139, "radar_crim_saved_vehicle", "png"],
130
+ [140, "radar_weed_stash", "png"],
131
+ [141, "radar_hunting", "png"],
132
+ [142, "radar_pool", "png"],
133
+ [143, "radar_objective_blue", "png"],
134
+ [144, "radar_objective_green", "png"],
135
+ [145, "radar_objective_red", "png"],
136
+ [146, "radar_objective_yellow", "png"],
137
+ [147, "radar_arms_dealing", "png"],
138
+ [148, "radar_mp_friend", "png"],
139
+ [149, "radar_celebrity_theft", "png"],
140
+ [150, "radar_weapon_assault_rifle", "png"],
141
+ [151, "radar_weapon_bat", "png"],
142
+ [152, "radar_weapon_grenade", "png"],
143
+ [153, "radar_weapon_health", "png"],
144
+ [154, "radar_weapon_knife", "png"],
145
+ [155, "radar_weapon_molotov", "png"],
146
+ [156, "radar_weapon_pistol", "png"],
147
+ [157, "radar_weapon_rocket", "png"],
148
+ [158, "radar_weapon_shotgun", "png"],
149
+ [159, "radar_weapon_smg", "png"],
150
+ [160, "radar_weapon_sniper", "png"],
151
+ [161, "radar_mp_noise", "gif"],
152
+ [162, "radar_poi", "png"],
153
+ [163, "radar_passive", "png"],
154
+ [164, "radar_usingmenu", "png"],
155
+ [171, "radar_gang_cops_partner", "png"],
156
+ [173, "radar_weapon_minigun", "png"],
157
+ [175, "radar_weapon_armour", "png"],
158
+ [176, "radar_property_takeover", "png"],
159
+ [177, "radar_gang_mexicans_highlight", "png"],
160
+ [178, "radar_gang_bikers_highlight", "png"],
161
+ [179, "radar_triathlon_cycling", "png"],
162
+ [180, "radar_triathlon_swimming", "png"],
163
+ [181, "radar_property_takeover_bikers", "png"],
164
+ [182, "radar_property_takeover_cops", "png"],
165
+ [183, "radar_property_takeover_vagos", "png"],
166
+ [184, "radar_camera", "png"],
167
+ [185, "radar_centre_red", "png"],
168
+ [186, "radar_handcuff_keys_bikers", "png"],
169
+ [187, "radar_handcuff_keys_vagos", "png"],
170
+ [188, "radar_handcuffs_closed_bikers", "png"],
171
+ [189, "radar_handcuffs_closed_vagos", "png"],
172
+ [192, "radar_camera_badger", "png"],
173
+ [193, "radar_camera_facade", "png"],
174
+ [194, "radar_camera_ifruit", "png"],
175
+ [197, "radar_yoga", "png"],
176
+ [198, "radar_taxi", "png"],
177
+ [205, "radar_shrink", "png"],
178
+ [206, "radar_epsilon", "png"],
179
+ [207, "radar_financier_strand_grey", "png"],
180
+ [208, "radar_trevor_family_grey", "png"],
181
+ [209, "radar_trevor_family_red", "png"],
182
+ [210, "radar_franklin_family_grey", "png"],
183
+ [211, "radar_franklin_family_blue", "png"],
184
+ [212, "radar_franklin_a", "png"],
185
+ [213, "radar_franklin_b", "png"],
186
+ [214, "radar_franklin_c", "png"],
187
+ [225, "radar_gang_vehicle", "png"],
188
+ [226, "radar_gang_vehicle_bikers", "png"],
189
+ [227, "radar_gang_vehicle_cops", "png"],
190
+ [228, "radar_gang_vehicle_vagos", "png"],
191
+ [229, "radar_guncar", "png"],
192
+ [230, "radar_driving_bikers", "png"],
193
+ [231, "radar_driving_cops", "png"],
194
+ [232, "radar_driving_vagos", "png"],
195
+ [233, "radar_gang_cops_highlight", "png"],
196
+ [234, "radar_shield_bikers", "png"],
197
+ [235, "radar_shield_cops", "png"],
198
+ [236, "radar_shield_vagos", "png"],
199
+ [237, "radar_custody_bikers", "png"],
200
+ [238, "radar_custody_vagos", "png"],
201
+ [251, "radar_arms_dealing_air", "png"],
202
+ [252, "radar_playerstate_arrested", "png"],
203
+ [253, "radar_playerstate_custody", "png"],
204
+ [254, "radar_playerstate_driving", "png"],
205
+ [255, "radar_playerstate_keyholder", "png"],
206
+ [256, "radar_playerstate_partner", "png"],
207
+ [262, "radar_ztype", "png"],
208
+ [263, "radar_stinger", "png"],
209
+ [264, "radar_packer", "png"],
210
+ [265, "radar_monroe", "png"],
211
+ [266, "radar_fairground", "png"],
212
+ [267, "radar_property", "png"],
213
+ [268, "radar_gang_highlight", "png"],
214
+ [269, "radar_altruist", "png"],
215
+ [270, "radar_ai", "png"],
216
+ [271, "radar_on_mission", "png"],
217
+ [272, "radar_cash_pickup", "png"],
218
+ [273, "radar_chop", "png"],
219
+ [274, "radar_dead", "png"],
220
+ [275, "radar_territory_locked", "png"],
221
+ [276, "radar_cash_lost", "png"],
222
+ [277, "radar_cash_vagos", "png"],
223
+ [278, "radar_cash_cops", "png"],
224
+ [279, "radar_hooker", "png"],
225
+ [280, "radar_friend", "png"],
226
+ [281, "radar_mission_2to4", "png"],
227
+ [282, "radar_mission_2to8", "png"],
228
+ [283, "radar_mission_2to12", "png"],
229
+ [284, "radar_mission_2to16", "png"],
230
+ [285, "radar_custody_dropoff", "png"],
231
+ [286, "radar_onmission_cops", "png"],
232
+ [287, "radar_onmission_lost", "png"],
233
+ [288, "radar_onmission_vagos", "png"],
234
+ [289, "radar_crim_carsteal_cops", "png"],
235
+ [290, "radar_crim_carsteal_bikers", "png"],
236
+ [291, "radar_crim_carsteal_vagos", "png"],
237
+ [292, "radar_band_strand", "png"],
238
+ [293, "radar_simeon_family", "png"],
239
+ [294, "radar_mission_1", "png"],
240
+ [295, "radar_mission_2", "png"],
241
+ [296, "radar_friend_darts", "png"],
242
+ [297, "radar_friend_comedyclub", "png"],
243
+ [298, "radar_friend_cinema", "png"],
244
+ [299, "radar_friend_tennis", "png"],
245
+ [300, "radar_friend_stripclub", "png"],
246
+ [301, "radar_friend_livemusic", "png"],
247
+ [302, "radar_friend_golf", "png"],
248
+ [303, "radar_bounty_hit", "png"],
249
+ [304, "radar_ugc_mission", "png"],
250
+ [305, "radar_horde", "png"],
251
+ [306, "radar_cratedrop", "png"],
252
+ [307, "radar_plane_drop", "png"],
253
+ [308, "radar_sub", "png"],
254
+ [309, "radar_race", "png"],
255
+ [310, "radar_deathmatch", "png"],
256
+ [311, "radar_arm_wrestling", "png"],
257
+ [312, "radar_mission_1to2", "png"],
258
+ [313, "radar_shootingrange_gunshop", "png"],
259
+ [314, "radar_race_air", "png"],
260
+ [315, "radar_race_land", "png"],
261
+ [316, "radar_race_sea", "png"],
262
+ [317, "radar_tow", "png"],
263
+ [318, "radar_garbage", "png"],
264
+ [319, "radar_drill", "png"],
265
+ [320, "radar_spikes", "png"],
266
+ [321, "radar_firetruck", "png"],
267
+ [322, "radar_minigun2", "png"],
268
+ [323, "radar_bugstar", "png"],
269
+ [324, "radar_submarine", "png"],
270
+ [325, "radar_chinook", "png"],
271
+ [326, "radar_getaway_car", "png"],
272
+ [327, "radar_mission_bikers_1", "png"],
273
+ [328, "radar_mission_bikers_1to2", "png"],
274
+ [329, "radar_mission_bikers_2", "png"],
275
+ [330, "radar_mission_bikers_2to4", "png"],
276
+ [331, "radar_mission_bikers_2to8", "png"],
277
+ [332, "radar_mission_bikers_2to12", "png"],
278
+ [333, "radar_mission_bikers_2to16", "png"],
279
+ [334, "radar_mission_cops_1", "png"],
280
+ [335, "radar_mission_cops_1to2", "png"],
281
+ [336, "radar_mission_cops_2", "png"],
282
+ [337, "radar_mission_cops_2to4", "png"],
283
+ [338, "radar_mission_cops_2to8", "png"],
284
+ [339, "radar_mission_cops_2to12", "png"],
285
+ [340, "radar_mission_cops_2to16", "png"],
286
+ [341, "radar_mission_vagos_1", "png"],
287
+ [342, "radar_mission_vagos_1to2", "png"],
288
+ [343, "radar_mission_vagos_2", "png"],
289
+ [344, "radar_mission_vagos_2to4", "png"],
290
+ [345, "radar_mission_vagos_2to8", "png"],
291
+ [346, "radar_mission_vagos_2to12", "png"],
292
+ [347, "radar_mission_vagos_2to16", "png"],
293
+ [348, "radar_gang_bike", "png"],
294
+ [349, "radar_gas_grenade", "png"],
295
+ [350, "radar_property_for_sale", "png"],
296
+ [351, "radar_gang_attack_package", "png"],
297
+ [352, "radar_martin_madrazzo", "png"],
298
+ [353, "radar_enemy_heli_spin", "gif"],
299
+ [354, "radar_boost", "png"],
300
+ [355, "radar_devin", "png"],
301
+ [356, "radar_dock", "png"],
302
+ [357, "radar_garage", "png"],
303
+ [358, "radar_golf_flag", "png"],
304
+ [359, "radar_hangar", "png"],
305
+ [360, "radar_helipad", "png"],
306
+ [361, "radar_jerry_can", "png"],
307
+ [362, "radar_mask", "png"],
308
+ [363, "radar_heist_prep", "png"],
309
+ [364, "radar_incapacitated", "png"],
310
+ [365, "radar_spawn_point_pickup", "png"],
311
+ [366, "radar_boilersuit", "png"],
312
+ [367, "radar_completed", "png"],
313
+ [368, "radar_rockets", "png"],
314
+ [369, "radar_garage_for_sale", "png"],
315
+ [370, "radar_helipad_for_sale", "png"],
316
+ [371, "radar_dock_for_sale", "png"],
317
+ [372, "radar_hangar_for_sale", "png"],
318
+ [373, "radar_placeholder_6", "png"],
319
+ [374, "radar_business", "png"],
320
+ [375, "radar_business_for_sale", "png"],
321
+ [376, "radar_race_bike", "png"],
322
+ [377, "radar_parachute", "png"],
323
+ [378, "radar_team_deathmatch", "png"],
324
+ [379, "radar_race_foot", "png"],
325
+ [380, "radar_vehicle_deathmatch", "png"],
326
+ [381, "radar_barry", "png"],
327
+ [382, "radar_dom", "png"],
328
+ [383, "radar_maryann", "png"],
329
+ [384, "radar_cletus", "png"],
330
+ [385, "radar_josh", "png"],
331
+ [386, "radar_minute", "png"],
332
+ [387, "radar_omega", "png"],
333
+ [388, "radar_tonya", "png"],
334
+ [389, "radar_paparazzo", "png"],
335
+ [390, "radar_aim", "png"],
336
+ [391, "radar_cratedrop_background", "png"],
337
+ [392, "radar_green_and_net_player1", "png"],
338
+ [393, "radar_green_and_net_player2", "png"],
339
+ [394, "radar_green_and_net_player3", "png"],
340
+ [395, "radar_green_and_friendly", "png"],
341
+ [396, "radar_net_player1_and_net_player2", "png"],
342
+ [397, "radar_net_player1_and_net_player3", "png"],
343
+ [398, "radar_creator", "png"],
344
+ [399, "radar_creator_direction", "png"],
345
+ [400, "radar_abigail", "png"],
346
+ [401, "radar_blimp", "png"],
347
+ [402, "radar_repair", "png"],
348
+ [403, "radar_testosterone", "png"],
349
+ [404, "radar_dinghy", "png"],
350
+ [405, "radar_fanatic", "png"],
351
+ [407, "radar_info_icon", "png"],
352
+ [408, "radar_capture_the_flag", "png"],
353
+ [409, "radar_last_team_standing", "png"],
354
+ [410, "radar_boat", "png"],
355
+ [411, "radar_capture_the_flag_base", "png"],
356
+ [412, "radar_mp_crew", "png"],
357
+ [413, "radar_capture_the_flag_outline", "png"],
358
+ [414, "radar_capture_the_flag_base_nobag", "png"],
359
+ [415, "radar_weapon_jerrycan", "png"],
360
+ [416, "radar_rp", "png"],
361
+ [417, "radar_level_inside", "png"],
362
+ [418, "radar_bounty_hit_inside", "png"],
363
+ [419, "radar_capture_the_usaflag", "png"],
364
+ [420, "radar_capture_the_usaflag_outline", "png"],
365
+ [421, "radar_tank", "png"],
366
+ [422, "radar_player_heli", "gif"],
367
+ [423, "radar_player_plane", "png"],
368
+ [424, "radar_player_jet", "png"],
369
+ [425, "radar_centre_stroke", "png"],
370
+ [426, "radar_player_guncar", "png"],
371
+ [427, "radar_player_boat", "png"],
372
+ [428, "radar_mp_heist", "png"],
373
+ [429, "radar_temp_1", "png"],
374
+ [430, "radar_temp_2", "png"],
375
+ [431, "radar_temp_3", "png"],
376
+ [432, "radar_temp_4", "png"],
377
+ [433, "radar_temp_5", "png"],
378
+ [434, "radar_temp_6", "png"],
379
+ [435, "radar_race_stunt", "png"],
380
+ [436, "radar_hot_property", "png"],
381
+ [437, "radar_urbanwarfare_versus", "png"],
382
+ [438, "radar_king_of_the_castle", "png"],
383
+ [439, "radar_player_king", "png"],
384
+ [440, "radar_dead_drop", "png"],
385
+ [441, "radar_penned_in", "png"],
386
+ [442, "radar_beast", "png"],
387
+ [443, "radar_edge_pointer", "png"],
388
+ [444, "radar_edge_crosstheline", "png"],
389
+ [445, "radar_mp_lamar", "png"],
390
+ [446, "radar_bennys", "png"],
391
+ [447, "radar_corner_number_1", "png"],
392
+ [448, "radar_corner_number_2", "png"],
393
+ [449, "radar_corner_number_3", "png"],
394
+ [450, "radar_corner_number_4", "png"],
395
+ [451, "radar_corner_number_5", "png"],
396
+ [452, "radar_corner_number_6", "png"],
397
+ [453, "radar_corner_number_7", "png"],
398
+ [454, "radar_corner_number_8", "png"],
399
+ [455, "radar_yacht", "png"],
400
+ [456, "radar_finders_keepers", "png"],
401
+ [457, "radar_assault_package", "png"],
402
+ [458, "radar_hunt_the_boss", "png"],
403
+ [459, "radar_sightseer", "png"],
404
+ [460, "radar_turreted_limo", "png"],
405
+ [461, "radar_belly_of_the_beast", "png"],
406
+ [462, "radar_yacht_location", "png"],
407
+ [463, "radar_pickup_beast", "png"],
408
+ [464, "radar_pickup_zoned", "png"],
409
+ [465, "radar_pickup_random", "png"],
410
+ [466, "radar_pickup_slow_time", "png"],
411
+ [467, "radar_pickup_swap", "png"],
412
+ [468, "radar_pickup_thermal", "png"],
413
+ [469, "radar_pickup_weed", "png"],
414
+ [470, "radar_weapon_railgun", "png"],
415
+ [471, "radar_seashark", "png"],
416
+ [472, "radar_pickup_hidden", "png"],
417
+ [473, "radar_warehouse", "png"],
418
+ [474, "radar_warehouse_for_sale", "png"],
419
+ [475, "radar_office", "png"],
420
+ [476, "radar_office_for_sale", "png"],
421
+ [477, "radar_truck", "png"],
422
+ [478, "radar_contraband", "png"],
423
+ [479, "radar_trailer", "png"],
424
+ [480, "radar_vip", "png"],
425
+ [481, "radar_cargobob", "png"],
426
+ [482, "radar_area_outline_blip", "png"],
427
+ [483, "radar_pickup_accelerator", "png"],
428
+ [484, "radar_pickup_ghost", "png"],
429
+ [485, "radar_pickup_detonator", "png"],
430
+ [486, "radar_pickup_bomb", "png"],
431
+ [487, "radar_pickup_armoured", "png"],
432
+ [488, "radar_stunt", "png"],
433
+ [489, "radar_weapon_lives", "png"],
434
+ [490, "radar_stunt_premium", "png"],
435
+ [491, "radar_adversary", "png"],
436
+ [492, "radar_biker_clubhouse", "png"],
437
+ [493, "radar_biker_caged_in", "png"],
438
+ [494, "radar_biker_turf_war", "png"],
439
+ [495, "radar_biker_joust", "png"],
440
+ [496, "radar_production_weed", "png"],
441
+ [497, "radar_production_crack", "png"],
442
+ [498, "radar_production_fake_id", "png"],
443
+ [499, "radar_production_meth", "png"],
444
+ [500, "radar_production_money", "png"],
445
+ [501, "radar_package", "png"],
446
+ [502, "radar_capture_1", "png"],
447
+ [503, "radar_capture_2", "png"],
448
+ [504, "radar_capture_3", "png"],
449
+ [505, "radar_capture_4", "png"],
450
+ [506, "radar_capture_5", "png"],
451
+ [507, "radar_capture_6", "png"],
452
+ [508, "radar_capture_7", "png"],
453
+ [509, "radar_capture_8", "png"],
454
+ [510, "radar_capture_9", "png"],
455
+ [511, "radar_capture_10", "png"],
456
+ [512, "radar_quad", "png"],
457
+ [513, "radar_bus", "png"],
458
+ [514, "radar_drugs_package", "png"],
459
+ [515, "radar_pickup_jump", "png"],
460
+ [516, "radar_adversary_4", "png"],
461
+ [517, "radar_adversary_8", "png"],
462
+ [518, "radar_adversary_10", "png"],
463
+ [519, "radar_adversary_12", "png"],
464
+ [520, "radar_adversary_16", "png"],
465
+ [521, "radar_laptop", "png"],
466
+ [522, "radar_pickup_deadline", "png"],
467
+ [523, "radar_sports_car", "png"],
468
+ [524, "radar_warehouse_vehicle", "png"],
469
+ [525, "radar_reg_papers", "png"],
470
+ [526, "radar_police_station_dropoff", "png"],
471
+ [527, "radar_junkyard", "png"],
472
+ [528, "radar_ex_vech_1", "png"],
473
+ [529, "radar_ex_vech_2", "png"],
474
+ [530, "radar_ex_vech_3", "png"],
475
+ [531, "radar_ex_vech_4", "png"],
476
+ [532, "radar_ex_vech_5", "png"],
477
+ [533, "radar_ex_vech_6", "png"],
478
+ [534, "radar_ex_vech_7", "png"],
479
+ [535, "radar_target_a", "png"],
480
+ [536, "radar_target_b", "png"],
481
+ [537, "radar_target_c", "png"],
482
+ [538, "radar_target_d", "png"],
483
+ [539, "radar_target_e", "png"],
484
+ [540, "radar_target_f", "png"],
485
+ [541, "radar_target_g", "png"],
486
+ [542, "radar_target_h", "png"],
487
+ [543, "radar_jugg", "png"],
488
+ [544, "radar_pickup_repair", "png"],
489
+ [545, "radar_steeringwheel", "png"],
490
+ [546, "radar_trophy", "png"],
491
+ [547, "radar_pickup_rocket_boost", "png"],
492
+ [548, "radar_pickup_homing_rocket", "png"],
493
+ [549, "radar_pickup_machinegun", "png"],
494
+ [550, "radar_pickup_parachute", "png"],
495
+ [551, "radar_pickup_time_5", "png"],
496
+ [552, "radar_pickup_time_10", "png"],
497
+ [553, "radar_pickup_time_15", "png"],
498
+ [554, "radar_pickup_time_20", "png"],
499
+ [555, "radar_pickup_time_30", "png"],
500
+ [556, "radar_supplies", "png"],
501
+ [557, "radar_property_bunker", "png"],
502
+ [558, "radar_gr_wvm_1", "png"],
503
+ [559, "radar_gr_wvm_2", "png"],
504
+ [560, "radar_gr_wvm_3", "png"],
505
+ [561, "radar_gr_wvm_4", "png"],
506
+ [562, "radar_gr_wvm_5", "png"],
507
+ [563, "radar_gr_wvm_6", "png"],
508
+ [564, "radar_gr_covert_ops", "png"],
509
+ [565, "radar_adversary_bunker", "png"],
510
+ [566, "radar_gr_moc_upgrade", "png"],
511
+ [567, "radar_gr_w_upgrade", "png"],
512
+ [568, "radar_sm_cargo", "png"],
513
+ [569, "radar_sm_hangar", "png"],
514
+ [570, "radar_tf_checkpoint", "png"],
515
+ [571, "radar_race_tf", "png"],
516
+ [572, "radar_sm_wp1", "png"],
517
+ [573, "radar_sm_wp2", "png"],
518
+ [574, "radar_sm_wp3", "png"],
519
+ [575, "radar_sm_wp4", "png"],
520
+ [576, "radar_sm_wp5", "png"],
521
+ [577, "radar_sm_wp6", "png"],
522
+ [578, "radar_sm_wp7", "png"],
523
+ [579, "radar_sm_wp8", "png"],
524
+ [580, "radar_sm_wp9", "png"],
525
+ [581, "radar_sm_wp10", "png"],
526
+ [582, "radar_sm_wp11", "png"],
527
+ [583, "radar_sm_wp12", "png"],
528
+ [584, "radar_sm_wp13", "png"],
529
+ [585, "radar_sm_wp14", "png"],
530
+ [586, "radar_nhp_bag", "png"],
531
+ [587, "radar_nhp_chest", "png"],
532
+ [588, "radar_nhp_orbit", "png"],
533
+ [589, "radar_nhp_veh1", "png"],
534
+ [590, "radar_nhp_base", "png"],
535
+ [591, "radar_nhp_overlay", "png"],
536
+ [592, "radar_nhp_turret", "png"],
537
+ [593, "radar_nhp_mg_firewall", "png"],
538
+ [594, "radar_nhp_mg_node", "png"],
539
+ [595, "radar_nhp_wp1", "png"],
540
+ [596, "radar_nhp_wp2", "png"],
541
+ [597, "radar_nhp_wp3", "png"],
542
+ [598, "radar_nhp_wp4", "png"],
543
+ [599, "radar_nhp_wp5", "png"],
544
+ [600, "radar_nhp_wp6", "png"],
545
+ [601, "radar_nhp_wp7", "png"],
546
+ [602, "radar_nhp_wp8", "png"],
547
+ [603, "radar_nhp_wp9", "png"],
548
+ [604, "radar_nhp_cctv", "png"],
549
+ [605, "radar_nhp_starterpack", "png"],
550
+ [606, "radar_nhp_turret_console", "png"],
551
+ [607, "radar_nhp_mg_mir_rotate", "png"],
552
+ [608, "radar_nhp_mg_mir_static", "png"],
553
+ [609, "radar_nhp_mg_proxy", "png"],
554
+ [610, "radar_acsr_race_target", "png"],
555
+ [611, "radar_acsr_race_hotring", "png"],
556
+ [612, "radar_acsr_wp1", "png"],
557
+ [613, "radar_acsr_wp2", "png"],
558
+ [614, "radar_bat_club_property", "png"],
559
+ [615, "radar_bat_cargo", "png"],
560
+ [616, "radar_bat_truck", "png"],
561
+ [617, "radar_bat_hack_jewel", "png"],
562
+ [618, "radar_bat_hack_gold", "png"],
563
+ [619, "radar_bat_keypad", "png"],
564
+ [620, "radar_bat_hack_target", "png"],
565
+ [621, "radar_pickup_dtb_health", "png"],
566
+ [622, "radar_pickup_dtb_blast_increase", "png"],
567
+ [623, "radar_pickup_dtb_blast_decrease", "png"],
568
+ [624, "radar_pickup_dtb_bomb_increase", "png"],
569
+ [625, "radar_pickup_dtb_bomb_decrease", "png"],
570
+ [626, "radar_bat_rival_club", "png"],
571
+ [627, "radar_bat_drone", "png"],
572
+ [628, "radar_bat_cash_reg", "png"],
573
+ [629, "radar_cctv", "png"],
574
+ [630, "radar_bat_assassinate", "png"],
575
+ [631, "radar_bat_pbus", "png"],
576
+ [632, "radar_bat_wp1", "png"],
577
+ [633, "radar_bat_wp2", "png"],
578
+ [634, "radar_bat_wp3", "png"],
579
+ [635, "radar_bat_wp4", "png"],
580
+ [636, "radar_bat_wp5", "png"],
581
+ [637, "radar_bat_wp6", "png"],
582
+ [638, "radar_blimp_2", "png"],
583
+ [639, "radar_oppressor_2", "png"],
584
+ [640, "radar_bat_wp7", "png"],
585
+ [641, "radar_arena_series", "png"],
586
+ [642, "radar_arena_premium", "png"],
587
+ [643, "radar_arena_workshop", "png"],
588
+ [644, "radar_race_wars", "png"],
589
+ [645, "radar_arena_turret", "png"],
590
+ [646, "radar_arena_rc_car", "png"],
591
+ [647, "radar_arena_rc_workshop", "png"],
592
+ [648, "radar_arena_trap_fire", "png"],
593
+ [649, "radar_arena_trap_flip", "png"],
594
+ [650, "radar_arena_trap_sea", "png"],
595
+ [651, "radar_arena_trap_turn", "png"],
596
+ [652, "radar_arena_trap_pit", "png"],
597
+ [653, "radar_arena_trap_mine", "png"],
598
+ [654, "radar_arena_trap_bomb", "png"],
599
+ [655, "radar_arena_trap_wall", "png"],
600
+ [656, "radar_arena_trap_brd", "png"],
601
+ [657, "radar_arena_trap_sbrd", "png"],
602
+ [658, "radar_arena_bruiser", "png"],
603
+ [659, "radar_arena_brutus", "png"],
604
+ [660, "radar_arena_cerberus", "png"],
605
+ [661, "radar_arena_deathbike", "png"],
606
+ [662, "radar_arena_dominator", "png"],
607
+ [663, "radar_arena_impaler", "png"],
608
+ [664, "radar_arena_imperator", "png"],
609
+ [665, "radar_arena_issi", "png"],
610
+ [666, "radar_arena_sasquatch", "png"],
611
+ [667, "radar_arena_scarab", "png"],
612
+ [668, "radar_arena_slamvan", "png"],
613
+ [669, "radar_arena_zr380", "png"],
614
+ [670, "radar_ap", "png"],
615
+ [671, "radar_comic_store", "png"],
616
+ [672, "radar_cop_car", "png"],
617
+ [673, "radar_rc_time_trials", "png"],
618
+ [674, "radar_king_of_the_hill", "png"],
619
+ [675, "radar_king_of_the_hill_teams", "png"],
620
+ [676, "radar_rucksack", "png"],
621
+ [677, "radar_shipping_container", "png"],
622
+ [678, "radar_agatha", "png"],
623
+ [679, "radar_casino", "png"],
624
+ [680, "radar_casino_table_games", "png"],
625
+ [681, "radar_casino_wheel", "png"],
626
+ [682, "radar_casino_concierge", "png"],
627
+ [683, "radar_casino_chips", "png"],
628
+ [684, "radar_casino_horse_racing", "png"],
629
+ [685, "radar_adversary_featured", "png"],
630
+ [686, "radar_roulette_1", "png"],
631
+ [687, "radar_roulette_2", "png"],
632
+ [688, "radar_roulette_3", "png"],
633
+ [689, "radar_roulette_4", "png"],
634
+ [690, "radar_roulette_5", "png"],
635
+ [691, "radar_roulette_6", "png"],
636
+ [692, "radar_roulette_7", "png"],
637
+ [693, "radar_roulette_8", "png"],
638
+ [694, "radar_roulette_9", "png"],
639
+ [695, "radar_roulette_10", "png"],
640
+ [696, "radar_roulette_11", "png"],
641
+ [697, "radar_roulette_12", "png"],
642
+ [698, "radar_roulette_13", "png"],
643
+ [699, "radar_roulette_14", "png"],
644
+ [700, "radar_roulette_15", "png"],
645
+ [701, "radar_roulette_16", "png"],
646
+ [702, "radar_roulette_17", "png"],
647
+ [703, "radar_roulette_18", "png"],
648
+ [704, "radar_roulette_19", "png"],
649
+ [705, "radar_roulette_20", "png"],
650
+ [706, "radar_roulette_21", "png"],
651
+ [707, "radar_roulette_22", "png"],
652
+ [708, "radar_roulette_23", "png"],
653
+ [709, "radar_roulette_24", "png"],
654
+ [710, "radar_roulette_25", "png"],
655
+ [711, "radar_roulette_26", "png"],
656
+ [712, "radar_roulette_27", "png"],
657
+ [713, "radar_roulette_28", "png"],
658
+ [714, "radar_roulette_29", "png"],
659
+ [715, "radar_roulette_30", "png"],
660
+ [716, "radar_roulette_31", "png"],
661
+ [717, "radar_roulette_32", "png"],
662
+ [718, "radar_roulette_33", "png"],
663
+ [719, "radar_roulette_34", "png"],
664
+ [720, "radar_roulette_35", "png"],
665
+ [721, "radar_roulette_36", "png"],
666
+ [722, "radar_roulette_0", "png"],
667
+ [723, "radar_roulette_00", "png"],
668
+ [724, "radar_limo", "png"],
669
+ [725, "radar_weapon_alien", "png"],
670
+ [726, "radar_race_open_wheel", "png"],
671
+ [727, "radar_rappel", "png"],
672
+ [728, "radar_swap_car", "png"],
673
+ [729, "radar_scuba_gear", "png"],
674
+ [730, "radar_cpanel_1", "png"],
675
+ [731, "radar_cpanel_2", "png"],
676
+ [732, "radar_cpanel_3", "png"],
677
+ [733, "radar_cpanel_4", "png"],
678
+ [734, "radar_snow_truck", "png"],
679
+ [735, "radar_buggy_1", "png"],
680
+ [736, "radar_buggy_2", "png"],
681
+ [737, "radar_zhaba", "png"],
682
+ [738, "radar_gerald", "png"],
683
+ [739, "radar_ron", "png"],
684
+ [740, "radar_arcade", "png"],
685
+ [741, "radar_drone_controls", "png"],
686
+ [742, "radar_rc_tank", "png"],
687
+ [743, "radar_stairs", "png"],
688
+ [744, "radar_camera_2", "png"],
689
+ [745, "radar_winky", "png"],
690
+ [746, "radar_mini_sub", "png"],
691
+ [747, "radar_kart_retro", "png"],
692
+ [748, "radar_kart_modern", "png"],
693
+ [749, "radar_military_quad", "png"],
694
+ [750, "radar_military_truck", "png"],
695
+ [751, "radar_ship_wheel", "png"],
696
+ [752, "radar_ufo", "png"],
697
+ [753, "radar_seasparrow2", "png"],
698
+ [754, "radar_dinghy2", "png"],
699
+ [755, "radar_patrol_boat", "png"],
700
+ [756, "radar_retro_sports_car", "png"],
701
+ [757, "radar_squadee", "png"],
702
+ [758, "radar_folding_wing_jet", "png"],
703
+ [759, "radar_valkyrie2", "png"],
704
+ [760, "radar_sub2", "png"],
705
+ [761, "radar_bolt_cutters", "png"],
706
+ [762, "radar_rappel_gear", "png"],
707
+ [763, "radar_keycard", "png"],
708
+ [764, "radar_password", "png"],
709
+ [765, "radar_island_heist_prep", "png"],
710
+ [766, "radar_island_party", "png"],
711
+ [767, "radar_control_tower", "png"],
712
+ [768, "radar_underwater_gate", "png"],
713
+ [769, "radar_power_switch", "png"],
714
+ [770, "radar_compound_gate", "png"],
715
+ [771, "radar_rappel_point", "png"],
716
+ [772, "radar_keypad", "png"],
717
+ [773, "radar_sub_controls", "png"],
718
+ [774, "radar_sub_periscope", "png"],
719
+ [775, "radar_sub_missile", "png"],
720
+ [776, "radar_painting", "png"],
721
+ [777, "radar_car_meet", "png"],
722
+ [778, "radar_car_test_area", "png"],
723
+ [779, "radar_auto_shop_property", "png"],
724
+ [780, "radar_docks_export", "png"],
725
+ [781, "radar_prize_car", "png"],
726
+ [782, "radar_test_car", "png"],
727
+ [783, "radar_car_robbery_board", "png"],
728
+ [784, "radar_car_robbery_prep", "png"],
729
+ [785, "radar_street_race_series", "png"],
730
+ [786, "radar_pursuit_series", "png"],
731
+ [787, "radar_car_meet_organiser", "png"],
732
+ [788, "radar_securoserv", "png"],
733
+ [789, "radar_bounty_collectibles", "png"],
734
+ [790, "radar_movie_collectibles", "png"],
735
+ [791, "radar_trailer_ramp", "png"],
736
+ [792, "radar_race_organiser", "png"],
737
+ [793, "radar_chalkboard_list", "png"],
738
+ [794, "radar_export_vehicle", "png"],
739
+ [795, "radar_train", "png"],
740
+ [796, "radar_heist_diamond", "png"],
741
+ [797, "radar_heist_doomsday", "png"],
742
+ [798, "radar_heist_island", "png"],
743
+ [799, "radar_slamvan2", "png"],
744
+ [800, "radar_crusader", "png"],
745
+ [801, "radar_construction_outfit", "png"],
746
+ [802, "radar_overlay_jammed", "png"],
747
+ [803, "radar_heist_island_unavailable", "png"],
748
+ [804, "radar_heist_diamond_unavailable", "png"],
749
+ [805, "radar_heist_doomsday_unavailable", "png"],
750
+ [806, "radar_placeholder_7", "png"],
751
+ [807, "radar_placeholder_8", "png"],
752
+ [808, "radar_placeholder_9", "png"],
753
+ [809, "radar_featured_series", "png"],
754
+ [810, "radar_vehicle_for_sale", "png"],
755
+ [811, "radar_van_keys", "png"],
756
+ [812, "radar_suv_service", "png"],
757
+ [813, "radar_security_contract", "png"],
758
+ [814, "radar_safe", "png"],
759
+ [815, "radar_ped_r", "png"],
760
+ [816, "radar_ped_e", "png"],
761
+ [817, "radar_payphone", "png"],
762
+ [818, "radar_patriot3", "png"],
763
+ [819, "radar_music_studio", "png"],
764
+ [820, "radar_jubilee", "png"],
765
+ [821, "radar_granger2", "png"],
766
+ [822, "radar_explosive_charge", "png"],
767
+ [823, "radar_deity", "png"],
768
+ [824, "radar_d_champion", "png"],
769
+ [825, "radar_buffalo4", "png"],
770
+ [826, "radar_agency", "png"],
771
+ [827, "radar_biker_bar", "png"],
772
+ [828, "radar_simeon_overlay", "png"],
773
+ [829, "radar_junk_skydive", "png"],
774
+ [830, "radar_luxury_car_showroom", "png"],
775
+ [831, "radar_car_showroom", "png"],
776
+ [832, "radar_car_showroom_simeon", "png"],
777
+ [833, "radar_flaming_skull", "png"],
778
+ [834, "radar_weapon_ammo", "png"],
779
+ [835, "radar_community_series", "png"],
780
+ [836, "radar_cayo_series", "png"],
781
+ [837, "radar_clubhouse_contract", "png"],
782
+ [838, "radar_agent_ulp", "png"],
783
+ [839, "radar_acid", "png"],
784
+ [840, "radar_acid_lab", "png"],
785
+ [841, "radar_dax_overlay", "png"],
786
+ [842, "radar_dead_drop_package", "png"],
787
+ [843, "radar_downtown_cab", "png"],
788
+ [844, "radar_gun_van", "png"],
789
+ [845, "radar_stash_house", "png"],
790
+ [846, "radar_tractor", "png"],
791
+ [847, "radar_warehouse_juggalo", "png"],
792
+ [848, "radar_warehouse_juggalo_dax", "png"],
793
+ [849, "radar_weapon_crowbar", "png"],
794
+ [850, "radar_duffel_bag", "png"],
795
+ [851, "radar_oil_tanker", "png"],
796
+ [852, "radar_acid_lab_tent", "png"],
797
+ [853, "radar_van_burrito", "png"],
798
+ [854, "radar_acid_boost", "png"],
799
+ [855, "radar_ped_gang_leader", "png"],
800
+ [856, "radar_multistorey_garage", "png"],
801
+ [857, "radar_seized_asset_sales", "png"],
802
+ [858, "radar_cayo_attrition", "png"],
803
+ [859, "radar_bicycle", "png"],
804
+ [860, "radar_bicycle_trial", "png"],
805
+ [861, "radar_raiju", "png"],
806
+ [862, "radar_conada2", "png"],
807
+ [863, "radar_overlay_ready_for_sell", "png"],
808
+ [864, "radar_overlay_missing_supplies", "png"],
809
+ [865, "radar_streamer216", "png"],
810
+ [866, "radar_signal_jammer", "png"],
811
+ [867, "radar_salvage_yard", "png"],
812
+ [868, "radar_robbery_prep_equipment", "png"],
813
+ [869, "radar_robbery_prep_overlay", "png"],
814
+ [870, "radar_yusuf", "png"],
815
+ [871, "radar_vincent", "png"],
816
+ [872, "radar_vinewood_garage", "png"],
817
+ [873, "radar_lstb", "png"],
818
+ [874, "radar_cctv_workstation", "png"],
819
+ [875, "radar_hacking_device", "png"],
820
+ [876, "radar_race_drag", "png"],
821
+ [877, "radar_race_drift", "png"],
822
+ [878, "radar_casino_prep", "png"],
823
+ [879, "radar_planning_wall", "png"],
824
+ [880, "radar_weapon_crate", "png"],
825
+ [881, "radar_weapon_snowball", "png"],
826
+ [882, "radar_train_signals_green", "png"],
827
+ [883, "radar_train_signals_red", "png"],
828
+ [884, "radar_office_transporter", "png"],
829
+ [885, "radar_yankton_survival", "png"],
830
+ [886, "radar_daily_bounty", "png"],
831
+ [887, "radar_bounty_target", "png"],
832
+ [888, "radar_filming_schedule", "png"],
833
+ [889, "radar_pizza_this", "png"],
834
+ [890, "radar_aircraft_carrier", "png"],
835
+ [891, "radar_weapon_emp", "png"],
836
+ [892, "radar_maude_eccles", "png"],
837
+ [893, "radar_bail_bonds_office", "png"],
838
+ [894, "radar_weapon_emp_mine", "png"],
839
+ [895, "radar_zombie_disease", "png"],
840
+ [896, "radar_zombie_proximity", "png"],
841
+ [897, "radar_zombie_fire", "png"],
842
+ [898, "radar_animal_possessed", "png"],
843
+ [899, "radar_mobile_phone", "png"],
844
+ [900, "radar_garment_factory", "png"],
845
+ [901, "radar_garment_factory_for_sale", "png"],
846
+ [902, "radar_garment_factory_equipment", "png"],
847
+ [903, "radar_field_hangar", "png"],
848
+ [904, "radar_field_hangar_for_sale", "png"],
849
+ [905, "radar_cargobob_ch53", "png"],
850
+ [906, "radar_chopper_lift_ammo", "png"],
851
+ [907, "radar_chopper_lift_armor", "png"],
852
+ [908, "radar_chopper_lift_explosives", "png"],
853
+ [909, "radar_chopper_lift_upgrade", "png"],
854
+ [910, "radar_chopper_lift_weapon", "png"],
855
+ [911, "radar_cargo_ship", "png"],
856
+ [912, "radar_submarine_missile", "png"],
857
+ [913, "radar_propeller_engine", "png"],
858
+ [914, "radar_shark", "png"],
859
+ [915, "radar_fast_travel", "png"],
860
+ [916, "radar_plane_duster2", "png"],
861
+ [917, "radar_plane_titan2", "png"],
862
+ [918, "radar_collectible", "png"],
863
+ [919, "radar_field_hangar_discount", "png"],
864
+ [920, "radar_garment_factory_discount", "png"],
865
+ [921, "radar_weapon_gusenberg_sweeper", "png"],
866
+ [922, "radar_weapon_tear_gas", "png"],
867
+ [923, "radar_dog", "png"],
868
+ [924, "radar_bobcat_security", "png"],
869
+ [925, "radar_smoke_shop", "png"],
870
+ [926, "radar_smoke_shop_for_sale", "png"],
871
+ [927, "radar_smoke_shop_attention", "png"],
872
+ [928, "radar_helitours", "png"],
873
+ [929, "radar_helitours_for_sale", "png"],
874
+ [930, "radar_helitours_attention", "png"],
875
+ [931, "radar_car_wash_business", "png"],
876
+ [932, "radar_car_wash_business_for_sale", "png"],
877
+ [933, "radar_car_wash_business_attention", "png"],
878
+ [934, "radar_attention", "png"],
879
+ [935, "radar_alarm", "png"],
880
+ [936, "radar_helitours_discount", "png"],
881
+ [937, "radar_smoke_shop_discount", "png"],
882
+ [938, "radar_car_wash_business_discount", "png"],
883
+ [939, "radar_real_estate", "png"],
884
+ [940, "radar_medical_courier", "png"],
885
+ [941, "radar_gruppe_sechs", "png"],
886
+ [942, "radar_fire_station", "png"],
887
+ [943, "radar_fire_truck", "png"],
888
+ [944, "radar_alpha_mail", "png"],
889
+ [945, "radar_ls_meteor", "png"],
890
+ [946, "radar_four20_survival", "png"],
891
+ [947, "radar_community_mission_series", "png"],
892
+ [948, "radar_property_mansion", "png"],
893
+ [949, "radar_ai_keypad", "png"],
894
+ [950, "radar_taxi_self_drive", "png"],
895
+ [951, "radar_train_subway", "png"],
896
+ [952, "radar_trashbag", "png"],
897
+ [953, "radar_mission_creator", "png"],
898
+ [954, "radar_cat", "png"],
899
+ [955, "radar_mansion_ai_m", "png"],
900
+ [956, "radar_mansion_ai_f", "png"],
901
+ [957, "radar_mansion_ai_gang", "png"]
902
+ ];
903
+ var BLIP_BASE = "https://docs.fivem.net/blips/";
904
+ function blipUrl(name, ext) {
905
+ return `${BLIP_BASE}${name}.${ext}`;
906
+ }
907
+ var BLIP_COLORS = [
908
+ [0, "White", "#FFFFFF"],
909
+ [1, "Red", "#E54141"],
910
+ [2, "Green", "#3FA83F"],
911
+ [3, "Blue", "#5B8CCF"],
912
+ [4, "White", "#FFFFFF"],
913
+ [5, "Yellow", "#F0D453"],
914
+ [6, "Light Red", "#E88888"],
915
+ [7, "Violet", "#8C5FA8"],
916
+ [8, "Pink", "#E878C8"],
917
+ [9, "Light Orange", "#F0A861"],
918
+ [10, "Light Brown", "#C1A470"],
919
+ [11, "Light Green", "#94D468"],
920
+ [12, "Light Blue", "#68C8E8"],
921
+ [13, "Light Purple", "#B898E8"],
922
+ [14, "Dark Purple", "#583E8E"],
923
+ [15, "Cyan", "#48C8B8"],
924
+ [16, "Light Yellow", "#E8E898"],
925
+ [17, "Orange", "#E87830"],
926
+ [18, "Light Blue", "#78A8E8"],
927
+ [19, "Dark Pink", "#C83878"],
928
+ [20, "Dark Yellow", "#A0A038"],
929
+ [21, "Dark Orange", "#B07828"],
930
+ [22, "Light Gray", "#B0B0B0"],
931
+ [23, "Light Pink", "#E8A8C0"],
932
+ [24, "Lemon Green", "#88F068"],
933
+ [25, "Forest Green", "#388038"],
934
+ [26, "Electric Blue", "#2060E0"],
935
+ [27, "Bright Purple", "#9840E0"],
936
+ [28, "Dark Yellow", "#7C7C28"],
937
+ [29, "Dark Blue", "#283878"],
938
+ [30, "Dark Cyan", "#287078"],
939
+ [31, "Light Brown", "#A08858"],
940
+ [32, "Light Blue", "#78B0E8"],
941
+ [33, "Light Yellow", "#E8E868"],
942
+ [34, "Light Pink", "#F0A0C0"],
943
+ [35, "Light Red", "#E07868"],
944
+ [36, "Beige", "#D8C898"],
945
+ [37, "White", "#FFFFFF"],
946
+ [38, "Blue", "#4870A0"],
947
+ [39, "Light Gray", "#909898"],
948
+ [40, "Dark Gray", "#585858"],
949
+ [41, "Pink Red", "#E07088"],
950
+ [42, "Blue", "#5090B8"],
951
+ [43, "Light Green", "#88C868"],
952
+ [44, "Light Orange", "#E09048"],
953
+ [45, "White", "#F0F0F0"],
954
+ [46, "Gold", "#D8B838"],
955
+ [47, "Orange", "#E07020"]
956
+ ];
957
+ var BLIP_ICON_DATA = BLIP_ENTRIES.map(([id, name]) => ({
958
+ value: String(id),
959
+ label: `${id} \u2014 ${name}`
960
+ }));
961
+ var BLIP_COLOR_DATA = BLIP_COLORS.map(([id, label2]) => ({
962
+ value: String(id),
963
+ label: `${id} \u2014 ${label2}`
964
+ }));
965
+ var blipEntryMap = new Map(BLIP_ENTRIES.map(([id, name, ext]) => [String(id), { id, name, ext }]));
966
+ var blipColorMap = new Map(BLIP_COLORS.map(([id, label2, hex]) => [String(id), { id, label: label2, hex }]));
967
+ var renderBlipOption = ({ option }) => {
968
+ const entry = blipEntryMap.get(option.value);
969
+ if (!entry) return option.label;
970
+ return /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", children: [
971
+ /* @__PURE__ */ jsx(
972
+ Image$1,
973
+ {
974
+ src: blipUrl(entry.name, entry.ext),
975
+ alt: entry.name,
976
+ w: 24,
977
+ h: 24,
978
+ fit: "contain",
979
+ style: { imageRendering: "pixelated" }
980
+ }
981
+ ),
982
+ /* @__PURE__ */ jsxs(Text, { size: "xs", truncate: true, children: [
983
+ entry.id,
984
+ " \u2014 ",
985
+ entry.name
986
+ ] })
987
+ ] });
988
+ };
989
+ var renderColorOption = ({ option }) => {
990
+ const entry = blipColorMap.get(option.value);
991
+ if (!entry) return option.label;
992
+ return /* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "nowrap", children: [
993
+ /* @__PURE__ */ jsx(
994
+ Box,
995
+ {
996
+ w: 24,
997
+ h: 24,
998
+ style: {
999
+ borderRadius: 4,
1000
+ backgroundColor: entry.hex,
1001
+ border: "1px solid rgba(255,255,255,0.15)",
1002
+ flexShrink: 0
1003
+ }
1004
+ }
1005
+ ),
1006
+ /* @__PURE__ */ jsxs(Text, { size: "xs", truncate: true, children: [
1007
+ entry.id,
1008
+ " \u2014 ",
1009
+ entry.label
1010
+ ] })
1011
+ ] });
1012
+ };
1013
+ function BlipIconSelect({ value, onChange, label: label2 = "Blip Icon", size = "xs", ...rest }) {
1014
+ const entry = value != null ? blipEntryMap.get(String(value)) : void 0;
1015
+ return /* @__PURE__ */ jsx(
1016
+ Select,
1017
+ {
1018
+ label: label2,
1019
+ size,
1020
+ ...rest,
1021
+ searchable: true,
1022
+ data: BLIP_ICON_DATA,
1023
+ value: value != null ? String(value) : null,
1024
+ onChange: (val) => val != null && onChange(Number(val)),
1025
+ renderOption: renderBlipOption,
1026
+ maxDropdownHeight: 300,
1027
+ nothingFoundMessage: "No results",
1028
+ leftSection: entry ? /* @__PURE__ */ jsx(
1029
+ Image$1,
1030
+ {
1031
+ src: blipUrl(entry.name, entry.ext),
1032
+ alt: entry.name,
1033
+ w: 18,
1034
+ h: 18,
1035
+ fit: "contain",
1036
+ style: { imageRendering: "pixelated" }
1037
+ }
1038
+ ) : void 0
1039
+ }
1040
+ );
1041
+ }
1042
+ function BlipColorSelect({ value, onChange, label: label2 = "Blip Color", size = "xs", ...rest }) {
1043
+ const entry = value != null ? blipColorMap.get(String(value)) : void 0;
1044
+ return /* @__PURE__ */ jsx(
1045
+ Select,
1046
+ {
1047
+ label: label2,
1048
+ size,
1049
+ ...rest,
1050
+ searchable: true,
1051
+ data: BLIP_COLOR_DATA,
1052
+ value: value != null ? String(value) : null,
1053
+ onChange: (val) => val != null && onChange(Number(val)),
1054
+ renderOption: renderColorOption,
1055
+ maxDropdownHeight: 300,
1056
+ nothingFoundMessage: "No results",
1057
+ leftSection: entry ? /* @__PURE__ */ jsx(
1058
+ Box,
1059
+ {
1060
+ w: 18,
1061
+ h: 18,
1062
+ style: {
1063
+ borderRadius: 4,
1064
+ backgroundColor: entry.hex,
1065
+ border: "1px solid rgba(255,255,255,0.15)",
1066
+ flexShrink: 0
1067
+ }
1068
+ }
1069
+ ) : void 0
1070
+ }
1071
+ );
1072
+ }
25
1073
 
26
1074
  // src/utils/colorWithAlpha.ts
27
1075
  var colorNames = {
@@ -168,11 +1216,11 @@ var colorNames = {
168
1216
  Yellow: { r: 255, g: 255, b: 0 },
169
1217
  YellowGreen: { r: 154, g: 205, b: 50 }
170
1218
  };
171
- function colorWithAlpha(color, alpha5) {
1219
+ function colorWithAlpha(color, alpha8) {
172
1220
  const lowerCasedColor = color.toLowerCase();
173
1221
  if (colorNames[lowerCasedColor]) {
174
1222
  const rgb = colorNames[lowerCasedColor];
175
- return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha5})`;
1223
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha8})`;
176
1224
  }
177
1225
  if (/^#([A-Fa-f0-9]{6})$/.test(color)) {
178
1226
  const hex = color.slice(1);
@@ -180,12 +1228,12 @@ function colorWithAlpha(color, alpha5) {
180
1228
  const r = bigint >> 16 & 255;
181
1229
  const g = bigint >> 8 & 255;
182
1230
  const b = bigint & 255;
183
- return `rgba(${r}, ${g}, ${b}, ${alpha5})`;
1231
+ return `rgba(${r}, ${g}, ${b}, ${alpha8})`;
184
1232
  }
185
1233
  if (/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.test(color)) {
186
1234
  const result = color.match(/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/);
187
1235
  if (result) {
188
- return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha5})`;
1236
+ return `rgba(${result[1]}, ${result[2]}, ${result[3]}, ${alpha8})`;
189
1237
  }
190
1238
  }
191
1239
  return color;
@@ -225,6 +1273,7 @@ var useSettings = create(() => ({
225
1273
  primaryColor: "dirk",
226
1274
  primaryShade: 9,
227
1275
  itemImgPath: "",
1276
+ resourceVersion: "dev",
228
1277
  customTheme: [
229
1278
  "#f0f4ff",
230
1279
  "#d9e3ff",
@@ -827,6 +1876,321 @@ async function getImageShape(file) {
827
1876
  img.src = typeof file === "string" ? file : URL.createObjectURL(file);
828
1877
  });
829
1878
  }
1879
+ var useItems = create(() => ({}));
1880
+ var useItemsList = (excludeItemNames = []) => {
1881
+ const excludeSet = new Set(excludeItemNames);
1882
+ return Object.values(useItems.getState()).filter((item) => !excludeSet.has(item.name));
1883
+ };
1884
+ var getItemImageUrl = (itemName) => {
1885
+ return useItems.getState()[itemName]?.image || "";
1886
+ };
1887
+ registerInitialFetch("FETCH_ALL_ITEMS", null, {
1888
+ item1: { name: "item1", label: "Item 1", weight: 0.5, image: "item1.png" },
1889
+ item2: { name: "item2", label: "Item 2", weight: 1, image: "item2.png" },
1890
+ item3: { name: "item3", label: "Item 3", weight: 2.5, image: "item3.png" }
1891
+ }).then((fetchedItems) => {
1892
+ if (!fetchedItems) return;
1893
+ useItems.setState(fetchedItems);
1894
+ });
1895
+
1896
+ // src/utils/inputMapper.ts
1897
+ var INPUT_MAPPER_PRIMARY_OPTIONS = [
1898
+ "DIGITALBUTTON_AXIS",
1899
+ "GAME_CONTROLLED",
1900
+ "JOYSTICK_AXIS",
1901
+ "JOYSTICK_AXIS_NEGATIVE",
1902
+ "JOYSTICK_AXIS_POSITIVE",
1903
+ "JOYSTICK_BUTTON",
1904
+ "JOYSTICK_IAXIS",
1905
+ "JOYSTICK_POV",
1906
+ "JOYSTICK_POV_AXIS",
1907
+ "KEYBOARD",
1908
+ "MKB_AXIS",
1909
+ "MOUSE_ABSOLUTEAXIS",
1910
+ "MOUSE_BUTTON",
1911
+ "MOUSE_CENTEREDAXIS",
1912
+ "MOUSE_NORMALIZED",
1913
+ "MOUSE_RELATIVEAXIS",
1914
+ "MOUSE_SCALEDAXIS",
1915
+ "MOUSE_WHEEL",
1916
+ "PAD_ANALOGBUTTON",
1917
+ "PAD_AXIS",
1918
+ "PAD_DEBUGBUTTON",
1919
+ "PAD_DIGITALBUTTON",
1920
+ "TOUCHPAD_ABSOLUTE_AXIS",
1921
+ "TOUCHPAD_CENTERED_AXIS"
1922
+ ];
1923
+ var KEYBOARD_KEYS = [
1924
+ "BACK",
1925
+ "TAB",
1926
+ "RETURN",
1927
+ "PAUSE",
1928
+ "CAPITAL",
1929
+ "ESCAPE",
1930
+ "SPACE",
1931
+ "PAGEUP",
1932
+ "PAGEDOWN",
1933
+ "END",
1934
+ "HOME",
1935
+ "LEFT",
1936
+ "UP",
1937
+ "RIGHT",
1938
+ "DOWN",
1939
+ "INSERT",
1940
+ "DELETE",
1941
+ "0",
1942
+ "1",
1943
+ "2",
1944
+ "3",
1945
+ "4",
1946
+ "5",
1947
+ "6",
1948
+ "7",
1949
+ "8",
1950
+ "9",
1951
+ "A",
1952
+ "B",
1953
+ "C",
1954
+ "D",
1955
+ "E",
1956
+ "F",
1957
+ "G",
1958
+ "H",
1959
+ "I",
1960
+ "J",
1961
+ "K",
1962
+ "L",
1963
+ "M",
1964
+ "N",
1965
+ "O",
1966
+ "P",
1967
+ "Q",
1968
+ "R",
1969
+ "S",
1970
+ "T",
1971
+ "U",
1972
+ "V",
1973
+ "W",
1974
+ "X",
1975
+ "Y",
1976
+ "Z",
1977
+ "F1",
1978
+ "F2",
1979
+ "F3",
1980
+ "F4",
1981
+ "F5",
1982
+ "F6",
1983
+ "F7",
1984
+ "F8",
1985
+ "F9",
1986
+ "F10",
1987
+ "F11",
1988
+ "F12",
1989
+ "NUMPAD0",
1990
+ "NUMPAD1",
1991
+ "NUMPAD2",
1992
+ "NUMPAD3",
1993
+ "NUMPAD4",
1994
+ "NUMPAD5",
1995
+ "NUMPAD6",
1996
+ "NUMPAD7",
1997
+ "NUMPAD8",
1998
+ "NUMPAD9",
1999
+ "MULTIPLY",
2000
+ "ADD",
2001
+ "SUBTRACT",
2002
+ "DECIMAL",
2003
+ "DIVIDE",
2004
+ "NUMPADENTER",
2005
+ "LSHIFT",
2006
+ "RSHIFT",
2007
+ "LCONTROL",
2008
+ "RCONTROL",
2009
+ "LMENU",
2010
+ "RMENU",
2011
+ "LWIN",
2012
+ "RWIN",
2013
+ "APPS",
2014
+ "NUMLOCK",
2015
+ "SCROLL",
2016
+ "OEM_1",
2017
+ "SEMICOLON",
2018
+ "EQUALS",
2019
+ "PLUS",
2020
+ "COMMA",
2021
+ "MINUS",
2022
+ "PERIOD",
2023
+ "SLASH",
2024
+ "OEM_2",
2025
+ "OEM_3",
2026
+ "GRAVE",
2027
+ "LBRACKET",
2028
+ "OEM_4",
2029
+ "BACKSLASH",
2030
+ "OEM_5",
2031
+ "RBRACKET",
2032
+ "OEM_6",
2033
+ "APOSTROPHE",
2034
+ "OEM_7",
2035
+ "OEM_102"
2036
+ ];
2037
+ var MOUSE_BUTTON_KEYS = [
2038
+ "MOUSE_LEFT",
2039
+ "MOUSE_RIGHT",
2040
+ "MOUSE_MIDDLE",
2041
+ "MOUSE_EXTRABTN1",
2042
+ "MOUSE_EXTRABTN2",
2043
+ "MOUSE_EXTRABTN3",
2044
+ "MOUSE_EXTRABTN4",
2045
+ "MOUSE_EXTRABTN5",
2046
+ "IOM_WHEEL_UP",
2047
+ "IOM_WHEEL_DOWN"
2048
+ ];
2049
+ var MOUSE_WHEEL_KEYS = ["IOM_WHEEL_UP", "IOM_WHEEL_DOWN"];
2050
+ var MOUSE_AXIS_KEYS = [
2051
+ "IOM_AXIS_X",
2052
+ "IOM_AXIS_Y",
2053
+ "IOM_AXIS_WHEEL",
2054
+ "IOM_AXIS_WHEEL_DELTA",
2055
+ "IOM_AXIS_WHEEL_RELATIVE",
2056
+ "IOM_IAXIS_X",
2057
+ "IOM_IAXIS_Y",
2058
+ "IOM_IAXIS_WHEEL",
2059
+ "IOM_IAXIS_WHEEL_DELTA",
2060
+ "IOM_IAXIS_WHEEL_RELATIVE",
2061
+ "IOM_AXIS_X_LEFT",
2062
+ "IOM_AXIS_X_RIGHT",
2063
+ "IOM_AXIS_Y_UP",
2064
+ "IOM_AXIS_Y_DOWN",
2065
+ "BASIC_MOUSE_AXIS_MAX",
2066
+ "MOUSE_AXIS_MAX"
2067
+ ];
2068
+ var PAD_BUTTON_KEYS = [
2069
+ "L1_INDEX",
2070
+ "R1_INDEX",
2071
+ "L2_INDEX",
2072
+ "R2_INDEX",
2073
+ "L3_INDEX",
2074
+ "R3_INDEX",
2075
+ "LUP_INDEX",
2076
+ "LRIGHT_INDEX",
2077
+ "LDOWN_INDEX",
2078
+ "LLEFT_INDEX",
2079
+ "RUP_INDEX",
2080
+ "RRIGHT_INDEX",
2081
+ "RDOWN_INDEX",
2082
+ "RLEFT_INDEX",
2083
+ "SELECT_INDEX",
2084
+ "START_INDEX",
2085
+ "TOUCH_INDEX"
2086
+ ];
2087
+ var PAD_DEBUG_KEYS = [
2088
+ "L1",
2089
+ "R1",
2090
+ "L2",
2091
+ "R2",
2092
+ "L3",
2093
+ "R3",
2094
+ "LUP",
2095
+ "LRIGHT",
2096
+ "LDOWN",
2097
+ "LLEFT",
2098
+ "RUP",
2099
+ "RRIGHT",
2100
+ "RDOWN",
2101
+ "RLEFT",
2102
+ "SELECT",
2103
+ "START",
2104
+ "TOUCH"
2105
+ ];
2106
+ var PAD_AXIS_KEYS = [
2107
+ "IOM_AXIS_LX",
2108
+ "IOM_AXIS_LY",
2109
+ "IOM_AXIS_RX",
2110
+ "IOM_AXIS_RY",
2111
+ "IOM_AXIS_LUP",
2112
+ "IOM_AXIS_LDOWN",
2113
+ "IOM_AXIS_LLEFT",
2114
+ "IOM_AXIS_LRIGHT",
2115
+ "IOM_AXIS_LUR",
2116
+ "IOM_AXIS_LUL",
2117
+ "IOM_AXIS_LDR",
2118
+ "IOM_AXIS_LDL",
2119
+ "IOM_AXIS_RUP",
2120
+ "IOM_AXIS_RDOWN",
2121
+ "IOM_AXIS_RLEFT",
2122
+ "IOM_AXIS_RRIGHT",
2123
+ "IOM_AXIS_RUR",
2124
+ "IOM_AXIS_RUL",
2125
+ "IOM_AXIS_RDR",
2126
+ "IOM_AXIS_RDL",
2127
+ "IOM_AXIS_DPADX",
2128
+ "IOM_AXIS_DPADY",
2129
+ "IOM_AXIS_LY_UP",
2130
+ "IOM_AXIS_LY_DOWN",
2131
+ "IOM_AXIS_LX_LEFT",
2132
+ "IOM_AXIS_LX_RIGHT",
2133
+ "IOM_AXIS_RY_UP",
2134
+ "IOM_AXIS_RY_DOWN",
2135
+ "IOM_AXIS_RX_LEFT",
2136
+ "IOM_AXIS_RX_RIGHT"
2137
+ ];
2138
+ var JOYSTICK_AXIS_KEYS = Array.from({ length: 8 }, (_, i) => `IOM_JOYSTICK_AXIS${i + 1}`);
2139
+ var JOYSTICK_BUTTON_KEYS = Array.from({ length: 32 }, (_, i) => `IOM_JOYSTICK_BUTTON${i + 1}`);
2140
+ var JOYSTICK_POV_KEYS = Array.from({ length: 4 }, (_, p) => {
2141
+ const idx = p + 1;
2142
+ return [
2143
+ `IOM_POV${idx}_UP`,
2144
+ `IOM_POV${idx}_RIGHT`,
2145
+ `IOM_POV${idx}_DOWN`,
2146
+ `IOM_POV${idx}_LEFT`
2147
+ ];
2148
+ }).flat();
2149
+ var INPUT_MAPPER_KEYS_BY_PRIMARY = {
2150
+ DIGITALBUTTON_AXIS: [],
2151
+ GAME_CONTROLLED: [],
2152
+ JOYSTICK_AXIS: [...JOYSTICK_AXIS_KEYS],
2153
+ JOYSTICK_AXIS_NEGATIVE: [...JOYSTICK_AXIS_KEYS],
2154
+ JOYSTICK_AXIS_POSITIVE: [...JOYSTICK_AXIS_KEYS],
2155
+ JOYSTICK_BUTTON: [...JOYSTICK_BUTTON_KEYS],
2156
+ JOYSTICK_IAXIS: [...JOYSTICK_AXIS_KEYS],
2157
+ JOYSTICK_POV: [...JOYSTICK_POV_KEYS],
2158
+ JOYSTICK_POV_AXIS: [...JOYSTICK_POV_KEYS],
2159
+ KEYBOARD: [...KEYBOARD_KEYS],
2160
+ MKB_AXIS: [],
2161
+ MOUSE_ABSOLUTEAXIS: [...MOUSE_AXIS_KEYS],
2162
+ MOUSE_BUTTON: [...MOUSE_BUTTON_KEYS],
2163
+ MOUSE_CENTEREDAXIS: [...MOUSE_AXIS_KEYS],
2164
+ MOUSE_NORMALIZED: [...MOUSE_AXIS_KEYS],
2165
+ MOUSE_RELATIVEAXIS: [...MOUSE_AXIS_KEYS],
2166
+ MOUSE_SCALEDAXIS: [...MOUSE_AXIS_KEYS],
2167
+ MOUSE_WHEEL: [...MOUSE_WHEEL_KEYS],
2168
+ PAD_ANALOGBUTTON: [...PAD_BUTTON_KEYS],
2169
+ PAD_AXIS: [...PAD_AXIS_KEYS],
2170
+ PAD_DEBUGBUTTON: [...PAD_DEBUG_KEYS],
2171
+ PAD_DIGITALBUTTON: [...PAD_BUTTON_KEYS],
2172
+ TOUCHPAD_ABSOLUTE_AXIS: [],
2173
+ TOUCHPAD_CENTERED_AXIS: []
2174
+ };
2175
+
2176
+ // src/utils/extractDefaults.ts
2177
+ function extractDefaults(schema) {
2178
+ if (!schema || typeof schema !== "object") return void 0;
2179
+ if (schema.default !== void 0) return schema.default;
2180
+ if (schema.type === "object" && schema.properties) {
2181
+ const result = {};
2182
+ let hasValue = false;
2183
+ for (const [key, child] of Object.entries(schema.properties)) {
2184
+ const val = extractDefaults(child);
2185
+ if (val !== void 0) {
2186
+ result[key] = val;
2187
+ hasValue = true;
2188
+ }
2189
+ }
2190
+ return hasValue ? result : void 0;
2191
+ }
2192
+ return void 0;
2193
+ }
830
2194
  function BorderedIcon(props) {
831
2195
  const theme2 = useMantineTheme();
832
2196
  return /* @__PURE__ */ jsx(
@@ -1767,149 +3131,142 @@ function LevelPanel(props) {
1767
3131
  }
1768
3132
  );
1769
3133
  }
1770
- var ModalContext = createContext(null);
1771
- function useModal(selector) {
1772
- const modal = useContext(ModalContext);
1773
- if (!modal) {
1774
- throw new Error("useModal must be used within a ModalProvider");
1775
- }
1776
- return useStore(modal, selector);
1777
- }
1778
- function ModalProvider({ children, defaultPage }) {
1779
- const storeRef = useRef(
1780
- create(() => ({
1781
- active: null
1782
- }))
1783
- );
1784
- return /* @__PURE__ */ jsxs(ModalContext.Provider, { value: storeRef.current, children: [
1785
- /* @__PURE__ */ jsx(Modal, {}),
1786
- children
1787
- ] });
1788
- }
1789
- function useModalActions() {
1790
- const modal = useContext(ModalContext);
1791
- if (!modal) throw new Error("useModalActions must be used within a ModalProvider");
1792
- const showModal = (openModal) => {
1793
- modal.setState({ active: openModal });
1794
- };
1795
- const hideModal = () => {
1796
- modal.setState({ active: null });
1797
- };
1798
- return { showModal, hideModal };
1799
- }
1800
- function Modal() {
1801
- const active = useModal((state) => state.active);
1802
- const { hideModal } = useModalActions();
1803
- const ref = useClickOutside(() => {
1804
- if (!active) return;
1805
- if (active.clickOutside == false) return;
1806
- if (active) {
1807
- hideModal();
1808
- }
1809
- });
3134
+ function Modal({
3135
+ title,
3136
+ icon: Icon,
3137
+ iconColor,
3138
+ description: description2,
3139
+ badge,
3140
+ onClose,
3141
+ width = "52vh",
3142
+ maxHeight = "85vh",
3143
+ height,
3144
+ zIndex = 100,
3145
+ clickOutside = true,
3146
+ children
3147
+ }) {
1810
3148
  const theme2 = useMantineTheme();
1811
- return /* @__PURE__ */ jsx(AnimatePresence, { children: active && /* @__PURE__ */ jsx(
1812
- MotionFlex,
3149
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(
3150
+ motion.div,
1813
3151
  {
1814
- h: "100%",
1815
- w: "100%",
1816
- bg: "rgba(0, 0, 0, 0.3)",
1817
- pos: "absolute",
1818
- style: {
1819
- zIndex: 2e3,
1820
- filter: "drop-shadow(0 0 2vh black)"
1821
- },
1822
3152
  initial: { opacity: 0 },
1823
3153
  animate: { opacity: 1 },
1824
3154
  exit: { opacity: 0 },
1825
- align: "center",
1826
- justify: "center",
3155
+ style: {
3156
+ position: "fixed",
3157
+ inset: 0,
3158
+ zIndex,
3159
+ display: "flex",
3160
+ alignItems: "center",
3161
+ justifyContent: "center",
3162
+ background: "rgba(0,0,0,0.65)"
3163
+ },
3164
+ onClick: clickOutside ? onClose : void 0,
1827
3165
  children: /* @__PURE__ */ jsxs(
1828
- MotionFlex,
3166
+ motion.div,
1829
3167
  {
1830
- pos: "absolute",
1831
- top: "50%",
1832
- left: "50%",
1833
- ref,
1834
- w: active.width || "40%",
3168
+ initial: { opacity: 0, scale: 0.96, y: 8 },
3169
+ animate: { opacity: 1, scale: 1, y: 0 },
3170
+ exit: { opacity: 0, scale: 0.96, y: 8 },
3171
+ transition: { duration: 0.18, ease: "easeOut" },
3172
+ onClick: (e) => e.stopPropagation(),
1835
3173
  style: {
1836
- transform: "translate(-50%, -50%)",
1837
- borderRadius: theme2.radius.xs,
1838
- boxShadow: theme2.shadows.xl,
1839
- zIndex: 2100
3174
+ background: alpha(theme2.colors.dark[9], 0.98),
3175
+ border: `0.1vh solid ${theme2.colors.dark[7]}`,
3176
+ borderRadius: theme2.radius.sm,
3177
+ width,
3178
+ maxHeight,
3179
+ height,
3180
+ display: "flex",
3181
+ flexDirection: "column",
3182
+ overflow: "hidden",
3183
+ userSelect: "none"
1840
3184
  },
1841
- bg: alpha(theme2.colors.dark[9], 0.9),
1842
- initial: { scale: 0.8, opacity: 0, transform: "translate(-50%, -50%)" },
1843
- animate: { scale: 1, opacity: 1, transform: "translate(-50%, -50%)" },
1844
- exit: { scale: 0.8, opacity: 0, transform: "translate(-50%, -50%)" },
1845
- p: "sm",
1846
- direction: "column",
1847
- maw: "70%",
1848
- gap: "xs",
1849
3185
  children: [
1850
3186
  /* @__PURE__ */ jsxs(
1851
3187
  Flex,
1852
3188
  {
1853
- direction: "column",
1854
- w: "100%",
3189
+ justify: "space-between",
3190
+ align: "center",
3191
+ px: "sm",
3192
+ py: "xs",
3193
+ style: {
3194
+ borderBottom: `0.1vh solid ${theme2.colors.dark[7]}`,
3195
+ flexShrink: 0
3196
+ },
1855
3197
  children: [
1856
- /* @__PURE__ */ jsxs(
1857
- Flex,
1858
- {
1859
- w: "100%",
1860
- align: "center",
1861
- gap: "xs",
1862
- children: [
1863
- active.icon && /* @__PURE__ */ jsx(
1864
- FontAwesomeIcon,
1865
- {
1866
- icon: active.icon,
1867
- style: {
1868
- fontSize: theme2.fontSizes.xs
1869
- }
1870
- }
1871
- ),
1872
- /* @__PURE__ */ jsx(
3198
+ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xs", children: [
3199
+ Icon && /* @__PURE__ */ jsx(
3200
+ Icon,
3201
+ {
3202
+ color: iconColor ?? "rgba(255,255,255,0.6)",
3203
+ size: "2vh"
3204
+ }
3205
+ ),
3206
+ /* @__PURE__ */ jsx(
3207
+ Text,
3208
+ {
3209
+ ff: "Akrobat Bold",
3210
+ size: "sm",
3211
+ tt: "uppercase",
3212
+ lts: "0.06em",
3213
+ c: "rgba(255,255,255,0.85)",
3214
+ children: title
3215
+ }
3216
+ ),
3217
+ badge && /* @__PURE__ */ jsx(
3218
+ "div",
3219
+ {
3220
+ style: {
3221
+ background: alpha(badge.color, 0.12),
3222
+ border: `0.1vh solid ${alpha(badge.color, 0.35)}`,
3223
+ borderRadius: theme2.radius.xs,
3224
+ padding: `0 ${theme2.spacing.xxs}`
3225
+ },
3226
+ children: /* @__PURE__ */ jsx(
1873
3227
  Text,
1874
3228
  {
1875
- size: "sm",
1876
- children: active.title
1877
- }
1878
- ),
1879
- /* @__PURE__ */ jsx(
1880
- MotionIcon,
1881
- {
1882
- icon: "times",
1883
- color: "rgba(255, 255, 255, 0.7)",
1884
- whileHover: {
1885
- scale: 1.1,
1886
- filter: "brightness(1.2)"
1887
- },
1888
- style: {
1889
- marginLeft: "auto",
1890
- cursor: "pointer",
1891
- fontSize: theme2.fontSizes.sm
1892
- },
1893
- onClick: () => {
1894
- hideModal();
1895
- }
3229
+ ff: "Akrobat Bold",
3230
+ size: "xxs",
3231
+ tt: "uppercase",
3232
+ lts: "0.06em",
3233
+ c: badge.color,
3234
+ children: badge.label
1896
3235
  }
1897
3236
  )
1898
- ]
1899
- }
1900
- ),
1901
- active.description && /* @__PURE__ */ jsx(
1902
- Text,
3237
+ }
3238
+ )
3239
+ ] }),
3240
+ /* @__PURE__ */ jsx(
3241
+ motion.button,
1903
3242
  {
1904
- size: "xs",
1905
- c: "rgba(255, 255, 255, 0.7)",
1906
- children: active.description
3243
+ onClick: onClose,
3244
+ whileHover: { background: alpha(theme2.colors.dark[7], 0.5) },
3245
+ style: {
3246
+ background: "transparent",
3247
+ border: "none",
3248
+ cursor: "pointer",
3249
+ padding: theme2.spacing.xxs,
3250
+ borderRadius: theme2.radius.xs,
3251
+ display: "flex"
3252
+ },
3253
+ children: /* @__PURE__ */ jsx(X, { color: "rgba(255,255,255,0.4)" })
1907
3254
  }
1908
3255
  )
1909
3256
  ]
1910
3257
  }
1911
3258
  ),
1912
- active.children
3259
+ description2 && /* @__PURE__ */ jsx(Flex, { px: "sm", pt: "xs", children: /* @__PURE__ */ jsx(
3260
+ Text,
3261
+ {
3262
+ ff: "Akrobat Regular",
3263
+ size: "xs",
3264
+ c: "rgba(255,255,255,0.65)",
3265
+ style: { lineHeight: 1.5 },
3266
+ children: description2
3267
+ }
3268
+ ) }),
3269
+ children
1913
3270
  ]
1914
3271
  }
1915
3272
  )
@@ -1963,121 +3320,421 @@ function PromptModal(props) {
1963
3320
  }
1964
3321
  );
1965
3322
  }
1966
- var useNuiEvent = (action, handler) => {
1967
- const savedHandler = useRef(noop);
1968
- useEffect(() => {
1969
- savedHandler.current = handler;
1970
- }, [handler]);
1971
- useEffect(() => {
1972
- const eventListener = (event) => {
1973
- const { action: eventAction, data } = event.data;
1974
- if (savedHandler.current) {
1975
- if (eventAction === action) {
1976
- savedHandler.current(data);
1977
- }
1978
- }
1979
- };
1980
- window.addEventListener("message", eventListener);
1981
- return () => window.removeEventListener("message", eventListener);
1982
- }, [action]);
1983
- };
1984
- function getNested(obj, path) {
1985
- return path.split(".").reduce((acc, key) => acc ? acc[key] : void 0, obj);
1986
- }
1987
- function setNested(obj, path, value) {
1988
- const keys = path.split(".");
1989
- const root = Array.isArray(obj) ? [...obj] : { ...obj };
1990
- let current = root;
1991
- for (let i = 0; i < keys.length - 1; i++) {
1992
- const key = keys[i];
1993
- const nextKey = keys[i + 1];
1994
- const isIndex = !isNaN(Number(nextKey));
1995
- const existing = current[key];
1996
- current[key] = existing != null ? Array.isArray(existing) ? [...existing] : { ...existing } : isIndex ? [] : {};
1997
- current = current[key];
3323
+ var ModalContext = createContext(null);
3324
+ function useModal(selector) {
3325
+ const modal = useContext(ModalContext);
3326
+ if (!modal) {
3327
+ throw new Error("useModal must be used within a ModalProvider");
1998
3328
  }
1999
- current[keys[keys.length - 1]] = value;
2000
- return root;
3329
+ return useStore(modal, selector);
2001
3330
  }
2002
- function deleteNested(obj, path) {
2003
- const keys = path.split(".");
2004
- const newObj = { ...obj };
2005
- let current = newObj;
2006
- for (let i = 0; i < keys.length - 1; i++) {
2007
- const key = keys[i];
2008
- if (!current[key]) return obj;
2009
- current[key] = { ...current[key] };
2010
- current = current[key];
2011
- }
2012
- delete current[keys[keys.length - 1]];
2013
- return newObj;
3331
+ function StoreModal() {
3332
+ const active = useModal((state) => state.active);
3333
+ const { hideModal } = useModalActions();
3334
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: active && /* @__PURE__ */ jsx(
3335
+ Modal,
3336
+ {
3337
+ title: active.title,
3338
+ icon: active.icon,
3339
+ iconColor: active.iconColor,
3340
+ description: active.description,
3341
+ badge: active.badge,
3342
+ onClose: hideModal,
3343
+ width: active.width,
3344
+ maxHeight: active.maxHeight,
3345
+ height: active.height,
3346
+ zIndex: active.zIndex,
3347
+ clickOutside: active.clickOutside,
3348
+ children: active.children
3349
+ }
3350
+ ) });
2014
3351
  }
2015
- function flattenRules(rules, prefix = "") {
2016
- const result = {};
2017
- for (const key in rules) {
2018
- const fullPath = prefix ? `${prefix}.${key}` : key;
2019
- const val = rules[key];
2020
- if (typeof val === "function") result[fullPath] = val;
2021
- else if (typeof val === "object")
2022
- Object.assign(result, flattenRules(val, fullPath));
2023
- }
2024
- return result;
3352
+ function ModalProvider({ children }) {
3353
+ const storeRef = useRef(
3354
+ create(() => ({
3355
+ active: null
3356
+ }))
3357
+ );
3358
+ return /* @__PURE__ */ jsxs(ModalContext.Provider, { value: storeRef.current, children: [
3359
+ /* @__PURE__ */ jsx(StoreModal, {}),
3360
+ children
3361
+ ] });
2025
3362
  }
2026
- async function runRule(rule, value, values) {
2027
- const result = rule(value, values);
2028
- return result instanceof Promise ? await result : result;
3363
+ function useModalActions() {
3364
+ const modal = useContext(ModalContext);
3365
+ if (!modal) throw new Error("useModalActions must be used within a ModalProvider");
3366
+ const showModal = (openModal) => {
3367
+ modal.setState({ active: openModal });
3368
+ };
3369
+ const hideModal = () => {
3370
+ modal.setState({ active: null });
3371
+ };
3372
+ return { showModal, hideModal };
2029
3373
  }
2030
- function createFormStore(initialValues, validationRules, onSubmit) {
2031
- const flatRules = validationRules ? flattenRules(validationRules) : {};
2032
- const history = [];
2033
- const future = [];
2034
- const changed = /* @__PURE__ */ new Set();
2035
- function computeChanged(values, initialVals) {
2036
- const allKeys = /* @__PURE__ */ new Set([
2037
- ...Object.keys(values),
2038
- ...Object.keys(initialVals)
2039
- ]);
2040
- const fields = [];
2041
- let partial = {};
2042
- for (const key of allKeys) {
2043
- if (values[key] !== initialVals[key]) {
2044
- fields.push(key);
2045
- partial = setNested(partial, key, values[key]);
2046
- }
2047
- }
2048
- return { fields, partial };
2049
- }
2050
- return createStore((set, get) => ({
2051
- initialValues,
2052
- values: initialValues,
2053
- errors: {},
2054
- partialChanged: {},
2055
- canBack: false,
2056
- canForward: false,
2057
- changedFields: [],
2058
- changedCount: 0,
2059
- onSubmit,
2060
- submit: async () => {
2061
- const state = get();
2062
- const isValid = await state.validate();
2063
- if (isValid && state.onSubmit) {
2064
- state.onSubmit(get());
2065
- }
2066
- },
2067
- getInputProps: (path) => {
2068
- return {
2069
- value: getNested(get().values, path) ?? "",
2070
- error: get().errors[path],
2071
- onChange: (e) => {
2072
- get().setValue(path, e.target.value, { validate: true });
2073
- }
2074
- };
2075
- },
2076
- resetChangeCount: () => {
2077
- changed.clear();
2078
- set({ changedFields: [], changedCount: 0, partialChanged: {} });
2079
- },
2080
- setInitialValues: (newInitialValues) => set({ initialValues: newInitialValues }),
3374
+ function ConfirmModal({
3375
+ title,
3376
+ description: description2,
3377
+ confirmLabel = "Delete",
3378
+ confirmText,
3379
+ onConfirm,
3380
+ onClose,
3381
+ zIndex = 200
3382
+ }) {
3383
+ const theme2 = useMantineTheme();
3384
+ const [typed, setTyped] = useState("");
3385
+ const canConfirm = !confirmText || typed === confirmText;
3386
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(
3387
+ motion.div,
3388
+ {
3389
+ initial: { opacity: 0 },
3390
+ animate: { opacity: 1 },
3391
+ exit: { opacity: 0 },
3392
+ style: {
3393
+ position: "fixed",
3394
+ inset: 0,
3395
+ zIndex,
3396
+ display: "flex",
3397
+ alignItems: "center",
3398
+ justifyContent: "center",
3399
+ background: "rgba(0,0,0,0.7)"
3400
+ },
3401
+ onClick: onClose,
3402
+ children: /* @__PURE__ */ jsxs(
3403
+ motion.div,
3404
+ {
3405
+ initial: { opacity: 0, scale: 0.95, y: 8 },
3406
+ animate: { opacity: 1, scale: 1, y: 0 },
3407
+ exit: { opacity: 0, scale: 0.95, y: 8 },
3408
+ transition: { duration: 0.18, ease: "easeOut" },
3409
+ onClick: (e) => e.stopPropagation(),
3410
+ style: {
3411
+ background: alpha(theme2.colors.dark[9], 0.98),
3412
+ border: `0.1vh solid ${alpha("#ef4444", 0.3)}`,
3413
+ borderRadius: theme2.radius.sm,
3414
+ width: "44vh",
3415
+ display: "flex",
3416
+ flexDirection: "column",
3417
+ overflow: "hidden"
3418
+ },
3419
+ children: [
3420
+ /* @__PURE__ */ jsxs(
3421
+ Flex,
3422
+ {
3423
+ justify: "space-between",
3424
+ align: "center",
3425
+ px: "sm",
3426
+ py: "xs",
3427
+ style: {
3428
+ borderBottom: `0.1vh solid ${alpha("#ef4444", 0.2)}`,
3429
+ background: alpha("#ef4444", 0.06),
3430
+ flexShrink: 0
3431
+ },
3432
+ children: [
3433
+ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xs", children: [
3434
+ /* @__PURE__ */ jsx(AlertTriangle, { size: "1.8vh", color: "#ef4444" }),
3435
+ /* @__PURE__ */ jsx(
3436
+ Text,
3437
+ {
3438
+ ff: "Akrobat Bold",
3439
+ size: "sm",
3440
+ tt: "uppercase",
3441
+ lts: "0.05em",
3442
+ c: "#ef4444",
3443
+ children: title
3444
+ }
3445
+ )
3446
+ ] }),
3447
+ /* @__PURE__ */ jsx(
3448
+ motion.button,
3449
+ {
3450
+ onClick: onClose,
3451
+ whileHover: { background: alpha(theme2.colors.dark[7], 0.5) },
3452
+ style: {
3453
+ background: "transparent",
3454
+ border: "none",
3455
+ cursor: "pointer",
3456
+ padding: theme2.spacing.xxs,
3457
+ borderRadius: theme2.radius.xs,
3458
+ display: "flex"
3459
+ },
3460
+ children: /* @__PURE__ */ jsx(X, { color: "rgba(255,255,255,0.4)" })
3461
+ }
3462
+ )
3463
+ ]
3464
+ }
3465
+ ),
3466
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "sm", p: "sm", children: [
3467
+ /* @__PURE__ */ jsx(
3468
+ Text,
3469
+ {
3470
+ ff: "Akrobat Regular",
3471
+ size: "xs",
3472
+ c: "rgba(255,255,255,0.65)",
3473
+ style: { lineHeight: 1.5 },
3474
+ children: description2
3475
+ }
3476
+ ),
3477
+ confirmText && /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "xxs", children: [
3478
+ /* @__PURE__ */ jsxs(
3479
+ Text,
3480
+ {
3481
+ ff: "Akrobat Bold",
3482
+ size: "xxs",
3483
+ tt: "uppercase",
3484
+ lts: "0.07em",
3485
+ c: "rgba(255,255,255,0.35)",
3486
+ children: [
3487
+ "Type",
3488
+ " ",
3489
+ /* @__PURE__ */ jsx(Text, { component: "span", ff: "Akrobat Bold", c: "#ef4444", children: confirmText }),
3490
+ " ",
3491
+ "to confirm"
3492
+ ]
3493
+ }
3494
+ ),
3495
+ /* @__PURE__ */ jsx(
3496
+ TextInput,
3497
+ {
3498
+ size: "xs",
3499
+ placeholder: confirmText,
3500
+ value: typed,
3501
+ onChange: (e) => setTyped(e.currentTarget.value),
3502
+ styles: (t) => ({
3503
+ input: {
3504
+ backgroundColor: alpha(t.colors.dark[7], 0.5),
3505
+ border: `0.1vh solid ${alpha(
3506
+ typed === confirmText ? "#ef4444" : t.colors.dark[5],
3507
+ 0.5
3508
+ )}`,
3509
+ color: "rgba(255,255,255,0.85)",
3510
+ fontFamily: "Akrobat Regular"
3511
+ }
3512
+ }),
3513
+ autoFocus: true
3514
+ }
3515
+ )
3516
+ ] })
3517
+ ] }),
3518
+ /* @__PURE__ */ jsxs(
3519
+ Flex,
3520
+ {
3521
+ justify: "flex-end",
3522
+ gap: "xs",
3523
+ px: "sm",
3524
+ py: "sm",
3525
+ style: {
3526
+ borderTop: `0.1vh solid ${theme2.colors.dark[7]}`,
3527
+ flexShrink: 0
3528
+ },
3529
+ children: [
3530
+ /* @__PURE__ */ jsxs(
3531
+ motion.button,
3532
+ {
3533
+ onClick: onClose,
3534
+ whileHover: { background: alpha(theme2.colors.dark[7], 0.5) },
3535
+ whileTap: { scale: 0.97 },
3536
+ style: {
3537
+ background: "transparent",
3538
+ border: `0.1vh solid ${theme2.colors.dark[6]}`,
3539
+ borderRadius: theme2.radius.xs,
3540
+ padding: "0.5vh 1vh",
3541
+ cursor: "pointer",
3542
+ display: "flex",
3543
+ alignItems: "center",
3544
+ gap: "0.4vh"
3545
+ },
3546
+ children: [
3547
+ /* @__PURE__ */ jsx(X, { size: "1.4vh", color: "rgba(255,255,255,0.4)" }),
3548
+ /* @__PURE__ */ jsx(
3549
+ Text,
3550
+ {
3551
+ ff: "Akrobat Bold",
3552
+ size: "xxs",
3553
+ tt: "uppercase",
3554
+ lts: "0.05em",
3555
+ c: "rgba(255,255,255,0.4)",
3556
+ children: "Cancel"
3557
+ }
3558
+ )
3559
+ ]
3560
+ }
3561
+ ),
3562
+ /* @__PURE__ */ jsxs(
3563
+ motion.button,
3564
+ {
3565
+ onClick: () => {
3566
+ if (canConfirm) {
3567
+ onConfirm();
3568
+ onClose();
3569
+ }
3570
+ },
3571
+ whileHover: canConfirm ? {
3572
+ background: alpha("#ef4444", 0.22),
3573
+ borderColor: alpha("#ef4444", 0.6)
3574
+ } : void 0,
3575
+ whileTap: canConfirm ? { scale: 0.97 } : void 0,
3576
+ style: {
3577
+ background: alpha("#ef4444", canConfirm ? 0.14 : 0.05),
3578
+ border: `0.1vh solid ${alpha(
3579
+ "#ef4444",
3580
+ canConfirm ? 0.45 : 0.15
3581
+ )}`,
3582
+ borderRadius: theme2.radius.xs,
3583
+ padding: "0.5vh 1vh",
3584
+ cursor: canConfirm ? "pointer" : "not-allowed",
3585
+ display: "flex",
3586
+ alignItems: "center",
3587
+ gap: "0.4vh",
3588
+ opacity: canConfirm ? 1 : 0.45,
3589
+ transition: "opacity 0.15s"
3590
+ },
3591
+ children: [
3592
+ /* @__PURE__ */ jsx(Trash2, { size: "1.4vh", color: "#ef4444" }),
3593
+ /* @__PURE__ */ jsx(
3594
+ Text,
3595
+ {
3596
+ ff: "Akrobat Bold",
3597
+ size: "xxs",
3598
+ tt: "uppercase",
3599
+ lts: "0.05em",
3600
+ c: "#ef4444",
3601
+ children: confirmLabel
3602
+ }
3603
+ )
3604
+ ]
3605
+ }
3606
+ )
3607
+ ]
3608
+ }
3609
+ )
3610
+ ]
3611
+ }
3612
+ )
3613
+ }
3614
+ ) });
3615
+ }
3616
+ function getNested(obj, path) {
3617
+ return path.split(".").reduce((acc, key) => acc ? acc[key] : void 0, obj);
3618
+ }
3619
+ function setNested(obj, path, value) {
3620
+ const keys = path.split(".");
3621
+ const root = Array.isArray(obj) ? [...obj] : { ...obj };
3622
+ let current = root;
3623
+ for (let i = 0; i < keys.length - 1; i++) {
3624
+ const key = keys[i];
3625
+ const nextKey = keys[i + 1];
3626
+ const isIndex = !isNaN(Number(nextKey));
3627
+ const existing = current[key];
3628
+ current[key] = existing != null ? Array.isArray(existing) ? [...existing] : { ...existing } : isIndex ? [] : {};
3629
+ current = current[key];
3630
+ }
3631
+ current[keys[keys.length - 1]] = value;
3632
+ return root;
3633
+ }
3634
+ function deleteNested(obj, path) {
3635
+ const keys = path.split(".");
3636
+ const newObj = { ...obj };
3637
+ let current = newObj;
3638
+ for (let i = 0; i < keys.length - 1; i++) {
3639
+ const key = keys[i];
3640
+ if (!current[key]) return obj;
3641
+ current[key] = { ...current[key] };
3642
+ current = current[key];
3643
+ }
3644
+ delete current[keys[keys.length - 1]];
3645
+ return newObj;
3646
+ }
3647
+ function isPlainObject(value) {
3648
+ return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
3649
+ }
3650
+ function collectChangedPaths(values, initial, prefix = "") {
3651
+ if (Object.is(values, initial)) return [];
3652
+ const valuesIsObj = isPlainObject(values);
3653
+ const initialIsObj = isPlainObject(initial);
3654
+ const valuesIsArr = Array.isArray(values);
3655
+ const initialIsArr = Array.isArray(initial);
3656
+ if (valuesIsArr || initialIsArr) {
3657
+ const maxLen = Math.max(values?.length ?? 0, initial?.length ?? 0);
3658
+ const fields = [];
3659
+ for (let i = 0; i < maxLen; i++) {
3660
+ const nextPrefix = prefix ? `${prefix}.${i}` : `${i}`;
3661
+ fields.push(...collectChangedPaths(values?.[i], initial?.[i], nextPrefix));
3662
+ }
3663
+ return fields;
3664
+ }
3665
+ if (valuesIsObj || initialIsObj) {
3666
+ const keys = /* @__PURE__ */ new Set([
3667
+ ...Object.keys(values ?? {}),
3668
+ ...Object.keys(initial ?? {})
3669
+ ]);
3670
+ const fields = [];
3671
+ for (const key of keys) {
3672
+ const nextPrefix = prefix ? `${prefix}.${key}` : key;
3673
+ fields.push(...collectChangedPaths(values?.[key], initial?.[key], nextPrefix));
3674
+ }
3675
+ return fields;
3676
+ }
3677
+ return prefix ? [prefix] : [];
3678
+ }
3679
+ function computeChangedState(values, initialVals) {
3680
+ const fields = collectChangedPaths(values, initialVals);
3681
+ let partial = {};
3682
+ for (const path of fields) {
3683
+ partial = setNested(partial, path, getNested(values, path));
3684
+ }
3685
+ return { fields, partial };
3686
+ }
3687
+ function flattenRules(rules, prefix = "") {
3688
+ const result = {};
3689
+ for (const key in rules) {
3690
+ const fullPath = prefix ? `${prefix}.${key}` : key;
3691
+ const val = rules[key];
3692
+ if (typeof val === "function") result[fullPath] = val;
3693
+ else if (typeof val === "object")
3694
+ Object.assign(result, flattenRules(val, fullPath));
3695
+ }
3696
+ return result;
3697
+ }
3698
+ async function runRule(rule, value, values) {
3699
+ const result = rule(value, values);
3700
+ return result instanceof Promise ? await result : result;
3701
+ }
3702
+ function createFormStore(initialValues, validationRules, onSubmit) {
3703
+ const flatRules = validationRules ? flattenRules(validationRules) : {};
3704
+ const history = [];
3705
+ const future = [];
3706
+ const changed = /* @__PURE__ */ new Set();
3707
+ return createStore((set, get) => ({
3708
+ initialValues,
3709
+ values: initialValues,
3710
+ errors: {},
3711
+ partialChanged: {},
3712
+ canBack: false,
3713
+ canForward: false,
3714
+ changedFields: [],
3715
+ changedCount: 0,
3716
+ onSubmit,
3717
+ submit: async () => {
3718
+ const state = get();
3719
+ const isValid = await state.validate();
3720
+ if (isValid && state.onSubmit) {
3721
+ state.onSubmit(get());
3722
+ }
3723
+ },
3724
+ getInputProps: (path) => {
3725
+ return {
3726
+ value: getNested(get().values, path) ?? "",
3727
+ error: get().errors[path],
3728
+ onChange: (e) => {
3729
+ get().setValue(path, e.target.value, { validate: true });
3730
+ }
3731
+ };
3732
+ },
3733
+ resetChangeCount: () => {
3734
+ changed.clear();
3735
+ set({ changedFields: [], changedCount: 0, partialChanged: {} });
3736
+ },
3737
+ setInitialValues: (newInitialValues) => set({ initialValues: newInitialValues }),
2081
3738
  setValue: (path, value, options) => {
2082
3739
  const state = get();
2083
3740
  const currentValues = state.values;
@@ -2176,7 +3833,7 @@ function createFormStore(initialValues, validationRules, onSubmit) {
2176
3833
  if (!history.length) return;
2177
3834
  const prev = history.pop();
2178
3835
  future.push(get().values);
2179
- const { fields, partial } = computeChanged(prev, get().initialValues);
3836
+ const { fields, partial } = computeChangedState(prev, get().initialValues);
2180
3837
  set({
2181
3838
  values: prev,
2182
3839
  partialChanged: partial,
@@ -2190,7 +3847,7 @@ function createFormStore(initialValues, validationRules, onSubmit) {
2190
3847
  if (!future.length) return;
2191
3848
  const next = future.pop();
2192
3849
  history.push(get().values);
2193
- const { fields, partial } = computeChanged(next, get().initialValues);
3850
+ const { fields, partial } = computeChangedState(next, get().initialValues);
2194
3851
  set({
2195
3852
  values: next,
2196
3853
  partialChanged: partial,
@@ -2219,7 +3876,11 @@ function useForm() {
2219
3876
  if (!store) {
2220
3877
  throw new Error("useForm must be used inside <FormProvider>");
2221
3878
  }
2222
- return useStore(store);
3879
+ const state = useStore(store);
3880
+ const changedFields = useMemo(() => {
3881
+ return collectChangedPaths(state.values, state.initialValues);
3882
+ }, [state.values, state.initialValues]);
3883
+ return { ...state, changedFields, changedCount: changedFields.length };
2223
3884
  }
2224
3885
  function useFormField(path) {
2225
3886
  const store = useContext(FormContext);
@@ -2268,6 +3929,820 @@ function useFormActions() {
2268
3929
  }
2269
3930
  return store.getState();
2270
3931
  }
3932
+ var _instance = null;
3933
+ function getScriptSettingsInstance() {
3934
+ if (!_instance) throw new Error("[dirk-cfx-react] createScriptSettings must be called before using SettingsPanel");
3935
+ return _instance;
3936
+ }
3937
+ function createScriptSettings(defaultValue) {
3938
+ const store = create(() => defaultValue);
3939
+ let clientVersion = 0;
3940
+ const useScriptSettingHooks = () => {
3941
+ };
3942
+ const updateScriptSettings = async (newSettings) => {
3943
+ store.setState((prev) => ({ ...prev, ...newSettings }));
3944
+ const response = await fetchNui("UPDATE_SCRIPT_SETTINGS", {
3945
+ data: newSettings,
3946
+ expectedVersion: clientVersion
3947
+ });
3948
+ if (response?.meta?.client_version != null) {
3949
+ clientVersion = response.meta.client_version;
3950
+ }
3951
+ if (response?.success === false && response?.meta?.latestData) {
3952
+ store.setState((prev) => ({ ...prev, ...response.meta.latestData }));
3953
+ }
3954
+ return response;
3955
+ };
3956
+ const getScriptSettingsHistory = async (params = {}) => {
3957
+ return fetchNui("GET_SCRIPT_SETTINGS_HISTORY", params);
3958
+ };
3959
+ _instance = {
3960
+ store,
3961
+ updateSettings: updateScriptSettings,
3962
+ getHistory: getScriptSettingsHistory
3963
+ };
3964
+ return { store, updateScriptSettings, getScriptSettingsHistory, useScriptSettingHooks };
3965
+ }
3966
+ var settingsPanelQueryClient = new QueryClient({
3967
+ defaultOptions: { queries: { staleTime: 3e4, gcTime: 5 * 6e4 } }
3968
+ });
3969
+ function NavItemButton({
3970
+ icon: Icon,
3971
+ label: label2,
3972
+ active,
3973
+ onClick
3974
+ }) {
3975
+ const theme2 = useMantineTheme();
3976
+ const color = theme2.colors[theme2.primaryColor][5];
3977
+ return /* @__PURE__ */ jsxs(
3978
+ motion.button,
3979
+ {
3980
+ onClick,
3981
+ whileHover: { background: active ? alpha(color, 0.15) : "rgba(255,255,255,0.04)" },
3982
+ whileTap: { scale: 0.97 },
3983
+ style: {
3984
+ width: "100%",
3985
+ background: active ? alpha(color, 0.12) : "transparent",
3986
+ border: "none",
3987
+ borderLeft: `0.2vh solid ${active ? color : "transparent"}`,
3988
+ borderRadius: `0 ${theme2.radius.xs} ${theme2.radius.xs} 0`,
3989
+ padding: "0.7vh 1vh",
3990
+ cursor: "pointer",
3991
+ display: "flex",
3992
+ alignItems: "center",
3993
+ gap: "0.7vh",
3994
+ transition: "border-color 0.15s, background 0.15s"
3995
+ },
3996
+ children: [
3997
+ /* @__PURE__ */ jsx(Icon, { color: active ? color : "rgba(255,255,255,0.35)" }),
3998
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.06em", c: active ? color : "rgba(255,255,255,0.35)", children: label2 }),
3999
+ active && /* @__PURE__ */ jsx(
4000
+ motion.div,
4001
+ {
4002
+ layoutId: "nav-active-dot",
4003
+ style: { marginLeft: "auto", width: "0.4vh", height: "0.4vh", borderRadius: "50%", background: color }
4004
+ }
4005
+ )
4006
+ ]
4007
+ }
4008
+ );
4009
+ }
4010
+ function SettingsJsonModal({
4011
+ onClose,
4012
+ schema
4013
+ }) {
4014
+ const theme2 = useMantineTheme();
4015
+ const color = theme2.colors[theme2.primaryColor][5];
4016
+ const form = useForm();
4017
+ const [json, setJson] = useState(() => JSON.stringify(form.values, null, 2));
4018
+ const [error2, setError] = useState(null);
4019
+ const handleSave = () => {
4020
+ try {
4021
+ const parsed = JSON.parse(json);
4022
+ if (schema) {
4023
+ const result = schema.safeParse(parsed);
4024
+ if (!result.success) {
4025
+ setError(result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("\n"));
4026
+ return;
4027
+ }
4028
+ const current = form.values;
4029
+ Object.keys(result.data).forEach((key) => {
4030
+ if (JSON.stringify(result.data[key]) !== JSON.stringify(current[key])) {
4031
+ form.setValue(key, result.data[key]);
4032
+ }
4033
+ });
4034
+ } else {
4035
+ const current = form.values;
4036
+ Object.keys(parsed).forEach((key) => {
4037
+ if (JSON.stringify(parsed[key]) !== JSON.stringify(current[key])) {
4038
+ form.setValue(key, parsed[key]);
4039
+ }
4040
+ });
4041
+ }
4042
+ onClose();
4043
+ } catch (e) {
4044
+ setError(e.message);
4045
+ }
4046
+ };
4047
+ return /* @__PURE__ */ jsxs(Modal, { title: "Settings JSON", icon: Code2, iconColor: color, onClose, width: "60vh", maxHeight: "80vh", zIndex: 200, children: [
4048
+ /* @__PURE__ */ jsxs(Box, { flex: 1, p: "0.8vh", style: { overflowY: "auto" }, children: [
4049
+ /* @__PURE__ */ jsx(
4050
+ JsonInput,
4051
+ {
4052
+ value: json,
4053
+ spellCheck: false,
4054
+ onChange: setJson,
4055
+ rows: 22,
4056
+ formatOnBlur: true,
4057
+ validationError: "Invalid JSON",
4058
+ styles: () => ({
4059
+ input: { fontFamily: "monospace", fontSize: "1.3vh", lineHeight: 1.6, resize: "none" }
4060
+ })
4061
+ }
4062
+ ),
4063
+ error2 && /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "#ef4444", mt: "xxs", children: error2 })
4064
+ ] }),
4065
+ /* @__PURE__ */ jsxs(Flex, { justify: "flex-end", gap: "xs", px: "sm", py: "xs", style: { borderTop: `0.1vh solid ${theme2.colors.dark[7]}`, flexShrink: 0 }, children: [
4066
+ /* @__PURE__ */ jsxs(
4067
+ motion.button,
4068
+ {
4069
+ onClick: onClose,
4070
+ whileHover: { background: alpha(theme2.colors.dark[7], 0.5) },
4071
+ whileTap: { scale: 0.97 },
4072
+ style: { background: "transparent", border: `0.1vh solid ${theme2.colors.dark[6]}`, borderRadius: theme2.radius.xs, padding: `${theme2.spacing.xxs} ${theme2.spacing.xs}`, cursor: "pointer", display: "flex", alignItems: "center", gap: theme2.spacing.xxs },
4073
+ children: [
4074
+ /* @__PURE__ */ jsx(X, { color: "rgba(255,255,255,0.4)" }),
4075
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: "Cancel" })
4076
+ ]
4077
+ }
4078
+ ),
4079
+ /* @__PURE__ */ jsxs(
4080
+ motion.button,
4081
+ {
4082
+ onClick: handleSave,
4083
+ whileHover: { background: alpha(color, 0.25) },
4084
+ whileTap: { scale: 0.97 },
4085
+ style: { background: alpha(color, 0.14), border: `0.1vh solid ${alpha(color, 0.4)}`, borderRadius: theme2.radius.xs, padding: `${theme2.spacing.xxs} ${theme2.spacing.xs}`, cursor: "pointer", display: "flex", alignItems: "center", gap: theme2.spacing.xxs },
4086
+ children: [
4087
+ /* @__PURE__ */ jsx(Check, { color }),
4088
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: color, children: "Apply" })
4089
+ ]
4090
+ }
4091
+ )
4092
+ ] })
4093
+ ] });
4094
+ }
4095
+ function formatValue(value) {
4096
+ if (value === null) return "null";
4097
+ if (value === void 0) return "undefined";
4098
+ if (typeof value === "string") return value;
4099
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
4100
+ try {
4101
+ return JSON.stringify(value);
4102
+ } catch {
4103
+ return String(value);
4104
+ }
4105
+ }
4106
+ function formatHistoryDateTime(entry) {
4107
+ if (entry.at_unix) {
4108
+ const date = new Date(entry.at_unix * 1e3);
4109
+ if (!Number.isNaN(date.getTime())) {
4110
+ return date.toLocaleString(void 0, { year: "numeric", month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit" });
4111
+ }
4112
+ }
4113
+ if (entry.at_utc) {
4114
+ const date = new Date(entry.at_utc);
4115
+ if (!Number.isNaN(date.getTime())) {
4116
+ return date.toLocaleString(void 0, { year: "numeric", month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit" });
4117
+ }
4118
+ }
4119
+ return "Unknown time";
4120
+ }
4121
+ function historyEntryKey(entry, index) {
4122
+ return `${entry.at_unix}-${entry.applied_version}-${index}`;
4123
+ }
4124
+ function ChangeDetails({ entry }) {
4125
+ const theme2 = useMantineTheme();
4126
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "0.45vh", p: "0.8vh", style: { border: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.8)}`, borderRadius: theme2.radius.xs, background: alpha(theme2.colors.dark[9], 0.35) }, children: [
4127
+ /* @__PURE__ */ jsxs(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: [
4128
+ "Version ",
4129
+ entry.expected_version ?? "?",
4130
+ " ",
4131
+ "\u2192",
4132
+ " ",
4133
+ entry.applied_version ?? "?"
4134
+ ] }),
4135
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "minmax(18vh, 22vh) minmax(0, 1fr) minmax(0, 1fr)", gap: "0.1vh", border: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.9)}`, borderRadius: theme2.radius.xs, overflow: "hidden", background: alpha(theme2.colors.dark[6], 0.8) }, children: [
4136
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", px: "0.6vh", py: "0.45vh", style: { background: alpha(theme2.colors.dark[8], 0.85) }, children: "Path" }),
4137
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", px: "0.6vh", py: "0.45vh", style: { background: alpha(theme2.colors.dark[8], 0.85) }, children: "From" }),
4138
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", px: "0.6vh", py: "0.45vh", style: { background: alpha(theme2.colors.dark[8], 0.85) }, children: "To" }),
4139
+ (entry.changes || []).map((change, idx) => {
4140
+ const bg = idx % 2 === 0 ? alpha(theme2.colors.dark[9], 0.5) : alpha(theme2.colors.dark[8], 0.42);
4141
+ return [
4142
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "#8ad1ff", px: "0.6vh", py: "0.55vh", style: { background: bg, wordBreak: "break-word" }, children: change.path }, `${idx}-p`),
4143
+ /* @__PURE__ */ jsx(Text, { ff: "monospace", size: "xxs", c: "rgba(255,255,255,0.5)", px: "0.6vh", py: "0.55vh", style: { background: bg, wordBreak: "break-word", whiteSpace: "pre-wrap" }, children: formatValue(change.old) }, `${idx}-o`),
4144
+ /* @__PURE__ */ jsx(Text, { ff: "monospace", size: "xxs", c: "rgba(255,255,255,0.78)", px: "0.6vh", py: "0.55vh", style: { background: bg, wordBreak: "break-word", whiteSpace: "pre-wrap" }, children: formatValue(change.new) }, `${idx}-n`)
4145
+ ];
4146
+ })
4147
+ ] })
4148
+ ] });
4149
+ }
4150
+ function HistoryTableRow({ entry, expanded, onToggle }) {
4151
+ const theme2 = useMantineTheme();
4152
+ const admin = entry.admin?.name || entry.admin?.identifier || "unknown";
4153
+ const firstPath = entry.changes?.[0]?.path || "-";
4154
+ const changeCount = entry.changes?.length || 0;
4155
+ const versionText = `${entry.expected_version ?? "?"} \u2192 ${entry.applied_version ?? "?"}`;
4156
+ return /* @__PURE__ */ jsx(motion.div, { layout: true, initial: { opacity: 0, y: 6 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.16, ease: "easeOut" }, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "0.45vh", children: [
4157
+ /* @__PURE__ */ jsx(
4158
+ motion.button,
4159
+ {
4160
+ onClick: onToggle,
4161
+ whileHover: { scale: 1.002 },
4162
+ whileTap: { scale: 0.997 },
4163
+ transition: { duration: 0.12 },
4164
+ style: { background: expanded ? alpha(theme2.colors.dark[7], 0.45) : alpha(theme2.colors.dark[8], 0.35), border: `0.1vh solid ${expanded ? alpha(theme2.colors[theme2.primaryColor][5], 0.35) : alpha(theme2.colors.dark[6], 0.75)}`, borderRadius: theme2.radius.xs, padding: "0.65vh 0.75vh", cursor: "pointer", textAlign: "left" },
4165
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "2.2vh 20vh 12vh 6vh 1fr minmax(16vh, auto)", gap: "0.8vh", alignItems: "center" }, children: [
4166
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx(motion.div, { animate: { rotate: expanded ? 0 : -90 }, transition: { duration: 0.18, ease: "easeOut" }, children: /* @__PURE__ */ jsx(ChevronDown, { size: "1.5vh", color: expanded ? "rgba(255,255,255,0.6)" : "rgba(255,255,255,0.45)" }) }) }),
4167
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.75)", lineClamp: 1, children: formatHistoryDateTime(entry) }),
4168
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.68)", lineClamp: 1, children: admin }),
4169
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.68)", children: changeCount }),
4170
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.58)", lineClamp: 1, children: firstPath }),
4171
+ /* @__PURE__ */ jsx(Text, { ff: "monospace", size: "xxs", c: "rgba(255,255,255,0.68)", children: versionText })
4172
+ ] })
4173
+ }
4174
+ ),
4175
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: expanded && /* @__PURE__ */ jsx(motion.div, { initial: { opacity: 0, height: 0, y: -4 }, animate: { opacity: 1, height: "auto", y: 0 }, exit: { opacity: 0, height: 0, y: -4 }, transition: { duration: 0.2, ease: "easeInOut" }, style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx(ChangeDetails, { entry }) }, "details") })
4176
+ ] }) });
4177
+ }
4178
+ function HistoryTableHeader() {
4179
+ const theme2 = useMantineTheme();
4180
+ return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "2.2vh 20vh 12vh 6vh 1fr minmax(16vh, auto)", gap: "0.8vh", alignItems: "center", border: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.8)}`, borderRadius: theme2.radius.xs, background: alpha(theme2.colors.dark[8], 0.55), padding: "0.55vh 0.75vh" }, children: [
4181
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.35)", children: " " }),
4182
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Time" }),
4183
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Admin" }),
4184
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "#" }),
4185
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "First Change" }),
4186
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: "Version" })
4187
+ ] });
4188
+ }
4189
+ function SettingsHistoryModal({
4190
+ onClose
4191
+ }) {
4192
+ const { getHistory } = getScriptSettingsInstance();
4193
+ const theme2 = useMantineTheme();
4194
+ const color = theme2.colors[theme2.primaryColor][5];
4195
+ const [queryInput, setQueryInput] = useState("");
4196
+ const [pathInput, setPathInput] = useState("");
4197
+ const [adminInput, setAdminInput] = useState("");
4198
+ const [query, setQuery] = useState("");
4199
+ const [path, setPath] = useState("");
4200
+ const [admin, setAdmin] = useState("");
4201
+ const [expandedKey, setExpandedKey] = useState(null);
4202
+ const filters = useMemo(() => ({ query, path, admin }), [query, path, admin]);
4203
+ const historyQuery = useInfiniteQuery({
4204
+ queryKey: ["scriptSettingsHistory", filters],
4205
+ initialPageParam: 0,
4206
+ queryFn: async ({ pageParam }) => {
4207
+ const response = await getHistory({
4208
+ offset: pageParam,
4209
+ limit: 25,
4210
+ query: filters.query || void 0,
4211
+ path: filters.path || void 0,
4212
+ admin: filters.admin || void 0
4213
+ });
4214
+ if (!response?.success || !response.data) {
4215
+ throw new Error(response?._error || "Failed to load settings history");
4216
+ }
4217
+ return response.data;
4218
+ },
4219
+ getNextPageParam: (lastPage) => lastPage.nextOffset
4220
+ });
4221
+ const rows = historyQuery.data?.pages.flatMap((page) => page.items) ?? [];
4222
+ const total = historyQuery.data?.pages[0]?.total ?? 0;
4223
+ const handleListScroll = (e) => {
4224
+ const el = e.currentTarget;
4225
+ if (el.scrollHeight - el.scrollTop - el.clientHeight < 280 && historyQuery.hasNextPage && !historyQuery.isFetchingNextPage) {
4226
+ historyQuery.fetchNextPage();
4227
+ }
4228
+ };
4229
+ return /* @__PURE__ */ jsxs(Modal, { title: "Settings History", icon: History, iconColor: color, onClose, width: "88vh", maxHeight: "82vh", zIndex: 260, children: [
4230
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { flex: 1, minHeight: 0 }, children: [
4231
+ /* @__PURE__ */ jsxs(Flex, { gap: "xs", p: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme2.colors.dark[7], 0.8)}` }, children: [
4232
+ /* @__PURE__ */ jsx(TextInput, { leftSection: /* @__PURE__ */ jsx(Search, { size: "1.4vh" }), placeholder: "Search path/admin/value", value: queryInput, onChange: (e) => setQueryInput(e.currentTarget.value), size: "xs", style: { flex: 1 } }),
4233
+ /* @__PURE__ */ jsx(TextInput, { leftSection: /* @__PURE__ */ jsx(Filter, { size: "1.4vh" }), placeholder: "Path filter (e.g. basic.weightUnit)", value: pathInput, onChange: (e) => setPathInput(e.currentTarget.value), size: "xs", style: { flex: 1 } }),
4234
+ /* @__PURE__ */ jsx(TextInput, { leftSection: /* @__PURE__ */ jsx(User, { size: "1.4vh" }), placeholder: "Admin filter", value: adminInput, onChange: (e) => setAdminInput(e.currentTarget.value), size: "xs", style: { flex: 1 } }),
4235
+ /* @__PURE__ */ jsx(
4236
+ motion.button,
4237
+ {
4238
+ onClick: () => {
4239
+ setExpandedKey(null);
4240
+ setQuery(queryInput.trim());
4241
+ setPath(pathInput.trim().toLowerCase());
4242
+ setAdmin(adminInput.trim().toLowerCase());
4243
+ },
4244
+ whileHover: { background: alpha(color, 0.2) },
4245
+ whileTap: { scale: 0.97 },
4246
+ style: { background: alpha(color, 0.12), border: `0.1vh solid ${alpha(color, 0.35)}`, borderRadius: theme2.radius.xs, padding: "0.55vh 0.85vh", cursor: "pointer" },
4247
+ children: /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: color, children: "Apply" })
4248
+ }
4249
+ )
4250
+ ] }),
4251
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "xs", p: "sm", style: { flex: 1, minHeight: 0, overflowY: "auto" }, onScroll: handleListScroll, children: [
4252
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", c: "rgba(255,255,255,0.45)", children: historyQuery.isFetching && !historyQuery.data ? "Loading history..." : `${total} entries` }),
4253
+ /* @__PURE__ */ jsx(HistoryTableHeader, {}),
4254
+ historyQuery.isError && /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", c: "#ef4444", children: historyQuery.error.message }),
4255
+ !historyQuery.isLoading && rows.length === 0 && !historyQuery.isError && /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", c: "rgba(255,255,255,0.45)", children: "No history found for current filters." }),
4256
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: rows.map((entry, index) => {
4257
+ const key = historyEntryKey(entry, index);
4258
+ return /* @__PURE__ */ jsx(HistoryTableRow, { entry, expanded: expandedKey === key, onToggle: () => setExpandedKey(expandedKey === key ? null : key) }, key);
4259
+ }) }),
4260
+ (historyQuery.isFetchingNextPage || historyQuery.isLoading) && /* @__PURE__ */ jsx(Flex, { justify: "center", py: "sm", children: /* @__PURE__ */ jsx(Loader, { size: "sm", color }) })
4261
+ ] })
4262
+ ] }),
4263
+ /* @__PURE__ */ jsx(Flex, { justify: "flex-end", gap: "xs", px: "sm", py: "xs", style: { borderTop: `0.1vh solid ${theme2.colors.dark[7]}`, flexShrink: 0 }, children: /* @__PURE__ */ jsxs(
4264
+ motion.button,
4265
+ {
4266
+ onClick: onClose,
4267
+ whileHover: { background: alpha(theme2.colors.dark[7], 0.5) },
4268
+ whileTap: { scale: 0.97 },
4269
+ style: { background: "transparent", border: `0.1vh solid ${theme2.colors.dark[6]}`, borderRadius: theme2.radius.xs, padding: `${theme2.spacing.xxs} ${theme2.spacing.xs}`, cursor: "pointer", display: "flex", alignItems: "center", gap: theme2.spacing.xxs },
4270
+ children: [
4271
+ /* @__PURE__ */ jsx(X, { color: "rgba(255,255,255,0.4)", size: "1.5vh" }),
4272
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.05em", c: "rgba(255,255,255,0.4)", children: "Close" })
4273
+ ]
4274
+ }
4275
+ ) })
4276
+ ] });
4277
+ }
4278
+ function SettingsPanelInner({
4279
+ navItems,
4280
+ title,
4281
+ subtitle,
4282
+ children,
4283
+ isSaving,
4284
+ onClose,
4285
+ schema,
4286
+ resetConfirmText,
4287
+ defaultSettings,
4288
+ width,
4289
+ height
4290
+ }) {
4291
+ const { updateSettings, getHistory } = getScriptSettingsInstance();
4292
+ const form = useForm();
4293
+ const theme2 = useMantineTheme();
4294
+ const color = theme2.colors[theme2.primaryColor][5];
4295
+ const version = useSettings((s) => s.resourceVersion);
4296
+ const [activeTab, setActiveTab] = useState(navItems[0]?.id ?? "");
4297
+ const [jsonOpen, setJsonOpen] = useState(false);
4298
+ const [historyOpen, setHistoryOpen] = useState(false);
4299
+ const [resetOpen, setResetOpen] = useState(false);
4300
+ const [closeConfirmOpen, setCloseConfirmOpen] = useState(false);
4301
+ const changedCount = form.changedCount ?? 0;
4302
+ const isDirty = changedCount > 0;
4303
+ useEffect(() => {
4304
+ function handleKeyDown(e) {
4305
+ if (e.key !== "Escape") return;
4306
+ if (isDirty) {
4307
+ e.preventDefault();
4308
+ setCloseConfirmOpen(true);
4309
+ return;
4310
+ }
4311
+ onClose();
4312
+ }
4313
+ window.addEventListener("keydown", handleKeyDown);
4314
+ return () => window.removeEventListener("keydown", handleKeyDown);
4315
+ }, [isDirty, onClose]);
4316
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4317
+ /* @__PURE__ */ jsx(AnimatePresence, { children: jsonOpen && /* @__PURE__ */ jsx(SettingsJsonModal, { onClose: () => setJsonOpen(false), schema }) }),
4318
+ /* @__PURE__ */ jsx(AnimatePresence, { children: historyOpen && /* @__PURE__ */ jsx(SettingsHistoryModal, { onClose: () => setHistoryOpen(false) }) }),
4319
+ /* @__PURE__ */ jsx(AnimatePresence, { children: resetOpen && /* @__PURE__ */ jsx(
4320
+ ConfirmModal,
4321
+ {
4322
+ title: "Reset to Defaults",
4323
+ description: "This will permanently reset ALL settings back to their defaults. Every setting you have configured will be overwritten. This cannot be undone.",
4324
+ confirmLabel: "Reset Settings",
4325
+ confirmText: resetConfirmText,
4326
+ onConfirm: () => {
4327
+ updateSettings(defaultSettings).then(() => form.reinitialize(cloneSettings(defaultSettings)));
4328
+ setResetOpen(false);
4329
+ },
4330
+ onClose: () => setResetOpen(false),
4331
+ zIndex: 300
4332
+ }
4333
+ ) }),
4334
+ /* @__PURE__ */ jsx(AnimatePresence, { children: closeConfirmOpen && /* @__PURE__ */ jsx(
4335
+ ConfirmModal,
4336
+ {
4337
+ title: "Discard Unsaved Changes?",
4338
+ description: "You have unsaved changes. Closing now will discard them.",
4339
+ confirmLabel: "Close Without Saving",
4340
+ onConfirm: () => {
4341
+ setCloseConfirmOpen(false);
4342
+ onClose();
4343
+ },
4344
+ onClose: () => setCloseConfirmOpen(false),
4345
+ zIndex: 300
4346
+ }
4347
+ ) }),
4348
+ /* @__PURE__ */ jsxs(
4349
+ MotionFlex,
4350
+ {
4351
+ pos: "absolute",
4352
+ left: "50%",
4353
+ top: "50%",
4354
+ bg: alpha(theme2.colors.dark[9], 0.9),
4355
+ w: width ?? "120vh",
4356
+ h: height ?? "80vh",
4357
+ bdrs: "sm",
4358
+ style: {
4359
+ userSelect: "none",
4360
+ overflow: "hidden",
4361
+ transform: "translate(-50%, -50%)",
4362
+ boxShadow: "0 0 10px rgba(0,0,0,0.5)",
4363
+ border: `0.1vh solid ${theme2.colors.dark[7]}`
4364
+ },
4365
+ direction: "row",
4366
+ initial: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
4367
+ animate: { scale: 1, opacity: 1, transform: "translate(-50%, -50%)" },
4368
+ exit: { scale: 0.3, opacity: 0, transform: "translate(-50%, -50%)" },
4369
+ children: [
4370
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", style: { width: "18vh", flexShrink: 0, borderRight: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.8)}`, background: alpha(theme2.colors.dark[8], 0.6), overflow: "hidden" }, children: [
4371
+ /* @__PURE__ */ jsxs(Flex, { align: "baseline", gap: "0.3vh", px: "sm", py: "sm", style: { borderBottom: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
4372
+ /* @__PURE__ */ jsx(Text, { size: "lg", ff: "Akrobat Bold", tt: "uppercase", children: title }),
4373
+ subtitle && /* @__PURE__ */ jsx(Text, { tt: "uppercase", fw: 600, c: color, children: subtitle })
4374
+ ] }),
4375
+ /* @__PURE__ */ jsxs(Flex, { gap: "xxs", px: "xs", py: "xs", style: { borderBottom: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.4)}`, flexShrink: 0 }, children: [
4376
+ /* @__PURE__ */ jsx(
4377
+ motion.button,
4378
+ {
4379
+ title: "Undo",
4380
+ onClick: () => form.canBack && form.back(),
4381
+ disabled: !form.canBack,
4382
+ whileHover: form.canBack ? { background: "rgba(255,255,255,0.07)" } : void 0,
4383
+ whileTap: form.canBack ? { scale: 0.97 } : void 0,
4384
+ style: { flex: 1, aspectRatio: "1 / 1", background: "transparent", border: `0.1vh solid ${alpha(theme2.colors.dark[5], form.canBack ? 0.6 : 0.3)}`, borderRadius: theme2.radius.xs, cursor: form.canBack ? "pointer" : "default", display: "flex", alignItems: "center", justifyContent: "center", opacity: form.canBack ? 1 : 0.35, transition: "opacity 0.2s" },
4385
+ children: /* @__PURE__ */ jsx(Undo2, { size: "1.5vh", color: "rgba(255,255,255,0.7)" })
4386
+ }
4387
+ ),
4388
+ /* @__PURE__ */ jsx(
4389
+ motion.button,
4390
+ {
4391
+ title: "Redo",
4392
+ onClick: () => form.canForward && form.forward(),
4393
+ disabled: !form.canForward,
4394
+ whileHover: form.canForward ? { background: "rgba(255,255,255,0.07)" } : void 0,
4395
+ whileTap: form.canForward ? { scale: 0.97 } : void 0,
4396
+ style: { flex: 1, aspectRatio: "1 / 1", background: "transparent", border: `0.1vh solid ${alpha(theme2.colors.dark[5], form.canForward ? 0.6 : 0.3)}`, borderRadius: theme2.radius.xs, cursor: form.canForward ? "pointer" : "default", display: "flex", alignItems: "center", justifyContent: "center", opacity: form.canForward ? 1 : 0.35, transition: "opacity 0.2s" },
4397
+ children: /* @__PURE__ */ jsx(Redo2, { size: "1.5vh", color: "rgba(255,255,255,0.7)" })
4398
+ }
4399
+ ),
4400
+ /* @__PURE__ */ jsx(
4401
+ motion.button,
4402
+ {
4403
+ title: isSaving ? "Saving..." : isDirty ? `Save (${changedCount})` : "Save",
4404
+ onClick: () => isDirty && !isSaving && form.submit(),
4405
+ disabled: !isDirty || isSaving,
4406
+ whileHover: isDirty && !isSaving ? { background: alpha(color, 0.25), borderColor: alpha(color, 0.5) } : void 0,
4407
+ whileTap: isDirty && !isSaving ? { scale: 0.97 } : void 0,
4408
+ style: { flex: 1, aspectRatio: "1 / 1", background: isDirty ? alpha(color, 0.14) : "transparent", border: `0.1vh solid ${isDirty ? alpha(color, 0.35) : alpha(theme2.colors.dark[5], 0.3)}`, borderRadius: theme2.radius.xs, cursor: isDirty && !isSaving ? "pointer" : "default", display: "flex", alignItems: "center", justifyContent: "center", opacity: isDirty ? 1 : 0.35, transition: "opacity 0.2s, background 0.15s" },
4409
+ children: isSaving ? /* @__PURE__ */ jsx(Loader, { size: "1.5vh", color, type: "dots" }) : /* @__PURE__ */ jsx(Save, { color: isDirty ? color : "rgba(255,255,255,0.35)", size: "1.5vh" })
4410
+ }
4411
+ ),
4412
+ /* @__PURE__ */ jsx(
4413
+ motion.button,
4414
+ {
4415
+ title: "History",
4416
+ onClick: () => setHistoryOpen(true),
4417
+ whileHover: { background: alpha("#22d3ee", 0.16), borderColor: alpha("#22d3ee", 0.5) },
4418
+ whileTap: { scale: 0.97 },
4419
+ style: { flex: 1, aspectRatio: "1 / 1", background: alpha("#22d3ee", 0.07), border: `0.1vh solid ${alpha("#22d3ee", 0.25)}`, borderRadius: theme2.radius.xs, cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center" },
4420
+ children: /* @__PURE__ */ jsx(History, { color: "#22d3ee", size: "1.5vh" })
4421
+ }
4422
+ )
4423
+ ] }),
4424
+ /* @__PURE__ */ jsx(Flex, { direction: "column", gap: "xxs", p: "xs", style: { flex: 1, overflowY: "auto" }, children: navItems.map((item) => /* @__PURE__ */ jsx(NavItemButton, { icon: item.icon, label: item.label, active: activeTab === item.id, onClick: () => setActiveTab(item.id) }, item.id)) }),
4425
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", p: "xs", gap: "xs", style: { borderTop: `0.1vh solid ${alpha(theme2.colors.dark[6], 0.5)}`, flexShrink: 0 }, children: [
4426
+ /* @__PURE__ */ jsxs(
4427
+ motion.button,
4428
+ {
4429
+ onClick: () => isDirty && form.reset(),
4430
+ disabled: !isDirty,
4431
+ whileHover: isDirty ? { background: alpha("#f97316", 0.12), borderColor: alpha("#f97316", 0.45) } : void 0,
4432
+ whileTap: isDirty ? { scale: 0.97 } : void 0,
4433
+ style: { width: "100%", background: "transparent", border: `0.1vh solid ${isDirty ? alpha("#f97316", 0.35) : alpha(theme2.colors.dark[5], 0.3)}`, borderRadius: theme2.radius.xs, padding: "0.65vh 0.8vh", cursor: isDirty ? "pointer" : "default", display: "flex", alignItems: "center", gap: "0.55vh", opacity: isDirty ? 1 : 0.35, transition: "opacity 0.2s" },
4434
+ children: [
4435
+ /* @__PURE__ */ jsx(XCircle, { color: isDirty ? "#f97316" : "rgba(255,255,255,0.35)", size: "1.6vh" }),
4436
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: isDirty ? "#f97316" : "rgba(255,255,255,0.35)", children: "Discard" })
4437
+ ]
4438
+ }
4439
+ ),
4440
+ /* @__PURE__ */ jsx("div", { style: { height: "0.05vh", background: "rgba(255,255,255,0.07)", margin: "0.1vh 0" } }),
4441
+ /* @__PURE__ */ jsxs(
4442
+ motion.button,
4443
+ {
4444
+ onClick: () => setJsonOpen(true),
4445
+ whileHover: { background: alpha(color, 0.16), borderColor: alpha(color, 0.45) },
4446
+ whileTap: { scale: 0.97 },
4447
+ style: { width: "100%", background: alpha(color, 0.07), border: `0.1vh solid ${alpha(color, 0.28)}`, borderRadius: theme2.radius.xs, padding: "0.65vh 0.8vh", cursor: "pointer", display: "flex", alignItems: "center", gap: "0.55vh" },
4448
+ children: [
4449
+ /* @__PURE__ */ jsx(Code2, { color, size: "1.6vh" }),
4450
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: color, children: "Manual Edit" })
4451
+ ]
4452
+ }
4453
+ ),
4454
+ /* @__PURE__ */ jsxs(
4455
+ motion.button,
4456
+ {
4457
+ onClick: () => setResetOpen(true),
4458
+ whileHover: { background: alpha("#ef4444", 0.16), borderColor: alpha("#ef4444", 0.5) },
4459
+ whileTap: { scale: 0.97 },
4460
+ style: { width: "100%", background: alpha("#ef4444", 0.07), border: `0.1vh solid ${alpha("#ef4444", 0.25)}`, borderRadius: theme2.radius.xs, padding: "0.65vh 0.8vh", cursor: "pointer", display: "flex", alignItems: "center", gap: "0.55vh" },
4461
+ children: [
4462
+ /* @__PURE__ */ jsx(RotateCcw, { color: "#ef4444", size: "1.6vh" }),
4463
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xxs", tt: "uppercase", lts: "0.06em", c: "#ef4444", children: "Reset Defaults" })
4464
+ ]
4465
+ }
4466
+ ),
4467
+ version && /* @__PURE__ */ jsxs(Text, { size: "0.95vh", c: "dimmed", ta: "center", style: { letterSpacing: "0.04em", opacity: 0.8 }, children: [
4468
+ "Version ",
4469
+ version
4470
+ ] })
4471
+ ] })
4472
+ ] }),
4473
+ /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
4474
+ motion.div,
4475
+ {
4476
+ initial: { opacity: 0, y: 4 },
4477
+ animate: { opacity: 1, y: 0 },
4478
+ exit: { opacity: 0, y: -4 },
4479
+ transition: { duration: 0.15 },
4480
+ style: { flex: 1, display: "flex", flexDirection: "column", overflowY: "auto" },
4481
+ children: children(activeTab)
4482
+ },
4483
+ activeTab
4484
+ ) })
4485
+ ]
4486
+ }
4487
+ )
4488
+ ] });
4489
+ }
4490
+ function cloneSettings(value) {
4491
+ return JSON.parse(JSON.stringify(value));
4492
+ }
4493
+ var defaultOnClose = () => fetchNui("CLOSE_ADMIN_SECTION");
4494
+ function SettingsPanel(props) {
4495
+ const { open, onClose = defaultOnClose } = props;
4496
+ const { store, updateSettings } = getScriptSettingsInstance();
4497
+ const [isSaving, setIsSaving] = useState(false);
4498
+ if (!open) return null;
4499
+ return /* @__PURE__ */ jsx(QueryClientProvider, { client: settingsPanelQueryClient, children: /* @__PURE__ */ jsx(
4500
+ FormProvider,
4501
+ {
4502
+ initialValues: cloneSettings(store.getState()),
4503
+ onSubmit: async (form) => {
4504
+ if (isSaving) return;
4505
+ setIsSaving(true);
4506
+ try {
4507
+ const result = await updateSettings(form.values);
4508
+ if (result?.success) {
4509
+ form.reinitialize(cloneSettings(form.values));
4510
+ return;
4511
+ }
4512
+ form.reinitialize(cloneSettings(store.getState()));
4513
+ if (result?._error) {
4514
+ console.warn(`[SettingsPanel] settings save failed: ${result._error}`);
4515
+ }
4516
+ } finally {
4517
+ setIsSaving(false);
4518
+ }
4519
+ },
4520
+ children: /* @__PURE__ */ jsx(AnimatePresence, { children: open && /* @__PURE__ */ jsx(
4521
+ SettingsPanelInner,
4522
+ {
4523
+ ...props,
4524
+ onClose,
4525
+ isSaving
4526
+ }
4527
+ ) })
4528
+ }
4529
+ ) });
4530
+ }
4531
+ function LazyImage({ src, alt, style }) {
4532
+ const [visible, setVisible] = useState(false);
4533
+ const ref = useRef(null);
4534
+ useEffect(() => {
4535
+ const observer = new IntersectionObserver(([entry]) => {
4536
+ if (entry.isIntersecting) {
4537
+ setVisible(true);
4538
+ observer.disconnect();
4539
+ }
4540
+ });
4541
+ if (ref.current) observer.observe(ref.current);
4542
+ return () => observer.disconnect();
4543
+ }, []);
4544
+ return /* @__PURE__ */ jsx("div", { ref, style: { width: "4vh", height: "4vh" }, children: visible && /* @__PURE__ */ jsx(Image$1, { src, alt, fit: "contain", style }) });
4545
+ }
4546
+ function SelectItem(props) {
4547
+ const invItems = useItems();
4548
+ const formattedItems = useMemo(() => {
4549
+ const seen = /* @__PURE__ */ new Set();
4550
+ return useItemsList(props.excludeItemNames ?? []).filter((item) => {
4551
+ if (seen.has(item.name)) return false;
4552
+ seen.add(item.name);
4553
+ return true;
4554
+ }).map((item) => ({ value: item.name, label: item.label, image: item.image }));
4555
+ }, [invItems, props.excludeItemNames]);
4556
+ return /* @__PURE__ */ jsx(
4557
+ Select,
4558
+ {
4559
+ maxDropdownHeight: "30vh",
4560
+ label: locale(props.label),
4561
+ size: "xs",
4562
+ flex: 1,
4563
+ style: props.style,
4564
+ limit: 50,
4565
+ value: props.value,
4566
+ onChange: (v) => props.onChange(v),
4567
+ data: formattedItems,
4568
+ allowDeselect: false,
4569
+ searchable: true,
4570
+ leftSectionWidth: "4vh",
4571
+ leftSection: props.value ? /* @__PURE__ */ jsx(
4572
+ Image$1,
4573
+ {
4574
+ fallbackSrc: "/placeholder.png",
4575
+ src: invItems[props.value]?.image || "",
4576
+ alt: props.value,
4577
+ fit: "contain",
4578
+ maw: "4vh",
4579
+ style: { aspectRatio: "1 / 1" }
4580
+ }
4581
+ ) : null,
4582
+ nothingFoundMessage: locale("NoItemsFound"),
4583
+ renderOption: (item) => /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xs", w: "100%", children: [
4584
+ /* @__PURE__ */ jsx(
4585
+ LazyImage,
4586
+ {
4587
+ src: invItems[item.option.value]?.image || "",
4588
+ alt: item.option.label,
4589
+ style: { aspectRatio: "1 / 1" }
4590
+ }
4591
+ ),
4592
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", children: [
4593
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: item.option.label }),
4594
+ /* @__PURE__ */ jsx(Text, { size: "xxs", c: "dimmed", children: item.option.value })
4595
+ ] })
4596
+ ] })
4597
+ }
4598
+ );
4599
+ }
4600
+ var KeyBindContext = createContext(null);
4601
+ function useKeyBindContext() {
4602
+ const ctx = useContext(KeyBindContext);
4603
+ if (!ctx) {
4604
+ throw new Error("FiveMKeyBindInput.* must be used inside <FiveMKeyBindInput>");
4605
+ }
4606
+ return ctx;
4607
+ }
4608
+ function Root({ value, onChange, children }) {
4609
+ return /* @__PURE__ */ jsx(KeyBindContext.Provider, { value: { value, onChange }, children: /* @__PURE__ */ jsx(Flex, { gap: "xs", style: { flex: 1 }, children }) });
4610
+ }
4611
+ function Category({ label: label2 = "Primary" }) {
4612
+ const { value, onChange } = useKeyBindContext();
4613
+ return /* @__PURE__ */ jsx(
4614
+ Select,
4615
+ {
4616
+ label: label2,
4617
+ size: "xs",
4618
+ style: { flex: 1 },
4619
+ value: value._type,
4620
+ data: [...INPUT_MAPPER_PRIMARY_OPTIONS],
4621
+ onChange: (nextType) => {
4622
+ if (!nextType) return;
4623
+ const keyOptions = INPUT_MAPPER_KEYS_BY_PRIMARY[nextType] ?? [];
4624
+ const hasCurrentKey = keyOptions.includes(value._key);
4625
+ const nextKey = hasCurrentKey ? value._key : keyOptions[0] ?? value._key;
4626
+ onChange({
4627
+ ...value,
4628
+ _type: nextType,
4629
+ _key: nextKey
4630
+ });
4631
+ },
4632
+ searchable: true,
4633
+ allowDeselect: false
4634
+ }
4635
+ );
4636
+ }
4637
+ function Key({ label: label2 = "Key" }) {
4638
+ const { value, onChange } = useKeyBindContext();
4639
+ const keyOptions = INPUT_MAPPER_KEYS_BY_PRIMARY[value._type] ?? [];
4640
+ if (keyOptions.length === 0) {
4641
+ return /* @__PURE__ */ jsx(
4642
+ TextInput,
4643
+ {
4644
+ label: label2,
4645
+ size: "xs",
4646
+ style: { flex: 1 },
4647
+ value: value._key,
4648
+ onChange: (e) => onChange({ ...value, _key: e.currentTarget.value }),
4649
+ placeholder: "Type key value"
4650
+ }
4651
+ );
4652
+ }
4653
+ return /* @__PURE__ */ jsx(
4654
+ Select,
4655
+ {
4656
+ label: label2,
4657
+ size: "xs",
4658
+ style: { flex: 1 },
4659
+ value: value._key,
4660
+ data: keyOptions,
4661
+ onChange: (nextKey) => {
4662
+ if (!nextKey) return;
4663
+ onChange({ ...value, _key: nextKey });
4664
+ },
4665
+ searchable: true,
4666
+ allowDeselect: false
4667
+ }
4668
+ );
4669
+ }
4670
+ var FiveMKeyBindInput = Object.assign(Root, {
4671
+ Category,
4672
+ Key
4673
+ });
4674
+ function AsyncSaveButton({
4675
+ onSave,
4676
+ color,
4677
+ label: label2 = "Save Changes",
4678
+ style
4679
+ }) {
4680
+ const theme2 = useMantineTheme();
4681
+ const [state, setState] = useState("idle");
4682
+ const handleClick = async () => {
4683
+ if (state === "pending") return;
4684
+ setState("pending");
4685
+ try {
4686
+ const result = await onSave();
4687
+ setState(result?.success === false ? "error" : "success");
4688
+ } catch {
4689
+ setState("error");
4690
+ }
4691
+ setTimeout(() => setState("idle"), 2e3);
4692
+ };
4693
+ const c = state === "error" ? "#ef4444" : color;
4694
+ return /* @__PURE__ */ jsxs(
4695
+ motion.button,
4696
+ {
4697
+ onClick: handleClick,
4698
+ disabled: state === "pending",
4699
+ whileHover: state === "pending" ? {} : { background: alpha(c, 0.25) },
4700
+ whileTap: state === "pending" ? {} : { scale: 0.98 },
4701
+ style: {
4702
+ background: alpha(c, 0.14),
4703
+ border: `0.1vh solid ${alpha(c, 0.4)}`,
4704
+ borderRadius: theme2.radius.xs,
4705
+ padding: `${theme2.spacing.xxs} ${theme2.spacing.xs}`,
4706
+ cursor: state === "pending" ? "default" : "pointer",
4707
+ display: "flex",
4708
+ alignItems: "center",
4709
+ justifyContent: "center",
4710
+ gap: theme2.spacing.xxs,
4711
+ transition: "background 0.2s, border-color 0.2s",
4712
+ alignSelf: "flex-end",
4713
+ ...style
4714
+ },
4715
+ children: [
4716
+ state === "pending" ? /* @__PURE__ */ jsx(Loader, { size: "1.4vh", color: c, type: "oval" }) : state === "error" ? /* @__PURE__ */ jsx(X, { size: "1.4vh", color: c }) : /* @__PURE__ */ jsx(Check, { size: "1.4vh", color: c }),
4717
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", size: "xs", tt: "uppercase", lts: "0.06em", c, children: state === "success" ? "Saved!" : state === "error" ? "Failed!" : label2 })
4718
+ ]
4719
+ }
4720
+ );
4721
+ }
4722
+ function AdminPageTitle(props) {
4723
+ return /* @__PURE__ */ jsxs(Flex, { align: "center", gap: "xs", children: [
4724
+ /* @__PURE__ */ jsx(props.icon, { color: props.color }),
4725
+ /* @__PURE__ */ jsx(Text, { ff: "Akrobat Bold", tt: "uppercase", lts: "0.1em", size: "sm", c: "rgba(255,255,255,0.6)", children: locale(props.title) })
4726
+ ] });
4727
+ }
4728
+ var useNuiEvent = (action, handler) => {
4729
+ const savedHandler = useRef(noop);
4730
+ useEffect(() => {
4731
+ savedHandler.current = handler;
4732
+ }, [handler]);
4733
+ useEffect(() => {
4734
+ const eventListener = (event) => {
4735
+ const { action: eventAction, data } = event.data;
4736
+ if (savedHandler.current) {
4737
+ if (eventAction === action) {
4738
+ savedHandler.current(data);
4739
+ }
4740
+ }
4741
+ };
4742
+ window.addEventListener("message", eventListener);
4743
+ return () => window.removeEventListener("message", eventListener);
4744
+ }, [action]);
4745
+ };
2271
4746
  function useTornEdges() {
2272
4747
  const game = useSettings((state) => state.game);
2273
4748
  return game === "rdr3" ? "torn-edge-wrapper" : "";
@@ -2319,23 +4794,6 @@ function TornEdgeSVGFilter() {
2319
4794
  }
2320
4795
  );
2321
4796
  }
2322
- function createScriptSettings(defaultValue) {
2323
- const store = create(() => defaultValue);
2324
- if (typeof window !== "undefined") {
2325
- window.addEventListener("message", (event) => {
2326
- if (event.data?.action === "UPDATE_SCRIPT_SETTINGS" && event.data?.data) {
2327
- store.setState((prev) => ({ ...prev, ...event.data.data }));
2328
- }
2329
- });
2330
- }
2331
- const useScriptSettingHooks = () => {
2332
- };
2333
- const updateScriptSettings = async (newSettings) => {
2334
- store.setState((prev) => ({ ...prev, ...newSettings }));
2335
- return await fetchNui("UPDATE_SCRIPT_SETTINGS", newSettings);
2336
- };
2337
- return { store, updateScriptSettings, useScriptSettingHooks };
2338
- }
2339
4797
  var label = {
2340
4798
  fontSize: "var(--mantine-font-size-xs)",
2341
4799
  fontFamily: "Akrobat Bold",
@@ -2355,7 +4813,9 @@ var genericInputStyles = {
2355
4813
  error,
2356
4814
  description,
2357
4815
  input: {
2358
- backgroundColor: "rgba(76, 76, 76, 0.3)",
4816
+ background: "rgba(255,255,255,0.04)",
4817
+ border: "0.1vh solid rgba(255,255,255,0.08)",
4818
+ color: "rgba(255,255,255,0.85)",
2359
4819
  minHeight: "4vh"
2360
4820
  }
2361
4821
  }
@@ -2473,7 +4933,7 @@ function mergeMantineThemeSafe(base, custom, override) {
2473
4933
  }
2474
4934
  };
2475
4935
  }
2476
- var DirkErrorBoundary = class extends React3.Component {
4936
+ var DirkErrorBoundary = class extends React4.Component {
2477
4937
  constructor() {
2478
4938
  super(...arguments);
2479
4939
  __publicField(this, "state", { error: null, stack: void 0 });
@@ -2544,9 +5004,13 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
2544
5004
  useEffect(() => {
2545
5005
  fetchNui("NUI_READY").catch(() => {
2546
5006
  });
2547
- fetchNui("GET_SETTINGS").then((data) => {
5007
+ Promise.all([
5008
+ fetchNui("GET_SETTINGS"),
5009
+ fetchNui("GET_RESOURCE_VERSION", void 0, { version: "dev" })
5010
+ ]).then(([data, resourceInfo]) => {
2548
5011
  useSettings.setState({
2549
- ...data
5012
+ ...data,
5013
+ resourceVersion: resourceInfo?.version || "dev"
2550
5014
  });
2551
5015
  }).catch((err) => {
2552
5016
  console.error("Failed to fetch initial settings within dirk-cfx-react:", err);
@@ -2575,6 +5039,6 @@ function DirkProvider({ children, overideResourceName, themeOverride }) {
2575
5039
  return /* @__PURE__ */ jsx(MantineProvider, { theme: mergedTheme, defaultColorScheme: "dark", children: /* @__PURE__ */ jsx(DirkErrorBoundary, { children: content }) });
2576
5040
  }
2577
5041
 
2578
- export { BorderedIcon, Counter, DirkProvider, FloatingParticles, FormProvider, InfoBox, InputContainer, LevelBanner, LevelPanel, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PromptModal, SegmentedControl, SegmentedProgress, Title, TornEdgeSVGFilter, colorWithAlpha, copyToClipboard, createFormStore, createScriptSettings, createSkill, fetchLuaTable, fetchNui, gameToMap, getImageShape, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, splitFAString, updatePresignedURL, uploadImage, useAutoFetcher, useForm, useFormActions, useFormError, useFormErrors, useFormField, useFormFields, useModal, useModalActions, useNavigation, useNavigationStore, useNuiEvent, useProfanityStore, useSettings, useTornEdges };
5042
+ export { AdminPageTitle, AsyncSaveButton, BlipColorSelect, BlipIconSelect, BorderedIcon, ConfirmModal, Counter, DirkProvider, FiveMKeyBindInput, FloatingParticles, FormProvider, INPUT_MAPPER_KEYS_BY_PRIMARY, INPUT_MAPPER_PRIMARY_OPTIONS, InfoBox, InputContainer, LevelBanner, LevelPanel, Modal, ModalContext, ModalProvider, MotionFlex, MotionIcon, MotionImage, MotionText, NavBar, NavigationContext, NavigationProvider, PromptModal, SegmentedControl, SegmentedProgress, SelectItem, SettingsPanel, Title, TornEdgeSVGFilter, colorWithAlpha, copyToClipboard, createFormStore, createScriptSettings, createSkill, extractDefaults, fetchLuaTable, fetchNui, gameToMap, getImageShape, getItemImageUrl, getScriptSettingsInstance, initialFetches, internalEvent, isEnvBrowser, isProfanity, latPr100, locale, localeStore, mapCenter, mapToGame, noop, numberToRoman, openLink, registerInitialFetch, registerInitialLuaTableFetch, runFetches, splitFAString, updatePresignedURL, uploadImage, useAudio, useAutoFetcher, useForm, useFormActions, useFormError, useFormErrors, useFormField, useFormFields, useItems, useItemsList, useModal, useModalActions, useNavigation, useNavigationStore, useNuiEvent, useProfanityStore, useSettings, useTornEdges };
2579
5043
  //# sourceMappingURL=index.js.map
2580
5044
  //# sourceMappingURL=index.js.map