starling-devex 0.1.2

Starling: a local dev orchestrator with a central daemon, shared named-URL proxy, and a k9s-style TUI (a Rust port of Tilt + portless)
import {
  createContext,
  PropsWithChildren,
  useContext,
  useMemo,
  useState,
} from "react"

/**
 * The ResourceSelection state keeps track of what resources are selected for bulk actions to be performed on them.
 */

export type ResourceSelectionContext = {
  selected: Set<string>
  isSelected: (resourceName: string) => boolean
  select: (...resourceNames: string[]) => void
  deselect: (...resourceNames: string[]) => void
  clearSelections: () => void
}

const ResourceSelectionContext = createContext<ResourceSelectionContext>({
  selected: new Set(),
  isSelected: (_resourceName: string) => {
    console.warn("Resource selections context is not set.")
    return false
  },
  select: (..._resourceNames: string[]) => {
    console.warn("Resource selections context is not set.")
  },
  deselect: (..._resourceNames: string[]) => {
    console.warn("Resource selections context is not set.")
  },
  clearSelections: () => {
    console.warn("Resource selections context is not set.")
  },
})

ResourceSelectionContext.displayName = "ResourceSelectionContext"

export function useResourceSelection(): ResourceSelectionContext {
  return useContext(ResourceSelectionContext)
}

export function ResourceSelectionProvider(
  props: PropsWithChildren<{ initialValuesForTesting?: string[] }>
) {
  const selections = new Set(props.initialValuesForTesting) || new Set()
  const [selectedResources, setSelectedResources] = useState(selections)

  const contextValue: ResourceSelectionContext = useMemo(() => {
    function isSelected(resourceName: string) {
      return selectedResources.has(resourceName)
    }

    function select(...resourceNames: string[]) {
      const newSelections = new Set<string>(selectedResources)
      resourceNames.forEach((name) => newSelections.add(name))
      return setSelectedResources(newSelections)
    }

    function deselect(...resourceNames: string[]) {
      const newSelections = new Set<string>(selectedResources)
      resourceNames.forEach((name) => newSelections.delete(name))
      return setSelectedResources(newSelections)
    }

    function clearSelections() {
      setSelectedResources(new Set())
    }
    return {
      selected: selectedResources,
      isSelected,
      select,
      deselect,
      clearSelections,
    }
  }, [selectedResources, setSelectedResources])

  return (
    <ResourceSelectionContext.Provider value={contextValue}>
      {props.children}
    </ResourceSelectionContext.Provider>
  )
}