{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"c-sortable-3","type":"registry:block","title":"Sortable list of items with nested layout","description":"Sortable list of items with nested layout","dependencies":["sonner"],"registryDependencies":["card","@reui/sortable"],"files":[{"path":"c-sortable-3.tsx","type":"registry:block","content":"\"use client\"\n\nimport { useState } from \"react\"\nimport {\n  Sortable,\n  SortableItem,\n  SortableItemHandle,\n} from \"@/components/reui/sortable\"\nimport { toast } from \"sonner\"\n\nimport { Card, CardContent } from \"@/components/ui/card\"\nimport { IconPlaceholder } from \"@/app/(create)/components/icon-placeholder\"\n\ninterface OptionValue {\n  id: string\n  value: string\n}\n\ninterface OptionGroup {\n  id: string\n  name: string\n  values: OptionValue[]\n}\n\nconst defaultOptionGroups: OptionGroup[] = [\n  {\n    id: \"1\",\n    name: \"Colors\",\n    values: [\n      { id: \"1-1\", value: \"White\" },\n      { id: \"1-2\", value: \"Black\" },\n      { id: \"1-3\", value: \"Grey\" },\n      { id: \"1-4\", value: \"Green\" },\n    ],\n  },\n  {\n    id: \"2\",\n    name: \"Sizes\",\n    values: [\n      { id: \"2-1\", value: \"Small\" },\n      { id: \"2-2\", value: \"Medium\" },\n      { id: \"2-3\", value: \"Large\" },\n    ],\n  },\n  {\n    id: \"3\",\n    name: \"Materials\",\n    values: [\n      { id: \"3-1\", value: \"Cotton\" },\n      { id: \"3-2\", value: \"Polyester\" },\n      { id: \"3-3\", value: \"Wool\" },\n    ],\n  },\n]\n\nexport function Pattern() {\n  const [optionGroups, setOptionGroups] =\n    useState<OptionGroup[]>(defaultOptionGroups)\n\n  const handleParentReorder = (newGroups: OptionGroup[]) => {\n    setOptionGroups(newGroups)\n\n    toast.success(\"Option groups reordered successfully!\", {\n      description: `${newGroups.map((group, index) => `${index + 1}. ${group.name}`).join(\", \")}`,\n    })\n  }\n\n  const getParentValue = (group: OptionGroup) => group.id\n  const getChildValue = (value: OptionValue) => value.id\n\n  const handleChildReorder = (groupId: string, newValues: OptionValue[]) => {\n    setOptionGroups((prev) =>\n      prev.map((group) =>\n        group.id === groupId ? { ...group, values: newValues } : group\n      )\n    )\n\n    toast.success(\"Values reordered successfully!\", {\n      description: newValues\n        .map((value, index) => `${index + 1}. ${value.value}`)\n        .join(\", \"),\n    })\n  }\n\n  return (\n    <div className=\"mx-auto w-full max-w-sm space-y-6 p-6\">\n      <Sortable\n        value={optionGroups}\n        onValueChange={handleParentReorder}\n        getItemValue={getParentValue}\n        strategy=\"vertical\"\n        className=\"space-y-4\"\n      >\n        {optionGroups.map((group) => (\n          <SortableItem key={group.id} value={group.id}>\n            <Card className=\"p-2\">\n              <CardContent className=\"p-0\">\n                {/* Group Header */}\n                <div className=\"mb-2 flex items-center gap-2\">\n                  <SortableItemHandle className=\"text-muted-foreground hover:text-foreground cursor-grab\">\n                    <IconPlaceholder\n                      lucide=\"GripVerticalIcon\"\n                      tabler=\"IconGripVertical\"\n                      hugeicons=\"DragDropVerticalIcon\"\n                      phosphor=\"DotsSixVerticalIcon\"\n                      remixicon=\"RiDraggable\"\n                      className=\"h-4 w-4\"\n                    />\n                  </SortableItemHandle>\n                  <h3 className=\"text-sm font-semibold\">{group.name}</h3>\n                </div>\n\n                {/* Option Values - Child Level */}\n                <Sortable\n                  value={group.values}\n                  onValueChange={(newValues) =>\n                    handleChildReorder(group.id, newValues)\n                  }\n                  getItemValue={getChildValue}\n                  strategy=\"vertical\"\n                  className=\"space-y-2\"\n                >\n                  {group.values.map((value) => (\n                    <SortableItem key={value.id} value={value.id}>\n                      <div className=\"border-border rounded-md flex items-center gap-2 border p-1.5\">\n                        <SortableItemHandle className=\"text-muted-foreground hover:text-foreground cursor-grab\">\n                          <IconPlaceholder\n                            lucide=\"GripVerticalIcon\"\n                            tabler=\"IconGripVertical\"\n                            hugeicons=\"DragDropVerticalIcon\"\n                            phosphor=\"DotsSixVerticalIcon\"\n                            remixicon=\"RiDraggable\"\n                            className=\"h-4 w-4\"\n                          />\n                        </SortableItemHandle>\n                        <span className=\"flex-1 text-sm\">{value.value}</span>\n                      </div>\n                    </SortableItem>\n                  ))}\n                </Sortable>\n              </CardContent>\n            </Card>\n          </SortableItem>\n        ))}\n      </Sortable>\n    </div>\n  )\n}","target":"components/examples/c-sortable-3.tsx"}],"meta":{"order":3,"gridSize":1}}