{
  "name": "checkbox-group-multi-selection-demo",
  "type": "registry:example",
  "dependencies": [
    "@diceui/checkbox-group"
  ],
  "registryDependencies": [
    "checkbox-group"
  ],
  "files": [
    {
      "path": "examples/checkbox-group-multi-selection-demo.tsx",
      "type": "registry:example",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n  CheckboxGroup,\n  CheckboxGroupDescription,\n  CheckboxGroupItem,\n  CheckboxGroupLabel,\n  CheckboxGroupList,\n} from \"@/registry/bases/radix/ui/checkbox-group\";\n\nconst tricks = [\n  { label: \"Kickflip\", value: \"kickflip\" },\n  { label: \"Heelflip\", value: \"heelflip\" },\n  { label: \"Tre Flip\", value: \"tre-flip\" },\n  { label: \"Pizza Guy\", value: \"pizza-guy\" },\n  { label: \"FS 540\", value: \"fs-540\" },\n  { label: \"The 900\", value: \"the-900\" },\n];\n\nexport default function CheckboxGroupMultiSelectionDemo() {\n  const { value, onValueChange, onShiftKeyDown } = useShiftMultiSelect({\n    items: tricks,\n    getItemValue: (item) => item.value,\n  });\n\n  return (\n    <CheckboxGroup value={value} onValueChange={onValueChange}>\n      <CheckboxGroupLabel>Tricks</CheckboxGroupLabel>\n      <CheckboxGroupDescription>\n        Hold Shift and click to select multiple items\n      </CheckboxGroupDescription>\n      <CheckboxGroupList\n        className=\"mt-1\"\n        onKeyDown={onShiftKeyDown}\n        onKeyUp={onShiftKeyDown}\n      >\n        {tricks.map((trick) => (\n          <CheckboxGroupItem key={trick.value} value={trick.value}>\n            {trick.label}\n          </CheckboxGroupItem>\n        ))}\n      </CheckboxGroupList>\n    </CheckboxGroup>\n  );\n}\n\ninterface UseShiftMultiSelectProps<T> {\n  /** The items for selection. */\n  items: T[];\n\n  /** The value of the item. */\n  getItemValue: (item: T) => string;\n}\n\nfunction useShiftMultiSelect<T>({\n  items,\n  getItemValue,\n}: UseShiftMultiSelectProps<T>) {\n  const [selectedValues, setSelectedValues] = React.useState<string[]>([]);\n  const [lastSelected, setLastSelected] = React.useState<number | null>(null);\n  const isShiftPressedRef = React.useRef(false);\n\n  const onShiftKeyDown = React.useCallback(\n    (event: React.KeyboardEvent<HTMLElement>) => {\n      if (event.key === \"Shift\") {\n        isShiftPressedRef.current = event.type === \"keydown\";\n      }\n    },\n    [],\n  );\n\n  const onValueChange = React.useCallback(\n    (newValue: string[]) => {\n      // Handle single selection\n      if (!isShiftPressedRef.current || lastSelected === null) {\n        setSelectedValues(newValue);\n        const clickedValue =\n          newValue.find((v) => !selectedValues.includes(v)) ??\n          selectedValues.find((v) => !newValue.includes(v));\n        if (clickedValue) {\n          const newIndex = items.findIndex(\n            (item) => getItemValue(item) === clickedValue,\n          );\n          if (newIndex !== -1) {\n            setLastSelected(newIndex);\n          }\n        }\n        return;\n      }\n\n      // Find the currently clicked item\n      const clickedValue =\n        newValue.find((v) => !selectedValues.includes(v)) ??\n        selectedValues.find((v) => !newValue.includes(v));\n      if (!clickedValue) return;\n\n      const currentIndex = items.findIndex(\n        (item) => getItemValue(item) === clickedValue,\n      );\n      if (currentIndex === -1) return;\n\n      // Handle shift-click selection\n      const start = Math.min(lastSelected, currentIndex);\n      const end = Math.max(lastSelected, currentIndex);\n      const rangeValues = items\n        .slice(start, end + 1)\n        .map((item) => getItemValue(item));\n\n      const newSelectedValues = new Set(selectedValues);\n      const currentItem = items[currentIndex];\n      const isSelecting =\n        currentItem && !selectedValues.includes(getItemValue(currentItem));\n\n      for (const value of rangeValues) {\n        if (isSelecting) {\n          newSelectedValues.add(value);\n        } else {\n          newSelectedValues.delete(value);\n        }\n      }\n\n      setSelectedValues(Array.from(newSelectedValues));\n      setLastSelected(currentIndex);\n    },\n    [lastSelected, selectedValues, items, getItemValue],\n  );\n\n  return {\n    value: selectedValues,\n    onValueChange,\n    onShiftKeyDown,\n  };\n}\n",
      "target": ""
    }
  ]
}