local D=script.Parent.Parent.Parent.Parent local E=D.Parent local s=require(D.Theme)local d=s.WithTheme local V=D.Validators local B=require(V.StyleValidator)local v=require(E.t)local w=require(E.Roact)local I=w.createElement local A=require(D.Utility.GetTextSize)local R=require(D.App.Surface.RoundedSurface)local p=script.Parent local o=require(p.CaptionClose)local q="\102\111\110\116\115\047\067\097\112\116\105\111\110"local e="\099\111\108\111\114\115\047\070\105\108\108\095\067\111\108\111\114\047\084\101\120\116\047\080\114\105\109\097\114\121"local S="\099\111\108\111\114\115\047\070\105\108\108\095\067\111\108\111\114\047\084\101\120\116\047\083\101\099\111\110\100\097\114\121"local k=w.PureComponent:extend(script.Name)k.defaultProps={Height=32,Text="\084\105\116\108\101\066\097\114",CaptionButtonWidth=48,BackgroundColor={Color=Color3.new(),Transparency=1}}k.validateProps=v.strictInterface({AlwaysShowClose=v.optional(v.boolean),CaptionButtonWidth=v.optional(v.number),Text=v.optional(v.string),LayoutOrder=v.optional(v.number);Icon=v.optional(B),ReleaseText=v.optional(v.string);TextColor=v.optional(B);BackgroundColor=v.optional(B);Height=v.optional(v.numberPositive),OnClose=v.optional(v.callback),Native=v.optional(v.table)})function k.render(D)local E=D.props return d(function(D)local s=D[q]local d=D[E.TextColor or e]local V,B=A(E.Text,s.Font,s.Size)local v=I("\084\101\120\116\076\097\098\101\108",{AutomaticSize=not V and Enum.AutomaticSize.X or nil,BackgroundTransparency=1,FontFace=s.Font;LayoutOrder=1,Size=UDim2.new(0,V and B.X or 0,1,0),Text=E.Text,TextColor3=d.Color,TextSize=s.Size,TextTransparency=d.Transparency})local p=D[S]local k,K=nil,nil if E.ReleaseText then k,K=A(E.ReleaseText,s.Font,s.Size)end local N=E.ReleaseText and I("\084\101\120\116\076\097\098\101\108",{AutomaticSize=not k and Enum.AutomaticSize.X or nil;BackgroundTransparency=1;FontFace=s.Font;LayoutOrder=2;Size=UDim2.new(0,k and K.X or 0,1,0);Text=E.ReleaseText,TextColor3=p.Color,TextSize=s.Size;TextTransparency=p.Transparency})or nil local Q=B.X if k then Q+=K.X+8 end local L=I("\070\114\097\109\101",{BackgroundTransparency=1,LayoutOrder=2;Size=UDim2.new(0,Q,1,0)},{Label=v;ReleaseLabel=N;Layout=I("\085\073\076\105\115\116\076\097\121\111\117\116",{FillDirection=Enum.FillDirection.Horizontal,Padding=UDim.new(0,8)})})local f=E.Icon and D[E.Icon]local W=nil if f then local D=f.ImageRectSize==Vector2.new()and Vector2.new(16,16)or f.ImageRectSize W=UDim2.fromOffset(math.clamp(D.X,0,36),math.clamp(D.Y,0,36))else W=UDim2.fromOffset(0,0)end local H=f and I("\073\109\097\103\101\076\097\098\101\108",{AnchorPoint=Vector2.new(.5,.5);BackgroundTransparency=1,Image=f.Image;ImageRectOffset=f.ImageRectOffset,ImageRectSize=f.ImageRectSize,Position=UDim2.fromScale(.5,.5);ResampleMode=f.ResampleMode;Size=W,ImageColor3=f.ImageColor3;ImageTransparency=f.ImageTransparency})local i=H and I("\070\114\097\109\101",{AnchorPoint=Vector2.new(.5,.5),BackgroundTransparency=1,Position=UDim2.new(0,24,.5,0),Size=UDim2.new(0,16,1,0)},H)local G=UDim2.new(0,(Q+(H and 32 or 0))+12,1,0)local r=I("\070\114\097\109\101",{BackgroundTransparency=1;LayoutOrder=2;Size=G},{Icon=i;TextConatainer=L;Layout=I("\085\073\076\105\115\116\076\097\121\111\117\116",{FillDirection=Enum.FillDirection.Horizontal;Padding=UDim.new(0,16)});Padding=I("\085\073\080\097\100\100\105\110\103",{PaddingLeft=UDim.new(0,12)})})local z=I("\070\114\097\109\101",{BackgroundTransparency=1,Size=G+UDim2.fromOffset(4,0)},{IconAndTitle=r;Padding=I("\085\073\080\097\100\100\105\110\103",{PaddingLeft=UDim.new(0,4)})})local Y=0 local P={}if E.OnClose then P.Close=I(o,{AlwaysShow=E.AlwaysShowClose,Width=E.CaptionButtonWidth,[w.Event.Activated]=E.OnClose})end local c=I("\070\114\097\109\101",{AnchorPoint=Vector2.new(1,0),BackgroundTransparency=1;Position=UDim2.fromScale(1,0),Size=UDim2.new(0,Y,1,0)},P)return I(R,{BackgroundColor=D[E.BackgroundColor];CornerRadius=UDim.new(0,D["\115\116\121\108\101\115\047\067\111\114\110\101\114\082\097\100\105\117\115\047\068\101\102\097\117\108\116\047\079\117\116\101\114"]),LayoutOrder=E.LayoutOrder,Size=UDim2.new(1,0,0,E.Height);ShowTopLeftCorner=true;ShowTopRightCorner=true,Native=E.Native},{Parts=z;CaptionButtonContainer=c})end)end return k
-- TitleBar: The top bar of a window component

local Winro = script.Parent.Parent.Parent.Parent
local Packages = Winro.Parent

local Theme = require(Winro.Theme)
local WithTheme = Theme.WithTheme

local Validators = Winro.Validators
local StyleValidator = require(Validators.StyleValidator)

local t = require(Packages.t)
local Roact = require(Packages.Roact)
local new = Roact.createElement


local GetTextSize = require(Winro.Utility.GetTextSize)
local RoundedSurface = require(Winro.App.Surface.RoundedSurface)

local TitleBarRoot = script.Parent
local CaptionClose = require(TitleBarRoot.CaptionClose)

local TITLEBAR_LABEL_FONT_STYLE = 'fonts/Caption'
local TITLEBAR_LABEL_TEXT_STYLE = 'colors/Fill_Color/Text/Primary'
local TITLEBAR_RELEASE_TEXT_STYLE = 'colors/Fill_Color/Text/Secondary'


local TitleBar = Roact.PureComponent:extend(script.Name)

TitleBar.defaultProps = {
	Height = 32, --- @defaultProp
	Text = 'TitleBar', --- @defaultProp
	CaptionButtonWidth = 48, --- @defaultProp

	BackgroundColor = {
		Color = Color3.new(),
		Transparency = 1,
	}, --- @defaultProp
}

TitleBar.validateProps = t.strictInterface({

	--- @prop @optional AlwaysShowClose boolean Always show the close button
	AlwaysShowClose = t.optional(t.boolean),
	
	--- @prop @optional CaptionButtonWidth number Caption Button's width
	CaptionButtonWidth = t.optional(t.number),

	--- @prop @optional Text string The TitleBar's text
	Text = t.optional(t.string),

	--- @prop @optional LayoutOrder number The TitleBar's layout order
	LayoutOrder = t.optional(t.number),

	--- @prop @optional Icon string|table The TitleBar's icon
	Icon = t.optional(StyleValidator),

	--- @prop @optional ReleaseText string The TitleBar's release text
	ReleaseText = t.optional(t.string),

	--- @prop @optional @style TextColor string|table The Label's text fill
	TextColor = t.optional(StyleValidator),

	--- @prop @optional @style BackgroundColor string|table The TitleBars's background fill
	BackgroundColor = t.optional(StyleValidator),

	--- @prop @optional Height number positive The TitleBar's height, in pixels
	Height = t.optional(t.numberPositive),

	--- @prop @optional OnClose function The function to call when the close button is pressed
	OnClose = t.optional(t.callback),

	--- @prop @optional Native table Native props
	Native = t.optional(t.table)
})

function TitleBar:render()
	local props = self.props

	return WithTheme(function(Theme)
		
		-- ////////// Label

		local LabelFontStyle = Theme[TITLEBAR_LABEL_FONT_STYLE]
		local LabelTextStyle = Theme[props.TextColor or TITLEBAR_LABEL_TEXT_STYLE]

		local GotLabelTextSize, LabelTextSize = GetTextSize(props.Text, LabelFontStyle.Font, LabelFontStyle.Size)

		local Label = new('TextLabel', {
			AutomaticSize = (not GotLabelTextSize) and Enum.AutomaticSize.X or nil, -- Fallback
			BackgroundTransparency = 1,
			FontFace = LabelFontStyle.Font,
			LayoutOrder = 1,
			Size = UDim2.new(0, GotLabelTextSize and LabelTextSize.X or 0, 1, 0),
			Text = props.Text,
			TextColor3 = LabelTextStyle.Color,
			TextSize = LabelFontStyle.Size,
			TextTransparency = LabelTextStyle.Transparency,
		})

		-- ////////// Release Label

		local ReleaseLabelTextStyle = Theme[TITLEBAR_RELEASE_TEXT_STYLE]

		local GotReleaseLabelTextSize, ReleaseLabelTextSize = nil, nil

		if props.ReleaseText then
			GotReleaseLabelTextSize, ReleaseLabelTextSize = GetTextSize(props.ReleaseText, LabelFontStyle.Font, LabelFontStyle.Size)
		end

		local ReleaseLabel = props.ReleaseText and new('TextLabel', {
			AutomaticSize = (not GotReleaseLabelTextSize) and Enum.AutomaticSize.X or nil, -- Fallback
			BackgroundTransparency = 1,
			FontFace = LabelFontStyle.Font,
			LayoutOrder = 2,
			Size = UDim2.new(0, GotReleaseLabelTextSize and ReleaseLabelTextSize.X or 0, 1, 0),
			Text = props.ReleaseText,
			TextColor3 = ReleaseLabelTextStyle.Color,
			TextSize = LabelFontStyle.Size,
			TextTransparency = ReleaseLabelTextStyle.Transparency,
		}) or nil

		-- ////////// Text Container

		local TextContainerWidth = LabelTextSize.X

		if GotReleaseLabelTextSize then
			TextContainerWidth += ReleaseLabelTextSize.X + 8 -- Account for 8px layout padding
		end

		local TextContainer = new('Frame', {
			BackgroundTransparency = 1,
			LayoutOrder = 2,
			Size = UDim2.new(0, TextContainerWidth, 1, 0),
		}, {
			Label = Label,
			ReleaseLabel = ReleaseLabel,

			Layout = new('UIListLayout', {
				FillDirection = Enum.FillDirection.Horizontal,
				Padding = UDim.new(0, 8),
			}),
		})

		-- ////////// Icon

		local IconImage = props.Icon and Theme[props.Icon]
		local IconImageSize = nil

		if IconImage then
			local IconImageRectSize = IconImage.ImageRectSize == Vector2.new() and Vector2.new(16, 16) or IconImage.ImageRectSize
			IconImageSize = UDim2.fromOffset(
				math.clamp(IconImageRectSize.X, 0, 9*4),
				math.clamp(IconImageRectSize.Y, 0, 9*4)
			)
		else
			IconImageSize = UDim2.fromOffset(0, 0)
		end
		
		local IconImage = IconImage and new('ImageLabel', {
			AnchorPoint = Vector2.new(0.5, 0.5),
			BackgroundTransparency = 1,
			Image = IconImage.Image,
			ImageRectOffset = IconImage.ImageRectOffset,
			ImageRectSize = IconImage.ImageRectSize,
			Position = UDim2.fromScale(0.5, 0.5),
			ResampleMode = IconImage.ResampleMode,
			Size = IconImageSize,
			ImageColor3 = IconImage.ImageColor3,
			ImageTransparency = IconImage.ImageTransparency,
		})

		local Icon = IconImage and new('Frame', {
			AnchorPoint = Vector2.new(0.5, 0.5),
			BackgroundTransparency = 1,
			Position = UDim2.new(0, 16 + 8, 0.5, 0),
			Size = UDim2.new(0, 16, 1, 0),
		}, IconImage)

		-- ////////// Icon and Title

		local TotalPartsSize = UDim2.new(0, TextContainerWidth + (IconImage and 16 * 2 or 0) + 12, 1, 0) -- Account for 12px left padding, Account for additional 16px padding if an icon is present

		local IconAndTitle = new('Frame', {
			BackgroundTransparency = 1,
			LayoutOrder = 2,
			Size = TotalPartsSize,
		}, {
			Icon = Icon,
			TextConatainer = TextContainer,

			Layout = new('UIListLayout', {
				FillDirection = Enum.FillDirection.Horizontal,
				Padding = UDim.new(0, 16),
			}),
			Padding = new('UIPadding', {
				PaddingLeft = UDim.new(0, 12),
			}),
		})

		-- ////////// TitleBar parts

		local Parts = new('Frame', {
			BackgroundTransparency = 1,
			Size = TotalPartsSize + UDim2.fromOffset(4, 0), -- Account for 4px left padding
		}, {
			IconAndTitle = IconAndTitle,

			Padding = new('UIPadding', {
				PaddingLeft = UDim.new(0, 4),
			}),
		})

		-- ////////// Caption buttons

		local CaptionContainerWidth = 0
		local CaptionButtons = {}

		if props.OnClose then
			CaptionButtons.Close = new(CaptionClose, {
				AlwaysShow = props.AlwaysShowClose,
				Width = props.CaptionButtonWidth,
				[Roact.Event.Activated] = props.OnClose,
			})
		end

		local CaptionButtonContainer = new('Frame', {
			AnchorPoint = Vector2.new(1, 0),
			BackgroundTransparency = 1,
			Position = UDim2.fromScale(1, 0),
			Size = UDim2.new(0, CaptionContainerWidth, 1, 0),
		}, CaptionButtons)

		-- ////////// TitleBar
		return new(RoundedSurface, {
			BackgroundColor = Theme[props.BackgroundColor],
			CornerRadius = UDim.new(0, Theme['styles/CornerRadius/Default/Outer']),
			LayoutOrder = props.LayoutOrder,
			Size = UDim2.new(1, 0, 0, props.Height),
			ShowTopLeftCorner = true,
			ShowTopRightCorner = true,
			Native = props.Native,
		}, {
			Parts = Parts,
			CaptionButtonContainer = CaptionButtonContainer,
		})
	end)
end

return TitleBar
