function RxInstanceUtils.observeDescendants(h,L)assert(typeof(h)=="\073\110\115\116\097\110\099\101","\066\097\100 \112\097\114\101\110\116")assert(type(L)=="\102\117\110\099\116\105\111\110"or L==nil,"\066\097\100 \112\114\101\100\105\099\097\116\101")return Observable.new(function(x)local T=Maid.new()local m={}local function B(h)if not L or L(h)then m[h]=true x:Fire(h,true)end end T:GiveTask(h.DescendantAdded:Connect(B))T:GiveTask(h.DescendantRemoving:Connect(function(h)if m[h]then m[h]=nil x:Fire(h,false)end end))for h,L in pairs(h:GetDescendants())do B(L)end return T end)end
--[=[
	Observes all descendants that match a predicate

	@param parent Instance
	@param predicate ((value: Instance) -> boolean)? -- Optional filter
	@return Observable<Instance, boolean>
]=]
function RxInstanceUtils.observeDescendants(parent, predicate)
	assert(typeof(parent) == "Instance", "Bad parent")
	assert(type(predicate) == "function" or predicate == nil, "Bad predicate")

	return Observable.new(function(sub)
		local maid = Maid.new()
		local added = {}

		local function handleDescendant(child)
			if not predicate or predicate(child) then
				added[child] = true
				sub:Fire(child, true)
			end
		end

		maid:GiveTask(parent.DescendantAdded:Connect(handleDescendant))
		maid:GiveTask(parent.DescendantRemoving:Connect(function(child)
			if added[child] then
				added[child] = nil
				sub:Fire(child, false)
			end
		end))

		for _, descendant in pairs(parent:GetDescendants()) do
			handleDescendant(descendant)
		end

		return maid
	end)
end
