local Color = require('../../Color')
local chroma = require('../../chroma')
local input = require('../input')

type Color = Color.Color
type PrivateColor = Color.PrivateColor

input.format.roblox = function(color: Color3, opacity: number?)
    return { color.R * 255, color.G * 255, color.B * 255, if opacity then opacity else 1 }
end

function chroma.roblox(...: any): Color
    local args = table.pack(...)
    args[args.n + 1] = 'roblox'
    return Color.new(unpack(args, 1, args.n + 1))
end

function Color:roblox(): Color3
    local self: PrivateColor = self :: any
    local rgb = self._rgb
    return Color3.fromRGB(rgb[1], rgb[2], rgb[3])
end

table.insert(input.autodetect, {
    p = 56,
    test = function(...: any): string?
        local args = table.pack(...)
        if args.n == 1 and type(args[1]) == 'userdata' and typeof(args[1]) == 'Color3' then
            return 'roblox'
        end
        return nil
    end,
})

return nil


local ColorTypes = require('./color-types')

type Color = ColorTypes.Color
type AsColor = ColorTypes.AsColor

export type BlendMode =
    'normal'
    | 'multiply'
    | 'screen'
    | 'overlay'
    | 'darken'
    | 'lighten'
    | 'dodge'
    | 'burn'

type BlendFn = ({ number }, { number }) -> { number }

export type Blend = ((AsColor, AsColor, mode: BlendMode) -> Color) & {
    normal: BlendFn,
    multiply: BlendFn,
    screen: BlendFn,
    overlay: BlendFn,
    darken: BlendFn,
    lighten: BlendFn,
    dodge: BlendFn,
    burn: BlendFn,
}

return nil


export type ColorBrewerName =
    'OrRd'
    | 'PuBu'
    | 'BuPu'
    | 'Oranges'
    | 'BuGn'
    | 'YlOrBr'
    | 'YlGn'
    | 'Reds'
    | 'RdPu'
    | 'Greens'
    | 'YlGnBu'
    | 'Purples'
    | 'GnBu'
    | 'Greys'
    | 'YlOrRd'
    | 'PuRd'
    | 'Blues'
    | 'PuBuGn'
    | 'Viridis'
    | 'Spectral'
    | 'RdYlGn'
    | 'RdBu'
    | 'PiYG'
    | 'PRGn'
    | 'RdYlBu'
    | 'BrBG'
    | 'RdGy'
    | 'PuOr'
    | 'Set2'
    | 'Accent'
    | 'Set1'
    | 'Set3'
    | 'Dark2'
    | 'Paired'
    | 'Pastel2'
    | 'Pastel1'

return nil


local InterpolationMode = require('./interpolation-mode')

export type InterpolationMode = InterpolationMode.InterpolationMode

export type ColorSpace =
    'cmyk'
    | 'css'
    | 'gl'
    | 'hcg'
    | 'hex'
    | 'hsi'
    | 'hsl'
    | 'hsv'
    | 'lab'
    | 'lch'
    | 'hcl'
    | 'name'
    | 'num'
    | 'oklab'
    | 'oklch'
    | 'rgb'
    | 'rgba'
    | 'temperature'
    | 'kelvin'
    | 'temp'

export type Color = {
    toString: (self: Color) -> string,
    -- cmyk
    cmyk: (self: Color) -> { number },
    -- css
    css: (self: Color, mode: string?) -> string,
    -- gl
    gl: (self: Color) -> { number },
    -- hcg
    hcg: (self: Color) -> { number },
    -- hex
    hex: (self: Color, mode: string?) -> string,
    -- hsi
    hsi: (self: Color) -> { number },
    -- hsl
    hsl: (self: Color) -> { number },
    -- hsv
    hsv: (self: Color) -> { number },
    -- lab
    lab: (self: Color) -> { number },
    -- lch
    lch: (self: Color) -> { number },
    hcl: (self: Color) -> { number },
    -- named
    name: (self: Color) -> string,
    -- num
    num: (self: Color) -> number,
    -- oklab
    oklab: (self: Color) -> { number },
    -- oklch
    oklch: (self: Color) -> { number },
    -- rgb
    rgb: (self: Color, round: boolean?) -> { number },
    rgba: (self: Color, round: boolean?) -> { number },
    -- temp
    temperature: (Color) -> number,
    kelvin: (Color) -> number,
    temp: (Color) -> number,
    -- roblox
    roblox: (Color) -> Color3,

    -- OPS
    -- alpha
    alpha: ((self: Color) -> number) & ((self: Color, a: number, mutate: boolean?) -> Color),
    -- clipped
    clipped: (self: Color) -> boolean,
    -- darken
    darken: (self: Color, amount: number?) -> Color,
    darker: (self: Color, amount: number?) -> Color,
    brighten: (self: Color, amount: number?) -> Color,
    brighter: (self: Color, amount: number?) -> Color,
    -- get
    get: (self: Color, mc: string) -> number | { number },
    -- luminance
    luminance: ((self: Color) -> number)
        & (self: Color, lum: number, mode: InterpolationMode?) -> Color,
    -- mix
    interpolate: (self: Color, color2: AsColor, amount: number?, mode: InterpolationMode?) -> Color,
    mix: (self: Color, color2: AsColor, amount: number?, mode: InterpolationMode?) -> Color,
    -- premultiply
    premultiply: (self: Color, mutate: boolean?) -> Color,
    -- saturate
    saturate: (self: Color, amount: number?) -> Color,
    desaturate: (self: Color, amount: number?) -> Color,
    -- set
    set: (self: Color, mc: any, value: any, mutate: boolean?) -> Color,
}

export type PrivateColor = Color & {
    _rgb: { [number]: number, _clipped: boolean? },
}

export type AsColor = Color | string | number | { number }

return nil


local ColorTypes = require('./color-types')

type Color = ColorTypes.Color

export type Cubehelix = ((number) -> Color) & {
    start: (() -> number) & ((number) -> Cubehelix),
    rotations: (() -> number) & ((number) -> Cubehelix),
    gamma: (() -> number) & ((number) -> Cubehelix),
    hue: (() -> number | { number }) & ((number | { number }) -> Cubehelix),
    lightness: (() -> { number }) & ((number | { number }) -> Cubehelix),
}

return nil


export type InterpolationMode =
    'hcg'
    | 'hsi'
    | 'hsl'
    | 'hsv'
    | 'lab'
    | 'lch'
    | 'hcl'
    | 'lrgb'
    | 'num'
    | 'oklab'
    | 'oklch'
    | 'rgb'

return nil


local ColorTypes = require('./color-types')

local InterpolationMode = require('./interpolation-mode')

type Color = ColorTypes.Color
type AsColor = ColorTypes.AsColor
export type InterpolationMode = InterpolationMode.InterpolationMode

type ScaleFn<T> = (number?) -> T

export type ScaleBase<T, E> = ScaleFn<T> & E & {
    classes: (() -> { number }) & ((number | { number }) -> ScaleBase<T, E>),
    domain: (() -> { number }) & (({ number }) -> ScaleBase<T, E>),
    mode: (() -> InterpolationMode) & ((InterpolationMode) -> ScaleBase<T, E>),
    range: ({ AsColor }) -> ScaleBase<T, E>,
    spread: (() -> number) & ((number) -> ScaleBase<T, E>),
    correctLightness: (boolean?) -> ScaleBase<T, E>,
    padding: (() -> { number }) & ((number | { number }) -> ScaleBase<T, E>),
    colors: (() -> { AsColor })
        & ((number) -> { string })
        & ((number, 'num' | 'temperature' | 'kelvin' | 'temp') -> { number })
        & ((number, 'css' | 'hex' | 'name' | nil) -> { string })
        & ((
            number,
            'cmyk'
                | 'gl'
                | 'hcg'
                | 'hsi'
                | 'hsl'
                | 'hsv'
                | 'lab'
                | 'lch'
                | 'hcl'
                | 'oklab'
                | 'oklch'
                | 'rgb'
                | 'rgba'
        ) -> { { number } }),
    cache: (() -> boolean) & ((boolean) -> ScaleBase<T, E>),
    gamma: (() -> number) & ((number) -> ScaleBase<T, E>),
    nodata: (() -> Color) & ((AsColor) -> ScaleBase<T, E>),
}

type ScaleExtension = {
    out: (('num' | 'temperature' | 'kelvin' | 'temp') -> ScaleBase<number, ScaleExtension>)
        & (('css' | 'hex' | 'name') -> ScaleBase<string, ScaleExtension>)
        & ((
            'cmyk'
                | 'gl'
                | 'hcg'
                | 'hsi'
                | 'hsl'
                | 'hsv'
                | 'lab'
                | 'lch'
                | 'hcl'
                | 'oklab'
                | 'oklch'
                | 'rgb'
                | 'rgba'
        ) -> ScaleBase<{ number }, ScaleExtension>),
}

export type Scale = ScaleBase<Color, ScaleExtension>

return nil


-- deviation: a utility to round numbers without introducing -0 floats

local function round(value: number): number
    local rounded = math.round(value)

    return if rounded == 0 then 0 else rounded
end

return round


--!strict
--[[
    DayNightCycle
    @author DistractedGames
    @version 2.0.1

    Manages the in-game day/night cycle, driven by a configurable real-world
    duration. It provides a robust event system to trigger actions at specific
    times of day (e.g., "Dawn", "Sunset").

    This module is designed to be managed by the ModuleLoader framework,
    utilizing the Start() lifecycle method, though can be adjusted to fit the
    project's structure.
--]]

local Lighting = game:GetService("Lighting")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

-- Assumes use of Logger module
local Logger = require(ReplicatedStorage.Source.Utility.Logger.Logger)

local logger = Logger.new({
	Debug = false, -- Toggles verbose logging for this module.
	Prefix = "DayNightCycle",
})

local DayNightCycle = {}

--[[
	Type definition for the module's configuration.
	- DayLengthInMinutes: Real-world minutes for a full 24-hour game day.
	- StartTimeOfDay: Optional specific start time in hours (0-24). If nil, uses current lighting.
	- TimeEvents: A dictionary mapping event names to game hours (0-24).
]]
export type DayNightCycleConfig = {
	DayLengthInMinutes: number,
	StartTimeOfDay: number?,
	TimeEvents: { [string]: number },
}

-- Default configuration, can be customized before Start() is called.
local config: DayNightCycleConfig = {
	DayLengthInMinutes = 180, -- A 3 hour day/night cycle.
	StartTimeOfDay = nil, -- Uses existing Lighting time by default.
	TimeEvents = {
		Dawn = 6.0, -- 6:00 AM
		Sunrise = 7.0, -- 7:00 AM
		Midday = 12.0, -- 12:00 PM
		Sunset = 18.0, -- 6:00 PM
		Dusk = 19.0, -- 7:00 PM
		Midnight = 0.0, -- 12:00 AM
	},
}

local connection: RBXScriptConnection?
local isRunning = false
local lastHourTriggered = -1
local triggeredEvents: { [string]: boolean } = {}
local timeRatio = 0
local cycleStartTime = 0

-- Constants
local MINUTES_IN_DAY = 1440 -- 24 hours * 60 minutes
local HOURS_IN_DAY = 24

-- Events
local remotesFolder = ReplicatedStorage:FindFirstChild("Remotes") or Instance.new("Folder")
if not remotesFolder.Parent then
	remotesFolder.Name = "Remotes"
	remotesFolder.Parent = ReplicatedStorage
end

DayNightCycle.Events = Instance.new("BindableEvent")
DayNightCycle.Events.Name = "DayNightEvents"
DayNightCycle.Events.Parent = remotesFolder

--[[
	Converts minutes after midnight to a 24-hour format.
	@param minutes The number of minutes past midnight.
	@return The time in hours (0-24).
]]
local function minutesToHours(minutes: number): number
	return minutes / 60
end

--[[
	Checks and fires time-based events based on the current hour.
	Resets triggered events daily at midnight.
	@param currentHour The current in-game hour.
]]
local function checkTimeEvents(currentHour: number)
	if currentHour < lastHourTriggered then
		-- Midnight has passed, reset all triggered events for the new day.
		triggeredEvents = {}
		logger.log("A new day has begun. Resetting daily time events.")
	end
	lastHourTriggered = currentHour

	for eventName, eventHour in config.TimeEvents do
		local hourDifference = math.abs(currentHour - eventHour)

		-- Handle midnight (0.0) being approached from hour 23.
		if eventHour == 0 and currentHour > 23 then
			hourDifference = HOURS_IN_DAY - currentHour
		end

		-- Trigger if we are close to the event time and it hasn't fired yet today.
		if hourDifference < 0.1 and not triggeredEvents[eventName] then
			triggeredEvents[eventName] = true
			DayNightCycle.Events:Fire(eventName, eventHour)
			logger.log(`Time event triggered: '{eventName}' at {string.format("%.1f", eventHour)}h.`)
		end
	end
end

--[[
	Core update function connected to Heartbeat. Calculates and sets the
	new time of day.
]]
local function onHeartbeat()
	local elapsed = time() - cycleStartTime
	local totalMinutes = (elapsed * timeRatio) % MINUTES_IN_DAY

	Lighting:SetMinutesAfterMidnight(totalMinutes)

	local currentHour = minutesToHours(totalMinutes)
	checkTimeEvents(currentHour)
end

--[[
	[Public Method]
	Starts the day/night cycle. Connects the update function to RunService.Heartbeat.
	Calling it again will have no effect.
]]
function DayNightCycle.StartCycle()
	if isRunning then
		logger.log("StartCycle called but the cycle is already running.", true)
		return
	end
	isRunning = true

	-- Initialize time calculations
	local dayInSeconds = config.DayLengthInMinutes * 60
	timeRatio = MINUTES_IN_DAY / dayInSeconds
	cycleStartTime = time()

	-- Determine where the cycle should start (in minutes)
    local startMinutes =  Lighting:GetMinutesAfterMidnight()
	if config.StartTimeOfDay then
        -- Use the configured start time instead.
		startMinutes = config.StartTimeOfDay * 60
	end

    -- Apply the time to lighting (ensures sync) and offset the internal timer.
    Lighting:SetMinutesAfterMidnight(startMinutes)
    cycleStartTime -= (startMinutes / timeRatio)

	-- Connect to the game loop with a throttled update
	connection = RunService.Heartbeat:Connect(onHeartbeat)

	logger.log(`Day/Night cycle started. Game day lasts {config.DayLengthInMinutes} real-world minutes.`)
end

--[[
	[Public Method]
	Stops the day/night cycle.
]]
function DayNightCycle.StopCycle()
	if not isRunning then
		return
	end
	isRunning = false

	if connection then
		connection:Disconnect()
		connection = nil
	end

	logger.log("Day/Night cycle stopped.")
end

--[[
    [Public Method]
    Adds or updated a custom time event.
    @param eventName The unique name for the event.
    @param eventHour The hour (0-24) to trigger the event.
]]
function DayNightCycle.AddTimeEvent(eventName: string, eventHour: number)
	assert(typeof(eventName) == "string", "eventName must be a string")
	assert(
		typeof(eventHour) == "number" and eventHour >= 0 and eventHour < 24,
		"eventHour must be a number between 0 and 23.99"
	)

    config.TimeEvents[eventName] = eventHour
    logger.log(`Added time event: {eventName} at {string.format("%.1f", eventHour)}h.`)
end

--[[
	[Public Method]
	Removes a time event.
	@param eventName The name of the event to remove.
	@return True if the event was found and removed, false otherwise.
--]]
function DayNightCycle.RemoveTimeEvent(eventName: string): boolean
	if config.TimeEvents[eventName] then
		config.TimeEvents[eventName] = nil
		logger.log(`Removed time event: '{eventName}'.`)
		return true
	end
	logger.log(`Attempted to remove non-existent event: '{eventName}'.`, true)
	return false
end

--[[
    [Public Method]
    Returns the current in-game time.
    @return The current time in hours (0-24).
]]
function DayNightCycle.GetCurrentTime(): number
    return minutesToHours(Lighting:GetMinutesAfterMidnight())
end

--[[
    ModuleLoader Lifecycle: Start
    Starts the actual day/night cycle. This runs after all modules have been
    through their Setup phase.
    If not using the ModuleLoader, be sure to call DayNightCycle.StartCycle from
    somewhere else.
]]
function DayNightCycle.Start()
    logger.log(`Starting Day/Night Cycle...`)
    DayNightCycle.StartCycle()
end

return table.freeze(DayNightCycle)


local ReplicatedStorage = game:GetService("ReplicatedStorage")

local ModuleLoader = require(ReplicatedStorage.Source:WaitForChild("ModuleLoader"))

ModuleLoader()


--!strict
--[[
    ModuleLoader
    @author DistractedGames
    @version 2.0.0

    This module implements a two-pass loading system for ModuleScripts. It's
    designed to run on both the server and the client to create a unified module
    framework.

    The loader operates in two distinct phases or "lifecycles":
    1.  Setup: The loader first requires all modules and calls the `Setup()`
        method on any module that has one. This phase is intended for initialization
        tasks that do not depend on other modules being active, such as setting
        up configuration or registering objects.

    2.  Start: After all modules have been through the Setup phase, the loader
        iterates through them a second time, calling the `Start()` method. This
        phase is for logic that may depend on other modules having completed their
        own setup, such as connecting to events or activating core functionality.

    This approach helps manage dependencies implicitly without needing a complex
    dependency graph.
--]]

local RunService = game:GetService("RunService")
local ServerScriptService = game:GetService("ServerScriptService")
local StarterPlayerScripts = game:GetService("StarterPlayer").StarterPlayerScripts

-- Determine the environment and root directory for modules.
local isServer = RunService:IsServer()
-- On the client, modules are expected to be in a "Source" folder within
-- StarterPlayerScripts to avoid issues with built-in Roblox player modules.
local rootDirectory = if isServer then ServerScriptService else StarterPlayerScripts
local moduleDirectory = if isServer
	then rootDirectory :: ServerScriptService
	else (rootDirectory :: StarterPlayerScripts):WaitForChild("Source") :: Folder

-- Configuration for the loader's behavior.
local config = {
	ATTEMPT_LIMIT = 3, -- How many times to try running a lifecycle method before failing.
	RETRY_DELAY = 1, -- Seconds to wait between failed attempts.
	Debug = false, -- When true, prints detailed logs for each step.
}

--[[
    Logs a formatted message to the output.
    Uses `warn` for warnings and `print` for debug messages.
    The log includes the calling function's name and line for easier debugging.
    @param message The core message to log.
    @param isWarning If true, formats the message as a warning.
]]
local function log(message: string, isWarning: boolean?)
	local prefix = "[ModuleLoader] "
	local source, line, funcName = debug.info(2, "sln")
	local formattedSource = `{string.match(source, "@(.*)")}`
	local logHeader = `{prefix} [{funcName or formattedSource}:{line}]`

	if isWarning then
		warn(`{logHeader} {message}`)
	elseif config.Debug then
		print(`{logHeader} {message}`)
	end
end

--[[
	Executes a module's lifecycle method (e.g., Setup or Start) within a protected call.
	It will retry the function according to the settings in the `config` table.
	@param methodName The name of the lifecycle method being called (for logging).
	@param methodFunc The actual function to execute.
	@param moduleName The name of the module (for logging).
	@return boolean: Whether the execution was ultimately successful.
	@return any: The result or error from the function execution.
]]
local function processLifeCycleMethod(methodName: string, methodFunc: () -> any?, moduleName: string): (boolean, any?)
	assert(
		type(methodFunc) == "function",
		`Lifecycle method '{methodName}' on module '{moduleName}' is not a function, got {typeof(methodFunc)}.`
	)

	local success, result
	for attempt = 1, config.ATTEMPT_LIMIT do
		success, result = pcall(methodFunc)
		if success then
			return true, result -- Successful execution, exit the loop.
		end

		-- Log the failure for this attempt.
		local err = tostring(result)
		log(
			`Module '{moduleName}' failed on lifecycle '{methodName}' (Attempt {attempt}/{config.ATTEMPT_LIMIT}):\n{err}`,
			true
		)

		-- Wait before retyring, but not after the final attempt.
		if attempt < config.ATTEMPT_LIMIT then
			task.wait(config.RETRY_DELAY)
		end
	end

	-- All attemps failed.
	return false, result
end

--[[
	Performs a single pass over all modules, executing a specific lifecycle method.
	@param methodName The name of the method to find and execute (e.g., "Setup", "Start").
]]
local function runLifecyclePass(methodName: string)
	log(`Starting '{methodName}' lifecycle pass...`)

	for _, moduleScript in moduleDirectory:GetDescendants() do
		if not moduleScript:IsA("ModuleScript") then
			continue
		end

		-- Safely require the module. The result is cached by Luau, so subsequent
		-- require calls in the next pass will be fast.
		local success, module = pcall(require, moduleScript)
		if not success then
			log(`Failed to require module '{moduleScript.Name}': {tostring(module)}`, true)
			continue
		end

		-- A module might not return a table or have the target method.
		-- This is valid, so we skip it.
		if type(module) ~= "table" or not module[methodName] then
			continue
		end

		log(`Running '{methodName}' for module: {moduleScript.Name}`)
		local methodFunc = module[methodName]

		-- Process the module's lifecycle method with retry logic.
		local wasSuccessful, result = processLifeCycleMethod(methodName, methodFunc, moduleScript.Name)

		if not wasSuccessful then
			log(
				`Module '{moduleScript.Name}' failed all attempts for lifecycle '{methodName}'. Final error:\n{tostring(
					result
				)}`,
				true
			)
            -- Depending on project needs, we might need to halt everything if a critical module fails.
            -- For now, we just log the final failure and continue.
        else
            log(`Module '{moduleScript.Name}' completed lifecycle '{methodName}' successfully.`)
		end

        -- Yield to prevent script exhaustion errors on projects with many modules.
        task.wait()
	end
    log(`Finished '{methodName}' lifecycle pass.`)
end

--[[
	The main entry point for the module loader.
	Executes the Setup and Start lifecycle passes in sequence.
--]]
return function()
    -- 'Setup' is for initial configuration and dependency-free preparations.
    runLifecyclePass("Setup")
	-- 'Start' is for activating functionality, which may depend on other modules being set up.
    runLifecyclePass("Start")

    log("All modules have been loaded and started.")
end


local ReplicatedStorage = game:GetService("ReplicatedStorage")

local ModuleLoader = require(ReplicatedStorage.Source.ModuleLoader)

ModuleLoader()


--[[
	Specifies the names of the RemoteEvent and RemoteFunction folders used by
    `createRemotesFolders` and `waitForAllRemotesAsync`.
]]

export type EnumType = "RemoteEvents" | "RemoteFunctions"

local RemoteFolderName = {
	RemoteEvents = "RemoteEvents" :: "RemoteEvents",
	RemoteFunctions = "RemoteFunctions" :: "RemoteFunctions",
}

return RemoteFolderName


--[[
	Specifies the names of all RemoteEvents. One RemoteEvent object gets
    generated for each name	in this list, and these names are used as enums when
    interacting with the Network module to tell it which remote event to fire
    without typing out typo-prone string literals.
]]

export type EnumType = "ExampleRemote1"
    | "ExampleRemote2"

local RemoteEventName = {
    ExampleRemote1 = "ExampleRemote1" :: "ExampleRemote1",
    ExampleRemote2 = "ExampleRemote2" :: "ExampleRemote2",
}

return RemoteEventName


--!strict

local network = script.Parent.Parent
local RemoteEventName = require(network.RemoteName.RemoteEventName)
local RemoteFolderName = require(network.RemoteFolderName)
local RemoteFunctionName = require(network.RemoteName.RemoteFunctionName)

--[[
	Wait in parallel for all RemoteEvents and RemoteFunctions defined in
    RemoteNames to replicate into the remoteFolder.

	Used to ensure all remotes exist before the client Network module finishes
    initializing.
]]
local function waitForAllRemotesAsync(remoteFolder: Folder, timeoutSeconds: number)
	-- Using FindFirstChild to satisfy type checker.
	local remoteEventsFolder = remoteFolder:FindFirstChild(RemoteFolderName.RemoteEvents) :: Folder
	local remoteFunctionsFolder = remoteFolder:FindFirstChild(RemoteFolderName.RemoteFunctions) :: Folder

	-- Make each set of event and function names read-only.
	local remoteEvents = table.freeze(RemoteEventName) :: { string }
	local remoteFunctions = table.freeze(RemoteFunctionName) :: { string }

	-- Validate that the remotes defined under RemoteNames exist in remote folders.
	local success = true
	local function search(names: { string }, folder: Folder)
		for _, remoteName in ipairs(names) do
			local remote = folder:WaitForChild(remoteName, timeoutSeconds)
			if not remote then
				success = false
				break
			end
		end
	end

	search(remoteEvents, remoteEventsFolder)
	search(remoteFunctions, remoteFunctionsFolder)

	assert(
        success,
        "Network could not find all reemotes. Did the client Network module initialize before the server?"
    )
end

return waitForAllRemotesAsync


--!strict
--[[
    RandomTableSelection
    @author DistractedGames
    @version 2.1.0

    A utility class that provides random selection from either:

    - An array (uniform probability)
    - A dictionary where { [item] = weight }

    Internally, all weighted tables are normalized into:
    - self.itemlist: { item, item, ... }    -- stable ordering
    - self.weightList: { number, number }   -- same index as itemList
    - self.totalWeight: number              -- cumulative sum

    This guarantees deterministic iteration order, fast selection, and simpler
    maintenance.
]]
local RandomTableSelection = {}
RandomTableSelection.__index = RandomTableSelection

export type Item = string

export type WeightedEntry = {
    item: Item,
    weight: number,
}

type ClassType = {
    getRandomItem: (self: RandomTableSelection) -> Item?,
    getRandomItemWithWeight: (self: RandomTableSelection) -> WeightedEntry?,
    containsItem: (self: RandomTableSelection, item: Item) -> boolean,
    getAllItems: (self: RandomTableSelection) -> { Item },
    getAllItemsWithWeights: (self: RandomTableSelection) -> { WeightedEntry },
    getAllItemsWithWeightsSorted: (self: RandomTableSelection) -> { WeightedEntry },
    addItem: (self: RandomTableSelection, item: Item, weight: number?) -> (),
    removeItem: (self: RandomTableSelection, item: Item) -> boolean,
}

type RandomTableSelection = setmetatable<ClassType, typeof(RandomTableSelection)>

type PrivateState = {
    isArray: boolean,
    itemList: { Item },
    weightList: { number }?,
    totalWeight: number?,
	indexMap: { [Item]: number },
}

local _private: { [RandomTableSelection]: PrivateState } = setmetatable({}, { __mode = "k" }) :: any

local function isArray(tbl: { Item } | { [Item]: number }): boolean
    if #tbl > 0 then
        local index = next(tbl)
        return typeof(index) == "number"
    end
    return false
end

local function buildFromArray(items: { Item }): ({ Item }, nil, nil)
    local itemList = table.clone(items)
    local weightList = nil
    return itemList, weightList, nil
end

local function buildFromWeighted(items: { [Item]: number }): ({ Item }, { number }, number)
    local itemList = {}
    local weightList = {}
    local total = 0

    for item, weight in items do
        if typeof(weight) == "number" and weight > 0 then
            table.insert(itemList, item)
            table.insert(weightList, weight)
            total += weight
        end
    end

    return itemList, weightList, total
end

local function weightedSelect(itemList: { Item }, weightList: { number }, total: number): Item?
    local threshold = math.random() * total
    local running = 0

    for i = 1, #weightList do
        running += weightList[i]
        if threshold <= running then
            return itemList[i]
        end
    end

    return itemList[#itemList] -- Extremely rare fallback
end

-- Constructor
function RandomTableSelection.new(items: { Item } | { [Item]: number }): RandomTableSelection
    assert(typeof(items) == "table", `[RandomTableSelection.new]: expected table, got {typeof(items)}`)

    local self = setmetatable({}, RandomTableSelection) :: RandomTableSelection

	_private[self] = {
		isArray = false,
		itemList = {},
		weightList = nil,
		totalWeight = nil,
		indexMap = {},
	}

	local state = _private[self]

    if isArray(items) then
        state.isArray = true
        state.itemList, state.weightList, state.totalWeight = buildFromArray(items :: { Item })
    else
        state.isArray = false
        state.itemList, state.weightList, state.totalWeight = buildFromWeighted(items :: { [Item]: number })
	end

	for i, item in state.itemList do
		state.indexMap[item] = i
	end

    return self
end

-- Core selection
function RandomTableSelection.getRandomItem(self: RandomTableSelection): Item?
	local state = _private[self]

    if #state.itemList == 0 then
        return nil
    end

    if state.isArray then
        local index = math.random(1, #state.itemList)
        return state.itemList[index]
    else
        return weightedSelect(state.itemList, state.weightList :: { number }, state.totalWeight :: number)
    end
end

function RandomTableSelection.getRandomItemWithWeight(self: RandomTableSelection): WeightedEntry?
	local state = _private[self]

    local item = self:getRandomItem()
    if item == nil then
        return nil
    end

    if state.isArray then
        local uniform = 1 / #state.itemList
        return { item = item, weight = uniform }
    else
        local index = state.indexMap[item]
        local weight = if index then (state.weightList :: { number })[index] else 1
        local total = state.totalWeight :: number
        return { item = item, weight = weight / total }
    end
end

-- Queries
function RandomTableSelection.containsItem(self: RandomTableSelection, item: Item): boolean
	local state = _private[self]

    return state.indexMap[item] ~= nil
end

function RandomTableSelection.getAllItems(self: RandomTableSelection): { Item }
	local state = _private[self]

    return table.clone(state.itemList)
end

function RandomTableSelection.getAllItemsWithWeights(self: RandomTableSelection): { WeightedEntry }
	local state = _private[self]

    local result = {}

    if state.isArray then
        local uniform = 1 / #state.itemList
        for _, item in state.itemList :: { Item } do
            table.insert(result, { item = item, weight = uniform })
        end
    else
        local weightList = state.weightList :: { number }
        local total = state.totalWeight :: number

        for i, item in state.itemList :: { Item } do
            table.insert(result, { item = item, weight = weightList[i] / total })
        end
    end

    return result
end

function RandomTableSelection.getAllItemsWithWeightsSorted(self: RandomTableSelection): { WeightedEntry }
    local entries = self:getAllItemsWithWeights()

    table.sort(entries, function(a: WeightedEntry, b: WeightedEntry)
        return a.weight < b.weight
    end)

    return entries
end

-- Mutation
function RandomTableSelection.addItem(self: RandomTableSelection, item: Item, weight: number?)
	local state = _private[self]

	table.insert(state.itemList, item)
	state.indexMap[item] = #state.itemList

	if not state.isArray then
	    local newWeight = weight or 1
		table.insert(state.weightList :: { number }, newWeight)
	    state.totalWeight = (state.totalWeight :: number) + newWeight
	end
end

function RandomTableSelection.removeItem(self: RandomTableSelection, item: Item): boolean
	local state = _private[self]

    local index = state.indexMap[item]
    if not index then
        return false
    end

	local lastIndex = #state.itemList
	local lastItem = state.itemList[lastIndex]

	-- Swapping last item into removed slot to prevent shifting and having to
	-- re-index each item.
	state.itemList[index] = lastItem
	state.indexMap[lastItem] = index

	state.itemList[lastIndex] = nil
    state.indexMap[item] = nil

    if not state.isArray then
		local weightList = state.weightList :: { number }

		local removedWeight = weightList[index]
		local lastWeight = weightList[lastIndex]

		weightList[index] = lastWeight
		weightList[lastIndex] = nil

		state.totalWeight = (state.totalWeight :: number) - removedWeight
    end

    return true
end

return RandomTableSelection


--!strict
-- ExampleModule.luau
--[[
    Demonstrates usage of the Logger utility in a basic module

    🧪 How to Use It

    1.  Place Logger.luau ReplicatedStorage/Source/Utility/

    2.  Add ExampleModule.luau to either ServerScriptService/Source or
        StarterPlayerScripts/Source so it gets picked up by ModuleLoader (if using)

    3.  Run your game and observe the output — you’ll see debug and warning
        messages formatted with context
--]]

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Logger = require(ReplicatedStorage.Source.Utility.Logger)

local logger = Logger.new({
    Debug = true,
    Prefix = "ExampleModule"
})

local ExampleModule = {}

function ExampleModule.Setup()
    logger.log("Running Setup phase")
    -- Simulate setup logic
end

function ExampleModule.Start()
    logger.log("Running Start phase")
    -- Simulate startup logic
    logger.log("Something went wrong during Start", true)
end

return ExampleModule


--!strict
--[[
    Logger
    @author DistractedGames
    @version 1.3.1

    A configurable logging utility that can be used across multiple scripts.
    Includes a specific logger for including collapsible tables in debug messages.
    Also includes a serializing function for converting tables to readable strings within logs.

    Example usage:
    ```lua
    local ReplicatedStorage = game:GetService("ReplicatedStorage")

    local Logger = require(ReplicatedStorage.Source.Utility.Logger)

    local logger = Logger.new({
        Debug = true, -- When true, will print debug messages, when false only warnings/errors
        Prefix = "MyScript" -- Prefixes [MyScript] before the logger message
    })
    local myTable = {
        name = "Test",
        value = 123,
    }

    -- This is the default debug message use:
    logger.log(`Debug messages will only print if Debug is true`)
    -- Output: [MyScript] [debugMessage:27] Debug messages will only print if Debug is true

    -- This statement is marked as a warning with the `true` value after the message:
    logger.log(`Warning messages will print regardless of Debug value`, true)
    -- Output: [MyScript] [warningMessage:31] Warning messages will print regardless of Debug value

    -- Use the `logTable` method to include a regular table printout, similar to the normal `print` function.
    -- The message is optional and prints before the table itself if included.
    logger.logTable(myTable, "This is a table of data:")
    -- Output: [MyScript] [debugMessage:36] This is a table of data: ▸ {...}

    -- Use the logger's serialize function inside an interpolated string to print tables.
    logger.log(`Processing data: {logger.serialize(myTable)}`)
    -- Output: [MyScript] [processData:40] Processing data: { name = Test, value = 123 }
    ```
]]

export type LoggerConfig = {
    Debug: boolean,
    Prefix: string?, -- Optional prefix for log messages
}

export type Logger = {
    log: (message: string, isWarning: boolean?) -> (),
    logTable: (table: any, message: string?) -> (),
    serialize: (value: any) -> string,
    setConfig: (newConfig: LoggerConfig) -> (),
    getConfig: () -> LoggerConfig,
}

-- Maximum depth for table serialization to prevent infinite loops.
local MAX_SERIALIZE_DEPTH = 3

-- Internal function to serialize table values for printing format.
local function serializeValue(value: any, depth: number): string
	depth = depth or 1
	if depth > MAX_SERIALIZE_DEPTH then
		return "{...}" -- Prevents infinite recursion
	end

	local valueType = typeof(value)

	if valueType == "table" then
		local parts = {}
		-- Simple check for array-like vs dictionary-like tables
		local isArray = #value > 0 and not next(value, #value)

		for key, val in pairs(value) do
			if isArray then
				table.insert(parts, serializeValue(val, depth + 1))
			else
				table.insert(parts, `{tostring(key)} = {serializeValue(val, depth + 1)}`)
			end
		end
		if isArray then
			return "[" .. table.concat(parts, ", ") .. "]"
		else
			return "{ " .. table.concat(parts, ", ") .. " }"
		end
	elseif valueType == "string" then
		return value -- Return raw string for clean logs
	else
		return tostring(value)
	end
end

-- Creates a new logger instance with default configuration.
local function new(initialConfig: LoggerConfig?): Logger
    local config: LoggerConfig = initialConfig or {
        Debug = false,
        Prefix = nil :: string?,
    }

    -- Used in lew of a metatable to keep things simple.
    local logger = {}

    --[[
        Logs a formatted message to the output.
        Uses `warn` for warnings and `print` for debug messages.
        The log includes the calling function's name and line for easier debugging.
        @param message The core message to log.
        @param isWarning If true, formats the message as a warning.
    ]]
    function logger.log(message: string, isWarning: boolean?)
        local prefix = if config.Prefix then `[{config.Prefix}] ` else ""
        local source, line, funcName = debug.info(2, "sln")
        local formattedSource = `{string.match(source, "@(.*)")}`
        local logHeader = `{prefix} [{funcName or formattedSource}:{line}]`

        if isWarning then
            warn(`{logHeader} {message}`)
        elseif config.Debug then
            print(`{logHeader} {message}`)
        end
    end

    --[[
        Logs a formatted table and optional message to the output.
        The log includes the calling function's name and line for easier debugging.
        @param table The table to be printed.
        @param message An optional message to prepend to the table output.
    ]]
    function logger.logTable(table: any, message: string?)
		if not config.Debug then
            return
        end

        local prefix = if config.Prefix then `[{config.Prefix}] ` else ""
        local source, line, funcName = debug.info(2, "sln")
        local formattedSource = `{string.match(source, "@(.*)")}`
        local logHeader = `{prefix} [{funcName or formattedSource}:{line}]`

        if message then
            print(logHeader, message, table)
        else
            print(logHeader, table)
        end
    end

    -- Used to serialize table values for printing.
    function logger.serialize(value: any): string
		return serializeValue(value, 1)
	end

    -- Used to update Logger configuration anytime after creation.
    function logger.setConfig(newConfig: LoggerConfig)
        config.Debug = newConfig.Debug
        config.Prefix = newConfig.Prefix
    end

    -- Used to get the current Logger configuration.
    function logger.getConfig()
        return table.clone(config)
    end

    return logger
end

return {
    new = new
}


local v0 = false;
require(script.Parent.defineFlags);
return function()
    if not v0 then
        v0 = true;
        local l_Parent_0 = script.Parent.Parent;
        if require(l_Parent_0.Src.Util.DebugFlags).EnableRoactConfigs() then
            require(l_Parent_0.Packages.Roact).setGlobalConfig({
                elementTracing = true,
                propValidation = true,
                typeChecks = true
            });
        end;
        return ;
    else
        return ;
    end;
end;


game:DefineFastFlag("9SliceEditorMigrateToRoact17", false);
game:DefineFastInt("9SliceEditorAnalyticsReportingHundrethsPercent", 0);
game:DefineFastFlag("9SliceEditorShorterLoadTime", false);
game:DefineFastFlag("9SliceEditorAllowUnloadedImages", false);
return nil;


if plugin then
    require(script.Parent.defineFlags);
    local l_9SliceEditorShorterLoadTime_0 = game:GetFastFlag("9SliceEditorShorterLoadTime");
    local l_status_0, l_result_0 = pcall(function()
        return game:GetService("StudioService"):HasInternalPermission();
    end);
    if not l_status_0 then
        l_result_0 = false;
    end;
    local l_Parent_0 = script.Parent.Parent;
    local v4 = require(l_Parent_0.Src.Util.DebugFlags);
    if not v4.RunningUnderCLI() then
        require(script.Parent.commonInit)();
        local v5 = nil;
        local v6 = nil;
        local function v11()
            local v7 = require(l_Parent_0.Packages.Roact);
            local v8 = require(l_Parent_0.Packages.Framework);
            local v9 = require(l_Parent_0.Src.MainPlugin);
            if l_result_0 then
                v5 = v8.DeveloperTools.forPlugin(l_Parent_0.Name, plugin);
            end;
            local function v10()
                plugin.Name = l_Parent_0.Name;
                v6 = v7.mount((v7.createElement(v9, {
                    Plugin = plugin
                })));
                if v5 then
                    v5:addRoactTree("Roact tree", v6);
                end;
            end;
            plugin.Unloading:Connect(function()
                if v5 then
                    v5:destroy();
                end;
                if v6 then
                    v7.unmount(v6);
                    v6 = nil;
                end;
            end);
            v10();
        end;
        if not l_9SliceEditorShorterLoadTime_0 then
            v11();
        elseif plugin.HostDataModelType ~= Enum.StudioDataModelType.Edit then
            return ;
        else
            if not (not l_result_0 or not v4.EnableDeveloperTools()) then
                v5 = require(l_Parent_0.Packages.Framework).DeveloperTools.forPlugin(l_Parent_0.Name, plugin);
            end;
            local v12 = nil;
            do
                local l_v12_0 = v12;
                l_v12_0 = game:GetService("GuiService").Open9SliceEditor:Connect(function(v14)
                    if l_v12_0 then
                        l_v12_0:Disconnect();
                        l_v12_0 = nil;
                    end;
                    local v15 = require(l_Parent_0.Packages.Roact);
                    local v16 = require(l_Parent_0.Src.MainPlugin);
                    plugin.Name = l_Parent_0.Name;
                    v6 = v15.mount((v15.createElement(v16, {
                        Plugin = plugin,
                        InitialEditorInstanceRequest = v14
                    })));
                    if v5 then
                        v5:addRoactTree("Roact tree", v6);
                    end;
                    plugin.Unloading:Connect(function()
                        if v5 then
                            v5:destroy();
                        end;
                        if v6 then
                            v15.unmount(v6);
                            v6 = nil;
                        end;
                    end);
                end);
            end;
        end;
        return ;
    else
        return ;
    end;
else
    return ;
end;


local l_Parent_0 = script.Parent.Parent;
require(script.Parent.defineFlags);
local l_9SliceEditorShorterLoadTime_0 = game:GetFastFlag("9SliceEditorShorterLoadTime");
local l_status_0, l_result_0 = pcall(function()
    return game:GetService("StudioService"):HasInternalPermission();
end);
if l_status_0 and l_result_0 then
    require(script.Parent.commonInit)();
    local v4 = require(l_Parent_0.Src.Util.DebugFlags);
    local v5 = if not l_9SliceEditorShorterLoadTime_0 then require(l_Parent_0.Packages.Framework) else nil;
    if not (not v4.RunningUnderCLI() and not v4.RunTests()) then
        local v6 = require(l_Parent_0.Packages.Dev.TestEZ);
        local l_TestBootstrap_0 = v6.TestBootstrap;
        local l_TeamCityReporter_0 = v6.Reporters.TeamCityReporter;
        local l_TextReporter_0 = v6.Reporters.TextReporter;
        if l_9SliceEditorShorterLoadTime_0 then
            v5 = require(l_Parent_0.Packages.Framework);
        end;
        local v10 = not not _G.TEAMCITY and l_TeamCityReporter_0 or l_TextReporter_0;
        local l_Src_0 = l_Parent_0.Src;
        print("----- All " .. l_Parent_0.Name .. " Tests ------");
        local v12 = tick();
        l_TestBootstrap_0:run({
            l_Src_0
        }, v10);
        print(string.format("Completed in %.3f s", tick() - v12));
        print("----------------------------------");
        if v4.RunDeveloperFrameworkTests() then
            print("");
            print("----- All DeveloperFramework Tests ------");
            v5.TestHelpers.runFrameworkTests(v6, v10);
            print("----------------------------------");
        end;
    end;
    if v4.RunningUnderCLI() then
        pcall(function()
            game:GetService("ProcessService"):ExitAsync(0);
        end);
    end;
    return ;
else
    return ;
end;


local l_9SliceEditorMigrateToRoact17_0 = game:GetFastFlag("9SliceEditorMigrateToRoact17");
local l_script_FirstAncestor_0 = script:FindFirstAncestor("Packages");
if not l_9SliceEditorMigrateToRoact17_0 then
    return require(l_script_FirstAncestor_0._Index.Roact.Roact);
else
    return require(l_script_FirstAncestor_0.RoactCompat);
end;


local l_Parent_0 = script.Parent.Parent.Parent;
local v1 = require(l_Parent_0.Packages.Roact);
local v2 = require(l_Parent_0.Packages.Framework);
local l_ContextServices_0 = v2.ContextServices;
local l_withContext_0 = l_ContextServices_0.withContext;
local l_Localization_0 = l_ContextServices_0.Localization;
local l_UI_0 = v2.UI;
local l_TextLabel_0 = l_UI_0.TextLabel;
local l_StyledDialog_0 = l_UI_0.StyledDialog;
local v9 = v1.PureComponent:extend("AlertDialog");
v9.init = function(v10, v11)
    v10:setState({
        enabled = v11.Enabled
    });
    v10.closeDialog = function()
        v10:setState({
            enabled = false
        });
        v10.props.OnClose();
    end;
end;
v9.render = function(v12)
    local l_props_0 = v12.props;
    local l_Stylizer_0 = l_props_0.Stylizer;
    local l_Localization_1 = l_props_0.Localization;
    return v1.createElement(l_StyledDialog_0, {
        Style = "Alert",
        Enabled = v12.state.enabled,
        Title = l_Localization_1:getText("AlertDialog", l_props_0.TitleKey),
        Buttons = {
            {
                Key = "ok",
                Text = l_Localization_1:getText("AlertDialog", "OkButtonText")
            }
        },
        OnButtonPressed = v12.closeDialog,
        OnClose = l_props_0.OnClose,
        MinContentSize = l_Stylizer_0.PopupMessageSize,
        Modal = true
    }, {
        Label = v1.createElement(l_TextLabel_0, {
            Size = UDim2.fromScale(0.95, 1),
            AnchorPoint = Vector2.new(0.5, 0),
            Position = UDim2.fromScale(0.5, 0),
            Text = l_Localization_1:getText("AlertDialog", l_props_0.MessageKey, l_props_0.MessageKeyFormatTable),
            TextColor = l_Stylizer_0.TextColor,
            TextWrapped = true,
            TextSize = l_Stylizer_0.TextSize,
            TextXAlignment = Enum.TextXAlignment.Left
        })
    });
end;
return (l_withContext_0({
    Localization = l_Localization_0,
    Stylizer = l_ContextServices_0.Stylizer
})(v9));


local l_Parent_0 = script.Parent.Parent.Parent;
local v1 = require(l_Parent_0.Packages.Roact);
local v2 = require(l_Parent_0.Packages.Framework);
local v3 = require(l_Parent_0.Src.Util.Constants);
local v4 = require(l_Parent_0.Src.Util.Orientation);
local l_ContextServices_0 = v2.ContextServices;
local l_withContext_0 = l_ContextServices_0.withContext;
local l_Analytics_0 = l_ContextServices_0.Analytics;
local l_Localization_0 = l_ContextServices_0.Localization;
local v9 = v1.PureComponent:extend("ImageDragger");
local v10 = v4.Left.rawValue();
local v11 = v4.Right.rawValue();
local v12 = v4.Top.rawValue();
local v13 = v4.Bottom.rawValue();
local v14 = {
    [v10] = 1,
    [v11] = 2,
    [v12] = 3,
    [v13] = 4
};
v9.init = function(v15, v16)
    v15:setState({
        dragging = false
    });
    v15.draggerInstanceRef = v1.createRef();
    v15.selectionPriority = 0;
    v15.onInputBegan = function(v17, v18)
        local l_orientation_0 = v15.props.orientation;
        if v18.UserInputType == Enum.UserInputType.MouseButton1 then
            v15:setState({
                dragging = true
            });
            v16.onDragBegin(v17, l_orientation_0, Vector2.new(v18.Position.X, v18.Position.Y), (Vector2.new(v17.Position.X.Scale, v17.Position.Y.Scale)));
            return ;
        else
            if v18.UserInputType == Enum.UserInputType.MouseMovement then
                v15.props.addPriorityDragCandidate(l_orientation_0, v17.ZIndex, v17);
                v15.props.setMostRecentMouseMoveInputObject(v18);
            end;
            return ;
        end;
    end;
    v15.onHandleInputChanged = function(v20, v21)
        local v22 = nil;
        local l_orientation_1 = v15.props.orientation;
        local v24 = v15.draggerInstanceRef:getValue();
        local l_DRAGGER_WIDTH_0 = v3.DRAGGER_WIDTH;
        local v26 = 0;
        l_DRAGGER_WIDTH_0 = v3.DRAGGER_CLICK_WINDOW_WIDTH;
        v26 = (not (l_orientation_1 ~= v11) or l_orientation_1 == v13) and 0.01 or 0;
        if not (l_orientation_1 ~= v10) or l_orientation_1 == v11 then
            v22 = math.abs(((v24.AbsolutePosition.X + v26) + l_DRAGGER_WIDTH_0 / 2) - v21.Position.X);
        elseif not (l_orientation_1 ~= v12) or l_orientation_1 == v13 then
            v22 = math.abs(((v24.AbsolutePosition.Y + v26) + l_DRAGGER_WIDTH_0 / 2) - v21.Position.Y);
        end;
        v15.props.addDragCandidateWithId(v20, v15.props.orientation, v22, v24, v15.selectionPriority);
    end;
    v15.onInputBeganOnLowPriorityHandles = function(v27, v28)
        if v28.UserInputType == Enum.UserInputType.MouseButton1 then
            v15.props.startUncertainDrag((Vector2.new(v28.Position.X, v28.Position.Y)));
            return ;
        else
            if v28.UserInputType == Enum.UserInputType.MouseMovement then
                v15.onHandleInputChanged(v27, v28);
                v15.props.setMostRecentMouseMoveInputObject(v28);
            end;
            return ;
        end;
    end;
    v15.onInputChanged = function(_, v30)
        local l_orientation_2 = v15.props.orientation;
        if v15.state.dragging and v30.UserInputType == Enum.UserInputType.MouseMovement then
            v16.onDragging(Vector2.new(v30.Position.X, v30.Position.Y), l_orientation_2);
        end;
    end;
    v15.onInputEnded = function(_, v33)
        local l_orientation_3 = v15.props.orientation;
        v16.onDragEnd(v33, l_orientation_3);
        if v33.UserInputType == Enum.UserInputType.MouseButton1 then
            v15:setState({
                dragging = false
            });
            return ;
        else
            if v33.UserInputType == Enum.UserInputType.MouseMovement then
                v15.props.removePriorityDragCandidate(l_orientation_3);
            end;
            return ;
        end;
    end;
    v15.onHandleInputEnded = function(v35, v36)
        v16.onDragEnd(v36, v15.props.orientation);
        if v36.UserInputType == Enum.UserInputType.MouseButton1 then
            v15:setState({
                dragging = false
            });
            return ;
        else
            if v36.UserInputType == Enum.UserInputType.MouseMovement then
                v15.props.removeDragCandidateWithId(v35);
            end;
            return ;
        end;
    end;
    v15.onInputBeganOnPriorityHandles = function(_, _)
        v15.selectionPriority = v14[v15.props.orientation];
    end;
    v15.onInputEndedOnPriorityHandles = function(_, _)
        v15.selectionPriority = 0;
    end;
end;
v9.render = function(v41)
    local l_props_0 = v41.props;
    local l_sliceRect_0 = l_props_0.sliceRect;
    local l_pixelDimensions_0 = l_props_0.pixelDimensions;
    local l_orientation_4 = l_props_0.orientation;
    local l_Stylizer_0 = l_props_0.Stylizer;
    local l_isHovering_0 = l_props_0.isHovering;
    local v48 = l_isHovering_0 and not l_props_0.isDragging;
    local v49 = math.round(l_sliceRect_0[l_orientation_4]);
    local v50 = nil;
    local v51 = nil;
    local v52 = nil;
    local v53 = nil;
    local v54 = nil;
    local v55 = nil;
    local v56 = nil;
    local v57 = nil;
    local v58 = nil;
    if not (l_orientation_4 ~= v10) or l_orientation_4 == v11 then
        v51 = UDim2.fromScale(math.clamp(v49 / l_pixelDimensions_0.X, 0, 1), 0.5);
        v55 = l_Stylizer_0.EdgeHandleSize;
        local v59 = nil;
        if l_orientation_4 == v10 then
            v59 = v3.IMAGES.DRAGGER_V2.LEFT;
            v58 = UDim2.fromOffset((v3.DRAGGER_CLICK_WINDOW_WIDTH / 2 - v3.DRAGGER_WIDTH_V2) + v3.DRAGGER_CENTER_INSETPX, 0);
        elseif l_orientation_4 == v11 then
            v59 = v3.IMAGES.DRAGGER_V2.RIGHT;
            v58 = UDim2.fromOffset(v3.DRAGGER_CLICK_WINDOW_WIDTH / 2 - v3.DRAGGER_CENTER_INSETPX, 0);
        end;
        v53 = UDim2.new(0.5, 0, 0, l_Stylizer_0.EdgeHandleInsetPx);
        v54 = UDim2.new(0.5, 0, 1, -l_Stylizer_0.EdgeHandleInsetPx);
        v50 = not not v48 and v59.OUTLINED or v59.NORMAL;
        v57 = Rect.new(0, 8, 8, 8);
        v52 = UDim2.new(0, v3.DRAGGER_WIDTH_V2, 1, 0);
        v56 = UDim2.new(0, v3.DRAGGER_CLICK_WINDOW_WIDTH, 1, v3.DRAGGER_HANDLE_SIZE * 2);
    elseif not (l_orientation_4 ~= v12) or l_orientation_4 == v13 then
        local v60 = math.clamp(v49 / l_pixelDimensions_0.Y, 0, 1);
        v50 = v3.IMAGES.HORIZONTAL_DRAGGER;
        v51 = UDim2.fromScale(0.5, v60);
        v55 = UDim2.new(l_Stylizer_0.EdgeHandleSize.Y, l_Stylizer_0.EdgeHandleSize.X);
        local v61 = nil;
        if l_orientation_4 == v12 then
            v61 = v3.IMAGES.DRAGGER_V2.TOP;
            v58 = UDim2.fromOffset(0, (v3.DRAGGER_CLICK_WINDOW_WIDTH / 2 - v3.DRAGGER_WIDTH_V2) + v3.DRAGGER_CENTER_INSETPX);
        elseif l_orientation_4 == v13 then
            v61 = v3.IMAGES.DRAGGER_V2.BOTTOM;
            v58 = UDim2.fromOffset(0, v3.DRAGGER_CLICK_WINDOW_WIDTH / 2 - v3.DRAGGER_CENTER_INSETPX);
        end;
        v53 = UDim2.new(0, l_Stylizer_0.EdgeHandleInsetPx, 0.5, 0);
        v54 = UDim2.new(1, -l_Stylizer_0.EdgeHandleInsetPx, 0.5, 0);
        v50 = not not v48 and v61.OUTLINED or v61.NORMAL;
        v57 = Rect.new(8, 0, 8, 8);
        v52 = UDim2.new(1, 0, 0, v3.DRAGGER_WIDTH_V2);
        v56 = UDim2.new(1, v3.DRAGGER_HANDLE_SIZE * 2, 0, v3.DRAGGER_CLICK_WINDOW_WIDTH);
    end;
    return v1.createElement("Frame", {
        AnchorPoint = Vector2.new(0.5, 0.5),
        Position = v51,
        Size = v56,
        BorderSizePixel = 0,
        BackgroundTransparency = 1,
        BackgroundColor3 = Color3.new(0, 0, 1),
        [v1.Event.InputBegan] = v41.onInputBeganOnLowPriorityHandles,
        [v1.Event.InputChanged] = v41.onHandleInputChanged,
        [v1.Event.InputEnded] = v41.onHandleInputEnded,
        [v1.Ref] = v41.draggerInstanceRef
    }, {
        Image = v1.createElement("ImageLabel", {
            Position = v58,
            BackgroundTransparency = 1,
            Image = v50,
            Size = v52,
            ScaleType = Enum.ScaleType.Slice,
            SliceCenter = v57,
            BorderSizePixel = 0,
            ImageColor3 = (not not v48 and Color3.fromRGB(255, 131, 131) or (l_isHovering_0 and l_props_0.isDragging) and Color3.fromRGB(210, 0, 0)) or Color3.fromRGB(255, 0, 0),
            ZIndex = (5 + v14[l_orientation_4]) + (not l_isHovering_0 and 0 or 100),
            [v1.Event.InputBegan] = v41.onInputBeganOnPriorityHandles,
            [v1.Event.InputEnded] = v41.onInputEndedOnPriorityHandles
        }, {
            Handle1 = v1.createElement("Frame", {
                AnchorPoint = Vector2.new(0.5, 0.5),
                Position = v53,
                Size = v55,
                BorderSizePixel = 0,
                ZIndex = 1 + v14[l_orientation_4],
                BackgroundColor3 = Color3.new(0, 1, 0),
                BackgroundTransparency = 1,
                [v1.Event.InputBegan] = v41.onInputBeganOnLowPriorityHandles,
                [v1.Event.InputChanged] = v41.onHandleInputChanged,
                [v1.Event.InputEnded] = v41.onHandleInputEnded
            }),
            Handle2 = v1.createElement("Frame", {
                AnchorPoint = Vector2.new(0.5, 0.5),
                Position = v54,
                Size = v55,
                BorderSizePixel = 0,
                ZIndex = 1 + v14[l_orientation_4],
                BackgroundColor3 = Color3.new(0, 1, 0),
                BackgroundTransparency = 1,
                [v1.Event.InputBegan] = v41.onInputBeganOnLowPriorityHandles,
                [v1.Event.InputChanged] = v41.onHandleInputChanged,
                [v1.Event.InputEnded] = v41.onHandleInputEnded
            })
        })
    });
end;
return (l_withContext_0({
    Analytics = l_Analytics_0,
    Localization = l_Localization_0,
    Stylizer = l_ContextServices_0.Stylizer,
    Mouse = l_ContextServices_0.Mouse
})(v9));


local l_Parent_0 = script.Parent.Parent.Parent;
local v1 = require(l_Parent_0.Packages.Roact);
local v2 = require(l_Parent_0.Packages.Framework);
local v3 = require(l_Parent_0.Src.Util.Constants);
local v4 = require(l_Parent_0.Src.Util.Orientation);
local v5 = require(l_Parent_0.Src.Util.MouseCursorManager);
local v6 = require(l_Parent_0.Src.Components.ImageDragger);
local l_ContextServices_0 = v2.ContextServices;
local l_withContext_0 = l_ContextServices_0.withContext;
local l_Analytics_0 = l_ContextServices_0.Analytics;
local l_Localization_0 = l_ContextServices_0.Localization;
local l_Pane_0 = v2.UI.Pane;
local v12 = v1.PureComponent:extend("ImageEditor");
local v13 = v4.Left.rawValue();
local v14 = v4.Right.rawValue();
local v15 = v4.Top.rawValue();
local v16 = v4.Bottom.rawValue();
local v17 = v4.Undefined.rawValue();
v12.init = function(v18, v19)
    v18.draggerHandlingMovement = false;
    v18.dragOrientation = v17;
    v18:setState({
        hoveringDraggerOrientation = -1
    });
    if math.max(v19.pixelDimensions.X, v19.pixelDimensions.Y) <= 0 then
        v18.leftPos = 0;
        v18.rightPos = 1;
        v18.topPos = 0;
        v18.bottomPos = 1;
    else
        local l_pixelDimensions_0 = v19.pixelDimensions;
        assert(l_pixelDimensions_0.X > 0);
        assert(l_pixelDimensions_0.Y > 0);
        local l_sliceRect_0 = v19.sliceRect;
        v18.leftPos = math.clamp(l_sliceRect_0[v13] / l_pixelDimensions_0.X, 0, 1);
        v18.rightPos = math.clamp(l_sliceRect_0[v14] / l_pixelDimensions_0.X, 0, 1);
        v18.topPos = math.clamp(l_sliceRect_0[v15] / l_pixelDimensions_0.Y, 0, 1);
        v18.bottomPos = math.clamp(l_sliceRect_0[v16] / l_pixelDimensions_0.Y, 0, 1);
    end;
    v18.backgroundImageRef = v1.createRef();
    v18.onDragging = function(v22, v23)
        if v18.dragOrientation == v17 then
            return ;
        else
            v18.draggerHandlingMovement = true;
            v18.dragOrientation = v23;
            v18.updateDraggedPosition(v22);
            return ;
        end;
    end;
    v18.disconnectMouseMoveInputObject = function()
        if v18.mouseMoveInputObjectConnection then
            v18.mouseMoveInputObjectConnection:Disconnect();
            v18.mouseMoveInputObjectConnection = nil;
        end;
    end;
    v18.setDraggingState = function(v24)
        v18.dragging = v24;
        v18:setState({
            dragging = v24
        });
    end;
    v18.setDraggingState(false);
    v18.onDragBegin = function(v25, v26, v27, v28)
        v18.obj = v25;
        v18.draggerHandlingMovement = true;
        v18.dragOrientation = v26;
        v18.mousePosition = v27;
        v18.draggerPosition = v28;
        v18.setDraggingState(true);
        v5.setLocked(v18.props.Mouse, true);
        local l_lastMouseMoveInputObject_0 = v18.lastMouseMoveInputObject;
        if l_lastMouseMoveInputObject_0 ~= nil then
            v18.disconnectMouseMoveInputObject();
            v18.mouseMoveInputObjectConnection = l_lastMouseMoveInputObject_0:GetPropertyChangedSignal("Position"):Connect(function()
                if v18.dragging then
                    v18.onDragging(l_lastMouseMoveInputObject_0.Position, v26);
                end;
            end);
        end;
    end;
    v18.onDragEnd = function(v30, _)
        local l_sliceRect_1 = v18.props.sliceRect;
        local l_pixelDimensions_1 = v18.props.pixelDimensions;
        if v30.UserInputType == Enum.UserInputType.MouseButton1 then
            local v34 = nil;
            if v18.dragOrientation == v13 then
                v34 = {
                    math.round(v18.leftPos * l_pixelDimensions_1.X),
                    l_sliceRect_1[v14],
                    l_sliceRect_1[v15],
                    l_sliceRect_1[v16]
                };
            elseif v18.dragOrientation == v14 then
                v34 = {
                    l_sliceRect_1[v13],
                    math.round(v18.rightPos * l_pixelDimensions_1.X),
                    l_sliceRect_1[v15],
                    l_sliceRect_1[v16]
                };
            elseif v18.dragOrientation == v15 then
                v34 = {
                    l_sliceRect_1[v13],
                    l_sliceRect_1[v14],
                    math.round(v18.topPos * l_pixelDimensions_1.Y),
                    l_sliceRect_1[v16]
                };
            elseif v18.dragOrientation == v16 then
                v34 = {
                    l_sliceRect_1[v13],
                    l_sliceRect_1[v14],
                    l_sliceRect_1[v15],
                    (math.round(v18.bottomPos * l_pixelDimensions_1.Y))
                };
            end;
            if v34 then
                v18.props.setSliceRect(v34, true);
            end;
            v18.disconnectMouseMoveInputObject();
            v18.setDraggingState(false);
            v18.uncertainDragStarted = false;
            v18.updateHoverDragger();
            v5.setLocked(v18.props.Mouse, false);
        end;
        v18.draggerHandlingMovement = false;
    end;
    v18.priorityDragCandidates = {};
    v18.getBestPriorityDragCandidate = function()
        local v35 = nil;
        local v36 = nil;
        for _, v38 in pairs(v18.priorityDragCandidates) do
            if not (v35 ~= nil) or v35 < v38.priority then
                v35 = v38.priority;
                v36 = v38;
            end;
        end;
        return v36;
    end;
    v18.uncertainDragCandidates = {};
    v18.getBestUncertainDragCandidate = function()
        local v39 = nil;
        for _, v41 in pairs(v18.uncertainDragCandidates) do
            if not (v39 ~= nil) or v39 < v41.priority then
                v39 = v41.priority;
            end;
        end;
        local v42 = nil;
        local v43 = nil;
        for _, v45 in pairs(v18.uncertainDragCandidates) do
            if v45.priority == v39 and (not (v42 ~= nil) or v45.distance < v42) then
                v42 = v45.distance;
                v43 = v45;
            end;
        end;
        return v43;
    end;
    v18.uncertainDragStarted = false;
    v18.startUncertainDrag = function(v46)
        if not v18.uncertainDragStarted then
            v18.uncertainDragStarted = true;
            local v47 = v18.getBestUncertainDragCandidate();
            if v47 then
                local l_instance_0 = v47.instance;
                v18.onDragBegin(l_instance_0, v47.orientation, v46, (Vector2.new(l_instance_0.Position.X.Scale, l_instance_0.Position.Y.Scale)));
                v18.draggerHandlingMovement = false;
            end;
            return ;
        else
            return ;
        end;
    end;
    v18.priorityHoverOrientation = nil;
    v18.updateHoverDragger = function(_, _)
        if not v18.dragging then
            local v51 = -1;
            local v52 = v18.getBestPriorityDragCandidate();
            if not v52 then
                local v53 = v18.getBestUncertainDragCandidate();
                if v53 then
                    v51 = v53.orientation;
                end;
            else
                v51 = v52.orientation;
            end;
            v18:setState({
                hoveringDraggerOrientation = v51
            });
            if not (v51 ~= v13) or v51 == v14 then
                v5.setCursor(v18.props.Mouse, v3.MOUSE_CURSORS.EW);
            elseif not (v51 ~= v15) or v51 == v16 then
                v5.setCursor(v18.props.Mouse, v3.MOUSE_CURSORS.NS);
            end;
            if v51 == -1 then
                v5.resetCursor(v18.props.Mouse);
            end;
            return ;
        else
            return ;
        end;
    end;
    v18.addDragCandidateWithId = function(v54, v55, v56, v57, v58)
        v18.uncertainDragCandidates[v54] = {
            distance = v56,
            instance = v57,
            orientation = v55,
            priority = v58 or 0
        };
        v18.updateHoverDragger();
    end;
    v18.removeDragCandidateWithId = function(v59)
        v18.uncertainDragCandidates[v59] = nil;
        v18.updateHoverDragger();
    end;
    v18.onBackgroundInputChanged = function(_, v61)
        if v18.dragging and v61.UserInputType == Enum.UserInputType.MouseMovement then
            if not v18.draggerHandlingMovement then
                v18.updateDraggedPosition(v61.Position);
            else
                return ;
            end;
        end;
    end;
    v18.onBackgroundInputEnded = function(_, v63)
        if not (not (v63.UserInputType == Enum.UserInputType.MouseButton1) or not v18.uncertainDragStarted) then
            v18.onDragEnd(v63, v18.dragOrientation);
        end;
    end;
    v18.updateDraggedPosition = function(v64)
        local l_sliceRect_2 = v18.props.sliceRect;
        local v66 = Vector2.new(v64.X, v64.Y) - v18.mousePosition;
        local l_fitImageSize_0 = v18.state.fitImageSize;
        if l_fitImageSize_0 then
            v18.newPosition = v18.draggerPosition + v66 / l_fitImageSize_0;
            local l_pixelDimensions_2 = v18.props.pixelDimensions;
            if v18.dragOrientation == v13 then
                v18.leftPos = math.clamp(v18.newPosition.X, 0, l_sliceRect_2[v14] / l_pixelDimensions_2.X);
                v18.obj.Position = UDim2.fromScale(v18.leftPos, v18.obj.Position.Y.Scale);
                return ;
            elseif v18.dragOrientation == v14 then
                v18.rightPos = math.clamp(v18.newPosition.X, l_sliceRect_2[v13] / l_pixelDimensions_2.X, 1);
                v18.obj.Position = UDim2.fromScale(v18.rightPos, v18.obj.Position.Y.Scale);
                return ;
            elseif v18.dragOrientation == v15 then
                v18.topPos = math.clamp(v18.newPosition.Y, 0, l_sliceRect_2[v16] / l_pixelDimensions_2.Y);
                v18.obj.Position = UDim2.fromScale(v18.obj.Position.X.Scale, v18.topPos);
                return ;
            else
                if v18.dragOrientation == v16 then
                    v18.bottomPos = math.clamp(v18.newPosition.Y, l_sliceRect_2[v15] / l_pixelDimensions_2.Y, 1);
                    v18.obj.Position = UDim2.fromScale(v18.obj.Position.X.Scale, v18.bottomPos);
                end;
                return ;
            end;
        else
            return ;
        end;
    end;
    v18.addPriorityDragCandidate = function(v69, v70, v71)
        v18.priorityDragCandidates[v69] = {
            priority = v70,
            instance = v71,
            orientation = v69
        };
        v18.updateHoverDragger();
    end;
    v18.removePriorityDragCandidate = function(v72)
        v18.priorityDragCandidates[v72] = nil;
        v18.updateHoverDragger();
    end;
    v18.setMostRecentMouseMoveInputObject = function(v73)
        v18.lastMouseMoveInputObject = v73;
    end;
    v18.onFitImageSizeChanged = function(v74)
        local l_pixelDimensions_3 = v18.props.pixelDimensions;
        local v76 = false;
        if l_pixelDimensions_3 then
            v76 = l_pixelDimensions_3.X < v74.AbsoluteSize.X;
        end;
        v18:setState({
            fitImageSize = v74.AbsoluteSize,
            isEnlarged = v76
        });
    end;
end;
v12.createDragger = function(v77, v78)
    return v1.createElement(v6, {
        orientation = v78,
        pixelDimensions = v77.props.pixelDimensions,
        sliceRect = v77.props.sliceRect,
        onDragBegin = v77.onDragBegin,
        onDragging = v77.onDragging,
        onDragEnd = v77.onDragEnd,
        addDragCandidateWithId = v77.addDragCandidateWithId,
        removeDragCandidateWithId = v77.removeDragCandidateWithId,
        isHovering = v77.state.hoveringDraggerOrientation == v78,
        isDragging = v77.state.dragging,
        addPriorityDragCandidate = v77.addPriorityDragCandidate,
        removePriorityDragCandidate = v77.removePriorityDragCandidate,
        startUncertainDrag = v77.startUncertainDrag,
        setMostRecentMouseMoveInputObject = v77.setMostRecentMouseMoveInputObject
    });
end;
v12.didMount = function(v79)
    v79.onFitImageSizeChanged(v79.backgroundImageRef:getValue());
end;
v12.render = function(v80)
    local l_props_0 = v80.props;
    local l_Stylizer_0 = l_props_0.Stylizer;
    local l_selectedObject_0 = l_props_0.selectedObject;
    local l_pixelDimensions_4 = l_props_0.pixelDimensions;
    assert(l_selectedObject_0);
    assert(l_pixelDimensions_4);
    local v85 = false;
    if l_pixelDimensions_4.X > 0 then
        v85 = l_pixelDimensions_4.Y > 0;
    end;
    assert(v85);
    return v1.createElement(l_Pane_0, {
        Position = l_props_0.position,
        Size = l_props_0.size,
        Style = "RoundBox",
        BackgroundColor = l_Stylizer_0.PaneBackgroundColor,
        Padding = v3.IMAGE_PREVIEW_WINDOW_PADDING
    }, {
        BackgroundCheckboardImage = v1.createElement("ImageButton", {
            BackgroundTransparency = 1,
            Image = v3.IMAGES.BACKGROUND_GRID,
            ScaleType = Enum.ScaleType.Tile,
            Size = UDim2.fromScale(1, 1),
            TileSize = UDim2.fromOffset(v3.BACKGROUND_TILE_SIZE, v3.BACKGROUND_TILE_SIZE),
            [v1.Event.InputChanged] = v80.onBackgroundInputChanged,
            [v1.Event.InputEnded] = v80.onBackgroundInputEnded,
            LayoutOrder = l_props_0.layoutOrder,
            AnchorPoint = Vector2.new(0.5, 0.5),
            Position = UDim2.fromScale(0.5, 0.5),
            [v1.Change.AbsoluteSize] = v80.onFitImageSizeChanged,
            [v1.Ref] = v80.backgroundImageRef
        }, {
            AspectRatioConstraint = v1.createElement("UIAspectRatioConstraint", {
                AspectRatio = l_pixelDimensions_4.X / l_pixelDimensions_4.Y,
                AspectType = Enum.AspectType.FitWithinMaxSize,
                DominantAxis = Enum.DominantAxis.Width
            }),
            ImagePreview = v1.createElement("ImageLabel", {
                BackgroundTransparency = 1,
                Image = l_selectedObject_0.Image,
                ImageColor3 = l_props_0.imageColor3,
                Position = UDim2.fromScale(0, 0),
                ScaleType = Enum.ScaleType.Fit,
                ResampleMode = not not v80.state.isEnlarged and Enum.ResamplerMode.Pixelated or Enum.ResamplerMode.Default,
                ImageRectOffset = l_props_0.imageRectOffset,
                ImageRectSize = l_props_0.imageRectSize,
                Size = UDim2.fromScale(1, 1)
            }, {
                LeftDragSlider = v80:createDragger(v13),
                RightDragSlider = v80:createDragger(v14),
                TopDragSlider = v80:createDragger(v15),
                BottomDragSlider = v80:createDragger(v16)
            }),
            border = v1.createElement("UIStroke", {
                Thickness = 1,
                Color = l_Stylizer_0.PaneBorderColor,
                Transparency = 0
            })
        })
    });
end;
return (l_withContext_0({
    Analytics = l_Analytics_0,
    Localization = l_Localization_0,
    Stylizer = l_ContextServices_0.Stylizer,
    Mouse = l_ContextServices_0.Mouse
})(v12));


local l_Parent_0 = script.Parent.Parent.Parent;
local v1 = require(l_Parent_0.Packages.Roact);
local v2 = require(l_Parent_0.Packages.Framework);
local v3 = require(l_Parent_0.Src.Util.SliceRectUtil);
local _ = require(l_Parent_0.Src.Types);
local v5 = require(l_Parent_0.Src.Util.Orientation);
local l_ContextServices_0 = v2.ContextServices;
local l_withContext_0 = l_ContextServices_0.withContext;
local l_Analytics_0 = l_ContextServices_0.Analytics;
local l_Localization_0 = l_ContextServices_0.Localization;
local l_Promise_0 = v2.Util.Promise;
local v11 = require(l_Parent_0.Src.Components.AlertDialog);
local l_GuiService_0 = game:GetService("GuiService");
local l_Selection_0 = game:GetService("Selection");
local l_RunService_0 = game:GetService("RunService");
local l_9SliceEditorAllowUnloadedImages_0 = game:GetFastFlag("9SliceEditorAllowUnloadedImages");
local v16 = v1.PureComponent:extend("InstanceUnderEditManager");
local v17 = v5.Left.rawValue();
local v18 = v5.Right.rawValue();
local v19 = v5.Top.rawValue();
local v20 = v5.Bottom.rawValue();
v16.init = function(v21, v22)
    v21.state = {
        showingAlertTitleKey = nil,
        showingAlertMessageKey = nil
    };
    v21.instanceUnderEdit = nil;
    v21.instanceWatchedForImageChange = nil;
    v21.lastSliceOffsets = nil;
    v21.uncroppedImageSize = Vector2.new();
    v21.showAlertDialog = function(v23, v24, v25)
        v21:setState({
            showingAlertTitleKey = v23,
            showingAlertMessageKey = v24,
            showingAlertMessageReplacements = v25
        });
    end;
    v21.closeAlertDialog = function()
        v21:setState({
            showingAlertTitleKey = v1.None,
            showingAlertMessageKey = v1.None,
            showingAlertMessageReplacements = v1.None
        });
    end;
    v21.imageUnderEditConnections = {};
    v21.clearCurrentImageUnderEdit = function()
        for _, v27 in ipairs(v21.imageUnderEditConnections) do
            if v27 then
                v27:Disconnect();
            end;
        end;
        v21.imageUnderEditConnections = {};
    end;
    v21.getOffsetsForResizedImage = function(v28, v29)
        local v30 = {
            [v17] = math.clamp(v28[v17], 0, v29.X)
        };
        v30[v18] = math.clamp(v28[v18], 0, (math.max(0, v29.X - v30[v17])));
        v30[v19] = math.clamp(v28[v19], 0, v29.Y);
        v30[v20] = math.clamp(v28[v20], 0, (math.max(0, v29.Y - v30[v19])));
        return v30;
    end;
    v21.getImageDimensionsForInstance = function(v31)
        if v31.ImageRectSize.X > 0 and v31.ImageRectSize.Y > 0 then
            return v31.ImageRectSize;
        elseif not l_9SliceEditorAllowUnloadedImages_0 then
            return v31.ContentImageSize;
        else
            return v21.uncroppedImageSize;
        end;
    end;
    v21.getImageUnderEdit = function()
        return v21.instanceUnderEdit;
    end;
    v21.onSliceCenterChanged = function()
        local v32 = v21.getImageUnderEdit();
        if v32 ~= nil then
            local v33 = v3.getSliceRectFromSliceCenter(v32.SliceCenter);
            v21.props.SliceRectChanged(v33);
            v21.lastSliceOffsets = v3.getOffsetsFromSliceRect(v33, (v21.getImageDimensionsForInstance(v32)));
        end;
    end;
    v21.getInstanceProperty = function(v34)
        local v35 = v21.getImageUnderEdit();
        return v35 and v35[v34];
    end;
    v21.onImageRectOffsetChanged = function()
        v21.props.InstancePropertyChanged("ImageRectOffset", v21.getInstanceProperty("ImageRectOffset"));
    end;
    v21.clampSliceCenterToDimensions = function(v36, v37)
        return Rect.new(math.clamp(v36.Min.X, 0, v37.X), math.clamp(v36.Min.Y, 0, v37.Y), math.clamp(v36.Max.X, 0, v37.X), (math.clamp(v36.Max.Y, 0, v37.Y)));
    end;
    v21.onImageRectSizeChanged = function()
        local v38 = v21.getImageUnderEdit();
        if v38 then
            local l_ImageRectSize_0 = v38.ImageRectSize;
            v21.props.InstancePropertyChanged("ImageRectSize", l_ImageRectSize_0);
            if l_ImageRectSize_0.X > 0 and l_ImageRectSize_0.Y > 0 then
                v38.SliceCenter = v21.clampSliceCenterToDimensions(v38.SliceCenter, l_ImageRectSize_0);
            end;
            return ;
        else
            return ;
        end;
    end;
    v21.onImageColor3Changed = function()
        v21.props.InstancePropertyChanged("ImageColor3", v21.getInstanceProperty("ImageColor3"));
    end;
    v21.onResampleModeChanged = function()
        v21.props.InstancePropertyChanged("ResampleMode", v21.getInstanceProperty("ResampleMode"));
    end;
    v21.openInstanceInEditor = function(v40, v41)
        v21.clearCurrentImageUnderEdit();
        local v42 = Vector2.new(0, 0);
        local v43 = {
            0,
            0,
            0,
            0
        };
        local v44 = {
            0,
            0,
            0,
            0
        };
        local v45 = v21.props.Localization:getText("Plugin", "Name");
        local v46 = {
            title = v45,
            pixelDimensions = v42,
            sliceRect = v43,
            revertSliceRect = v44
        };
        if v40 ~= nil then
            if not l_9SliceEditorAllowUnloadedImages_0 then
                v42 = v40.ContentImageSize;
            else
                assert(v41);
                local v47 = true;
                if v41.X <= 0 then
                    v47 = v41.Y > 0;
                end;
                assert(v47);
                v21.uncroppedImageSize = v41;
                v42 = v41;
            end;
            local v48 = v21.getImageDimensionsForInstance(v40);
            if v40.SliceCenter == Rect.new(0, 0, 0, 0) then
                v40.SliceCenter = Rect.new(0, 0, v48.X, v48.Y);
            end;
            table.insert(v21.imageUnderEditConnections, v40:GetPropertyChangedSignal("SliceCenter"):Connect(v21.onSliceCenterChanged));
            table.insert(v21.imageUnderEditConnections, v40:GetPropertyChangedSignal("ImageRectOffset"):Connect(v21.onImageRectOffsetChanged));
            table.insert(v21.imageUnderEditConnections, v40:GetPropertyChangedSignal("ImageRectSize"):Connect(v21.onImageRectSizeChanged));
            table.insert(v21.imageUnderEditConnections, v40:GetPropertyChangedSignal("ImageColor3"):Connect(v21.onImageColor3Changed));
            table.insert(v21.imageUnderEditConnections, v40:GetPropertyChangedSignal("ResampleMode"):Connect(v21.onResampleModeChanged));
            v43 = v3.getSliceRectFromSliceCenter(v40.SliceCenter);
            v44 = v3.copySliceRect(v43);
            v45 = v45 .. ": " .. tostring(v40.Name);
            v21.lastSliceOffsets = v3.getOffsetsFromSliceRect(v43, v48);
            v46 = {
                title = v45,
                pixelDimensions = v42,
                sliceRect = v43,
                revertSliceRect = v44,
                imageRectOffset = v40.ImageRectOffset,
                imageRectSize = v40.ImageRectSize,
                imageColor3 = v40.ImageColor3,
                resampleMode = v40.ResampleMode
            };
        end;
        v21.instanceUnderEdit = v40;
        v21.props.InstanceUnderEditChanged(v40, v46);
    end;
    v21.loadingToken = 0;
    v21.newLoadingToken = function()
        local l_v21_0 = v21;
        l_v21_0.loadingToken = l_v21_0.loadingToken + 1;
        return v21.loadingToken;
    end;
    if l_9SliceEditorAllowUnloadedImages_0 then
        v21.loadingImageRef = v1.createRef();
    end;
    v21.createPromiseForImageLoaded = function(v50, v51)
        v21.openInstanceInEditor(nil);
        local v52 = v21.newLoadingToken();
        return l_Promise_0.new(function(v53, v54)
            if v50 and (v50:IsA("ImageLabel") or v50:IsA("ImageButton")) then
                v21.connectImageChangedConnection(v50);
                local l_v50_0 = v50;
                if not l_9SliceEditorAllowUnloadedImages_0 then
                    if v50.IsLoaded then
                        v53(v50, v52);
                        return ;
                    end;
                elseif l_v50_0.IsLoaded then
                    v53(l_v50_0, v52);
                    return ;
                end;
                if not (not l_9SliceEditorAllowUnloadedImages_0 or not v51) then
                    v21.props.RequestToLoadImage(l_v50_0.Image);
                    v21.props.LoadingChanged(true);
                    l_RunService_0.RenderStepped:Wait();
                    l_RunService_0.RenderStepped:Wait();
                    l_RunService_0.RenderStepped:Wait();
                    if not v21._isMounted then
                        v54(false, v52);
                        return ;
                    end;
                end;
                v21.props.LoadingChanged(true);
                local v56 = tick();
                while true do
                    if tick() - v56 < 5 then
                        local v57 = false;
                        if not l_9SliceEditorAllowUnloadedImages_0 then
                            v57 = v50.IsLoaded and v50.ContentImageSize ~= Vector2.new(0, 0);
                        elseif v21._isMounted then
                            local v58 = v21.props.LoadingImageRef:getValue();
                            local l_v58_0 = v58;
                            if l_v58_0 then
                                l_v58_0 = v58.IsLoaded;
                                if l_v58_0 then
                                    l_v58_0 = false;
                                    if v58.ContentImageSize ~= Vector2.new(0, 0) then
                                        l_v58_0 = v58.Image == l_v50_0.Image;
                                    end;
                                end;
                            end;
                            v57 = l_v58_0;
                        else
                            v54(false, v52);
                            return ;
                        end;
                        if not v57 then
                            if not l_9SliceEditorAllowUnloadedImages_0 then
                                wait(1);
                            else
                                task.wait(0.2);
                            end;
                        elseif v52 == v21.loadingToken then
                            v53(v50);
                            return ;
                        else
                            v54(false, v52);
                            return ;
                        end;
                    else
                        v54(true, v52);
                        return ;
                    end;
                end;
            else
                v54(false, v52);
                return ;
            end;
        end);
    end;
    v21.createAndRunPromiseForImageLoaded = function(v60, v61)
        v21.disconnectImageChangedConnection();
        local v62 = nil;
        local v63 = false;
        if not l_9SliceEditorAllowUnloadedImages_0 then
            v62 = v21.createPromiseForImageLoaded(v60);
        else
            v63 = (v60 and (v60:IsA("ImageLabel") or v60:IsA("ImageButton"))) and not v60.IsLoaded;
            v62 = v21.createPromiseForImageLoaded(v60, v63);
        end;
        v62:andThen(function(v64)
            if v21._isMounted then
                if not l_9SliceEditorAllowUnloadedImages_0 then
                    assert(v64.IsLoaded);
                elseif not v63 then
                    assert(v64.IsLoaded);
                else
                    local v65 = v21.props.LoadingImageRef:getValue();
                    assert(v65 and v65.IsLoaded);
                end;
                if v61 then
                    if v21.lastSliceOffsets ~= nil then
                        local v66 = v21.getImageDimensionsForInstance(v64);
                        v64.SliceCenter = v3.getSliceCenterFromSliceRect((v3.getSliceRectFromOffsets(v21.getOffsetsForResizedImage(v21.lastSliceOffsets, v66), v66)));
                    else
                        v64.SliceCenter = Rect.new(0, 0, 0, 0);
                    end;
                end;
                if not l_9SliceEditorAllowUnloadedImages_0 then
                    v21.openInstanceInEditor(v64);
                else
                    local _ = nil;
                    v21.openInstanceInEditor(v64, if not v63 then v64.ContentImageSize else v21.props.LoadingImageRef:getValue().ContentImageSize);
                end;
                v21.props.LoadingChanged(false);
                return ;
            else
                return ;
            end;
        end, function(v68, v69)
            if v69 ~= v21.loadingToken then
                return ;
            elseif v21._isMounted then
                if v68 then
                    print(v21.props.Localization:getText("Plugin", "ImageLoadErrorMessage"));
                end;
                v21.props.LoadingChanged(false);
                return ;
            else
                return ;
            end;
        end);
    end;
    v21.onImageChanged = function()
        l_RunService_0.RenderStepped:Wait();
        l_RunService_0.RenderStepped:Wait();
        if v21._isMounted then
            local l_instanceWatchedForImageChange_0 = v21.instanceWatchedForImageChange;
            if l_instanceWatchedForImageChange_0 ~= nil then
                v21.createAndRunPromiseForImageLoaded(l_instanceWatchedForImageChange_0, true);
            end;
            return ;
        else
            return ;
        end;
    end;
    v21.onSelectionChanged = function()
        local v71 = l_Selection_0:Get();
        if #v71 > 1 then
            return ;
        elseif #v71 == 0 then
            v21.disconnectImageChangedConnection();
            v21.openInstanceInEditor(nil);
            return ;
        else
            local v72 = v71[1];
            assert(v72);
            if v72 == v21.instanceUnderEdit then
                return ;
            else
                v21.createAndRunPromiseForImageLoaded(v72, false);
                return ;
            end;
        end;
    end;
    v21.connectImageChangedConnection = function(v73)
        if not v21.imageChangedConnection then
            v21.instanceWatchedForImageChange = v73;
            v21.imageChangedConnection = v73:GetPropertyChangedSignal("Image"):Connect(v21.onImageChanged);
        end;
    end;
    v21.disconnectImageChangedConnection = function()
        if v21.imageChangedConnection then
            v21.imageChangedConnection:Disconnect();
            v21.imageChangedConnection = nil;
        end;
        v21.instanceWatchedForImageChange = nil;
    end;
    v21.startListeningToSelection = function()
        if not v21.selectionChangedConnection then
            v21.selectionChangedConnection = l_Selection_0.SelectionChanged:Connect(v21.onSelectionChanged);
        end;
    end;
    v21.stopListeningToSelection = function()
        if v21.selectionChangedConnection then
            v21.selectionChangedConnection:Disconnect();
            v21.selectionChangedConnection = nil;
        end;
    end;
    v21.onSliceCenterEditButtonClicked = function(v74)
        if v74:IsA("ImageLabel") or v74:IsA("ImageButton") then
            if not l_9SliceEditorAllowUnloadedImages_0 then
                if v74.IsLoaded then
                    local l_ContentImageSize_0 = v74.ContentImageSize;
                    if not l_ContentImageSize_0 or l_ContentImageSize_0 == Vector2.new(0, 0) then
                        v21.showAlertDialog("ErrorMessageTitle", "ImageContentDimensionsErrorMessage");
                        return ;
                    end;
                else
                    v21.showAlertDialog("ErrorMessageTitle", "ImageLoadedErrorMessage", {
                        contentId = v74.Image
                    });
                    return ;
                end;
            end;
            if not l_9SliceEditorAllowUnloadedImages_0 then
                v21.openInstanceInEditor(v74);
                v21.connectImageChangedConnection(v74);
                return ;
            else
                v21.createAndRunPromiseForImageLoaded(v74, false);
                return ;
            end;
        else
            v21.showAlertDialog("ErrorMessageTitle", "InvalidInstanceErrorMessage");
            return ;
        end;
    end;
    if v22.WidgetEnabled then
        v21.startListeningToSelection();
    end;
    v21.onOpen9SliceEditorConnection = l_GuiService_0.Open9SliceEditor:Connect(v21.onSliceCenterEditButtonClicked);
end;
v16.didMount = function(v76)
    v76._isMounted = true;
    if v76.props.InitialEditorInstanceRequest then
        task.defer(function()
            if v76._isMounted then
                v76.onSliceCenterEditButtonClicked(v76.props.InitialEditorInstanceRequest);
            end;
        end);
    end;
end;
v16.didUpdate = function(v77, v78, _)
    if not v77.props.WidgetEnabled or v78.WidgetEnabled then
        if not (v77.props.WidgetEnabled or not v78.WidgetEnabled) then
            v77.stopListeningToSelection();
            v77.clearCurrentImageUnderEdit();
            v77.disconnectImageChangedConnection();
        end;
        return ;
    else
        v77.startListeningToSelection();
        return ;
    end;
end;
v16.willUnmount = function(v80)
    v80._isMounted = false;
    v80.stopListeningToSelection();
    v80.clearCurrentImageUnderEdit();
    v80.disconnectImageChangedConnection();
    if v80.onOpen9SliceEditorConnection then
        v80.onOpen9SliceEditorConnection:Disconnect();
        v80.onOpen9SliceEditorConnection = nil;
    end;
end;
v16.render = function(v81)
    local l_state_0 = v81.state;
    if not l_state_0.showingAlertTitleKey then
        return nil;
    else
        return v1.createElement(v11, {
            Enabled = true,
            TitleKey = l_state_0.showingAlertTitleKey,
            MessageKey = l_state_0.showingAlertMessageKey,
            MessageKeyFormatTable = l_state_0.showingAlertMessageReplacements,
            OnClose = v81.closeAlertDialog
        });
    end;
end;
return (l_withContext_0({
    Analytics = l_Analytics_0,
    Localization = l_Localization_0,
    Stylizer = l_ContextServices_0.Stylizer
})(v16));


local l_ChangeHistoryService_0 = game:GetService("ChangeHistoryService");
local l_Parent_0 = script.Parent.Parent.Parent;
local v2 = require(l_Parent_0.Packages.Roact);
local v3 = require(l_Parent_0.Packages.Framework);
local v4 = require(l_Parent_0.Src.Util.Orientation);
local v5 = require(l_Parent_0.Src.Util.MouseCursorManager);
local l_Components_0 = l_Parent_0.Src.Components;
local v7 = require(l_Components_0.ImageEditor);
local v8 = require(l_Components_0.TextEditor);
local l_ContextServices_0 = v3.ContextServices;
local l_withContext_0 = l_ContextServices_0.withContext;
local l_Analytics_0 = l_ContextServices_0.Analytics;
local l_Localization_0 = l_ContextServices_0.Localization;
local l_StyleModifier_0 = v3.Util.StyleModifier;
local l_UI_0 = v3.UI;
local l_Pane_0 = l_UI_0.Pane;
local l_Button_0 = l_UI_0.Button;
local l_9SliceEditorAllowUnloadedImages_0 = game:GetFastFlag("9SliceEditorAllowUnloadedImages");
local l_TextLabel_0 = l_UI_0.TextLabel;
local v19 = v2.PureComponent:extend("SliceEditor");
local v20 = v4.Left.rawValue();
local v21 = v4.Right.rawValue();
local v22 = v4.Top.rawValue();
local v23 = v4.Bottom.rawValue();
local function _(v24, v25)
    local v26 = false;
    if v24[v20] == v25[v20] then
        v26 = false;
        if v24[v21] == v25[v21] then
            v26 = false;
            if v24[v22] == v25[v22] then
                v26 = v24[v23] == v25[v23];
            end;
        end;
    end;
    return v26;
end;
v19.init = function(v28, _)
    v28.getImageDimensions = function()
        local l_imageRectSize_0 = v28.props.imageRectSize;
        if (l_imageRectSize_0 and l_imageRectSize_0.X > 0) and l_imageRectSize_0.Y > 0 then
            return l_imageRectSize_0;
        else
            return v28.props.pixelDimensions;
        end;
    end;
    v28.clampAndRoundSliceRect = function(v31)
        local v32 = v28.getImageDimensions();
        local _ = nil;
        local _ = nil;
        local _ = nil;
        local _ = nil;
        return {
            math.clamp(math.round(v31[v20]), 0, v32.X),
            math.clamp(math.round(v31[v21]), 0, v32.X),
            math.clamp(math.round(v31[v22]), 0, v32.Y),
            (math.clamp(math.round(v31[v23]), 0, v32.Y))
        };
    end;
    v28.setSliceRect = function(v37, v38)
        local l_v37_0 = v37;
        if v38 then
            l_v37_0 = v28.clampAndRoundSliceRect(v37);
        end;
        if v28.props.selectedObject then
            v28.props.selectedObject.SliceCenter = Rect.new(l_v37_0[v20], l_v37_0[v22], l_v37_0[v21], l_v37_0[v23]);
        end;
        l_ChangeHistoryService_0:SetWaypoint("9SliceEditor changed SliceCenter");
    end;
    v28.onRevert = function()
        v28.setSliceRect(v28.props.revertSliceRect, false);
    end;
end;
v19.didMount = function(v40)
    v5.resetCursor(v40.props.Mouse);
end;
v19.render = function(v41)
    local l_props_0 = v41.props;
    local l_Stylizer_0 = l_props_0.Stylizer;
    local l_selectedObject_0 = l_props_0.selectedObject;
    local v45 = v41.getImageDimensions();
    local l_setSliceRect_0 = v41.setSliceRect;
    local l_sliceRect_0 = l_props_0.sliceRect;
    local l_Localization_1 = l_props_0.Localization;
    local l_Button_1 = l_props_0.Stylizer.Button;
    local v50 = false;
    if l_selectedObject_0 then
        local l_sliceRect_1 = l_props_0.sliceRect;
        local l_revertSliceRect_0 = l_props_0.revertSliceRect;
        local v53 = false;
        if l_sliceRect_1[v20] == l_revertSliceRect_0[v20] then
            v53 = false;
            if l_sliceRect_1[v21] == l_revertSliceRect_0[v21] then
                v53 = false;
                if l_sliceRect_1[v22] == l_revertSliceRect_0[v22] then
                    v53 = l_sliceRect_1[v23] == l_revertSliceRect_0[v23];
                end;
            end;
        end;
        if not v53 then
            v50 = true;
        end;
        return v2.createElement(l_Pane_0, {
            Style = "Box",
            Size = UDim2.fromScale(1, 1),
            Position = UDim2.fromOffset(0, 0),
            Layout = Enum.FillDirection.Vertical,
            Spacing = 0,
            HorizontalAlignment = Enum.HorizontalAlignment.Center,
            VerticalAlignment = Enum.VerticalAlignment.Top
        }, {
            Upper = v2.createElement(l_Pane_0, {
                Size = UDim2.new(1, 0, 1, -l_Stylizer_0.ButtonsAreaSize.Y.Offset),
                Layout = Enum.FillDirection.Horizontal,
                HorizontalAlignment = Enum.HorizontalAlignment.Left,
                VerticalAlignment = Enum.VerticalAlignment.Center,
                Spacing = 0,
                Padding = {
                    Top = l_Stylizer_0.PaddingPx,
                    Left = l_Stylizer_0.PaddingPx,
                    Right = l_Stylizer_0.PaddingPx,
                    Bottom = 0
                }
            }, {
                ImageEditorComponent = v2.createElement(v7, {
                    layoutOrder = 1,
                    size = UDim2.new(1 - l_Stylizer_0.TextAreaXWindowScaleFactor, -l_Stylizer_0.TextAreaSize.X.Offset, 1, 0),
                    selectedObject = l_selectedObject_0,
                    pixelDimensions = v45,
                    setSliceRect = l_setSliceRect_0,
                    sliceRect = l_sliceRect_0,
                    imageRectOffset = l_props_0.imageRectOffset,
                    imageRectSize = v45,
                    imageColor3 = l_props_0.imageColor3,
                    resampleMode = l_props_0.resampleMode
                }),
                TextEditorComponent = v2.createElement(v8, {
                    layoutOrder = 2,
                    size = UDim2.new(l_Stylizer_0.TextAreaXWindowScaleFactor, l_Stylizer_0.TextAreaSize.X.Offset, 0, l_Stylizer_0.TextAreaSize.Y.Offset),
                    pixelDimensions = v45,
                    setSliceRect = l_setSliceRect_0,
                    sliceRect = l_sliceRect_0
                })
            }),
            Lower = v2.createElement(l_Pane_0, {
                LayoutOrder = 2,
                Layout = Enum.FillDirection.Horizontal,
                HorizontalAlignment = Enum.HorizontalAlignment.Center,
                VerticalAlignment = Enum.VerticalAlignment.Center,
                Size = UDim2.new(1, 0, 0, l_Stylizer_0.ButtonsAreaSize.Y.Offset),
                Position = UDim2.fromOffset(0, l_Stylizer_0.ButtonsAreaYPos),
                Spacing = l_Stylizer_0.ButtonsSpacing
            }, {
                CloseButton = v2.createElement(l_Button_0, {
                    OnClick = l_props_0.onClose,
                    Size = l_Button_1.Size,
                    Style = l_Button_1.Style,
                    LayoutOrder = 1,
                    Text = l_Localization_1:getText("SliceEditor", "CloseButton")
                }),
                RevertButton = v2.createElement(l_Button_0, {
                    OnClick = v41.onRevert,
                    Size = l_Button_1.Size,
                    Style = l_Button_1.Style,
                    StyleModifier = not v50 and l_StyleModifier_0.Disabled or nil,
                    LayoutOrder = 2,
                    Text = l_Localization_1:getText("SliceEditor", "RevertButton")
                })
            })
        });
    else
        local v54 = l_Localization_1:getText("SliceEditor", "NoImageSelectedMessage");
        if l_props_0.loading then
            v54 = l_Localization_1:getText("SliceEditor", "ImageLoadingMessage");
        end;
        return v2.createElement(l_Pane_0, {
            Style = "Box",
            Size = UDim2.fromScale(1, 1),
            Position = UDim2.fromOffset(0, 0)
        }, {
            EntireFrame = v2.createElement(l_Pane_0, {
                AutomaticSize = Enum.AutomaticSize.XY,
                AnchorPoint = Vector2.new(0.5, 0.5),
                Position = UDim2.fromScale(0.5, 0.5)
            }, {
                Message = v2.createElement(l_TextLabel_0, {
                    Text = v54,
                    TextWrapped = true,
                    Size = l_Stylizer_0.InfoBoxSize
                })
            }),
            LoadingImage = if not l_9SliceEditorAllowUnloadedImages_0 then nil else v2.createElement("ImageLabel", {
                BackgroundTransparency = 1,
                ImageTransparency = 0.99,
                Image = l_props_0.contentIdToLoad,
                Size = UDim2.fromOffset(1, 1),
                Position = UDim2.fromOffset(0, 0),
                ScaleType = Enum.ScaleType.Fit,
                [v2.Ref] = l_props_0.loadingImageRef
            })
        });
    end;
end;
return (l_withContext_0({
    Analytics = l_Analytics_0,
    Localization = l_Localization_0,
    Stylizer = l_ContextServices_0.Stylizer,
    Mouse = l_ContextServices_0.Mouse
})(v19));