{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "css-gridlist",
  "type": "registry:ui",
  "title": "GridList",
  "dependencies": [
    "react-aria-components",
    "lucide-react"
  ],
  "registryDependencies": [
    "https://react-aria.adobe.com/registry/css-checkbox.json",
    "https://react-aria.adobe.com/registry/css-progresscircle.json"
  ],
  "files": [
    {
      "path": "components/ui/GridList.tsx",
      "type": "registry:ui",
      "content": "'use client';\nimport {\n  Button,\n  GridList as AriaGridList,\n  GridListItem as AriaGridListItem,\n  GridListLoadMoreItem as AriaGridListLoadMoreItem,\n  Text,\n  GridListSection,\n  GridListHeader,\n  type GridListItemProps,\n  type GridListProps,\n  type GridListLoadMoreItemProps\n} from 'react-aria-components/GridList';\nimport {Checkbox} from '@/registry/react-aria/ui/Checkbox';\nimport {GripVertical} from 'lucide-react';\nimport {ProgressCircle} from '@/registry/react-aria/ui/ProgressCircle';\nimport './GridList.css';\n\nexport function GridList<T>({children, layout = 'grid', ...props}: GridListProps<T>) {\n  return (\n    <AriaGridList {...props} layout={layout}>\n      {children}\n    </AriaGridList>\n  );\n}\n\nexport function GridListItem({\n  children,\n  ...props\n}: Omit<GridListItemProps, 'children'> & {\n  children?: React.ReactNode;\n}) {\n  let textValue = typeof children === 'string' ? children : undefined;\n  return (\n    <AriaGridListItem textValue={textValue} {...props}>\n      {({selectionMode, selectionBehavior, allowsDragging}) => (\n        <>\n          {/* Add elements for drag and drop and selection. */}\n          {allowsDragging && (\n            <Button slot=\"drag\">\n              <GripVertical size={16} />\n            </Button>\n          )}\n          {selectionMode === 'multiple' && selectionBehavior === 'toggle' && (\n            <Checkbox slot=\"selection\" />\n          )}\n          {children}\n        </>\n      )}\n    </AriaGridListItem>\n  );\n}\n\nexport function GridListLoadMoreItem(props: GridListLoadMoreItemProps) {\n  return (\n    <AriaGridListLoadMoreItem {...props}>\n      <ProgressCircle isIndeterminate aria-label=\"Loading more...\" />\n    </AriaGridListLoadMoreItem>\n  );\n}\n\nexport {GridListSection, GridListHeader, Text};\n"
    },
    {
      "path": "components/ui/GridList.css",
      "type": "registry:component",
      "content": "@import './theme.css';\n\n.react-aria-GridList {\n  justify-content: center;\n  gap: var(--spacing-4);\n  padding: var(--spacing-2);\n  scroll-padding: var(--spacing-2);\n  border-radius: var(--radius);\n  max-height: inherit;\n  overflow: auto;\n  forced-color-adjust: none;\n  outline: none;\n  width: 100%;\n  max-height: 500px;\n  min-height: 100px;\n  box-sizing: border-box;\n  --grid-item-size: 200px;\n\n  &:has(.react-aria-GridListSection) {\n    scroll-padding: 50px;\n  }\n\n  &[data-layout='grid']:not(:has(.react-aria-GridListSection)):not([data-empty]) {\n    display: grid;\n    grid-auto-rows: min-content;\n\n    &:not([data-orientation='horizontal']) {\n      grid-template-columns: repeat(auto-fit, minmax(100px, var(--grid-item-size)));\n    }\n  }\n\n  &[data-layout='grid'] > .react-aria-GridListSection {\n    grid-template-columns: repeat(auto-fit, minmax(100px, var(--grid-item-size)));\n    grid-auto-rows: min-content;\n  }\n\n  .react-aria-GridListSection:not(:first-child) {\n    margin-top: var(--spacing-4);\n  }\n\n  &[data-layout='stack'] > .react-aria-GridListSection {\n    grid-template-columns: auto;\n    align-items: center;\n  }\n\n  &[data-size='small'] {\n    --grid-item-size: 150px;\n  }\n\n  @media (width < 500px) {\n    &[data-layout='grid'] {\n      --grid-item-size: 150px;\n    }\n\n    &[data-layout='grid']:not(:has(.react-aria-GridListSection)) {\n      grid-template-columns: 1fr 1fr;\n    }\n  }\n\n  &[data-layout='stack']:not([data-empty]) {\n    display: grid;\n    grid-template-columns: auto;\n    align-items: center;\n\n    &[data-orientation='horizontal'] {\n      display: flex;\n      flex-direction: row;\n      justify-content: normal;\n\n      .react-aria-GridListItem {\n        flex-shrink: 0;\n        width: var(--grid-item-size);\n      }\n    }\n  }\n\n  &[data-layout='grid'][data-orientation='horizontal'] {\n    grid-auto-flow: column;\n    grid-template-rows: auto auto;\n    grid-template-columns: none;\n    grid-auto-columns: var(--grid-item-size);\n    justify-content: normal;\n    max-height: none;\n  }\n\n  &[data-focus-visible] {\n    outline: 2px solid var(--focus-ring-color);\n  }\n\n  &[data-empty] {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-style: italic;\n  }\n\n  &[data-drop-target] {\n    outline: 2px solid var(--highlight-background);\n    outline-offset: -1px;\n    background: var(--highlight-overlay);\n  }\n\n  .react-aria-DropIndicator {\n    display: none;\n    &[data-drop-target] {\n      display: block;\n      outline: 2px solid var(--highlight-background);\n      outline-offset: -1px;\n      background: var(--highlight-overlay);\n      border-radius: var(--radius);\n    }\n  }\n}\n\n.react-aria-GridListItem {\n  display: flex;\n  flex-direction: column;\n  gap: var(--spacing-2);\n  border-radius: var(--radius);\n  outline: none;\n  cursor: default;\n  color: var(--text-color);\n  font: var(--font-size) system-ui;\n  box-sizing: border-box;\n  padding-bottom: var(--spacing-4);\n  background: var(--overlay-background);\n  box-shadow: 0 2px 8px rgb(0 0 0 / 0.15);\n  min-width: 0;\n  max-width: 250px;\n  overflow: clip;\n  position: relative;\n  transform: translateZ(0);\n  transition-property: scale;\n  transition-duration: 200ms;\n  -webkit-tap-highlight-color: transparent;\n\n  &[data-focus-visible] {\n    outline: 2px solid var(--focus-ring-color);\n    outline-offset: 2px;\n  }\n\n  &[data-pressed] {\n    scale: 0.98;\n  }\n\n  &::after {\n    content: '';\n    position: absolute;\n    inset: 0;\n    pointer-events: none;\n    border-radius: inherit;\n    border: 2px solid light-dark(black, white);\n    outline: 2px solid light-dark(rgb(255 255 255 / 0.7), rgb(0 0 0 / 0.7));\n    outline-offset: -4px;\n    opacity: 0;\n    transition: opacity 200ms;\n  }\n\n  &[data-selected] {\n    &::after {\n      opacity: 1;\n    }\n  }\n\n  &[data-href] {\n    cursor: pointer;\n  }\n\n  &[data-disabled] {\n    color: var(--text-color-disabled);\n  }\n\n  .react-aria-CheckboxField {\n    position: absolute;\n    top: var(--spacing-4);\n    inset-inline-start: var(--spacing-4);\n\n    .react-aria-CheckboxButton {\n      --focus-ring-color: var(--highlight-foreground);\n      --checkmark-color: light-dark(white, black);\n\n      .indicator {\n        --indicator-border: light-dark(rgb(0 0 0 / 0.9), rgb(255 255 255 / 0.7));\n\n        @media (forced-colors: active) {\n          --indicator-border: ButtonBorder;\n        }\n      }\n\n      &[data-selected] .indicator {\n        --indicator-color: light-dark(black, var(--highlight-foreground));\n        --indicator-shadow: transparent;\n\n        @media (forced-colors: active) {\n          --indicator-color: Highlight;\n          --checkmark-color: HighlightText;\n        }\n      }\n\n      &::before {\n        content: '';\n        position: absolute;\n        inset: -4px;\n        background: light-dark(rgb(255 255 255 / 0.51), rgb(0 0 0 / 0.56));\n        box-shadow: rgba(0, 0, 0, 0.24) 0px 2px 8px 0px;\n        border-radius: var(--radius);\n      }\n    }\n  }\n\n  img {\n    width: 100%;\n    height: var(--grid-item-size);\n    object-fit: cover;\n    padding-bottom: var(--spacing-2);\n    -webkit-user-drag: none;\n    -webkit-touch-callout: none;\n    flex-shrink: 0;\n  }\n\n  .react-aria-Text {\n    padding: 0 var(--spacing-4);\n    display: -webkit-box;\n    overflow: hidden;\n    -webkit-box-orient: vertical;\n    -webkit-line-clamp: 3;\n\n    &:not([slot]) {\n      font-weight: 500;\n    }\n\n    &[slot='description'] {\n      font-size: var(--font-size-sm);\n    }\n  }\n\n  .react-aria-Button[slot='drag'] {\n    all: unset;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    position: absolute;\n    bottom: var(--spacing-2);\n    inset-inline-end: var(--spacing-2);\n    border-radius: var(--radius);\n    color: var(--text-color);\n\n    &[data-focus-visible] {\n      border-radius: 4px;\n      outline: 2px solid var(--focus-ring-color);\n    }\n  }\n\n  &[data-dragging] {\n    opacity: 0.6;\n  }\n\n  &[data-drop-target] {\n    &::before {\n      content: '';\n      position: absolute;\n      inset: 0;\n      border-radius: inherit;\n      z-index: 5;\n      outline: 2px solid var(--highlight-background);\n      outline-offset: -2px;\n      background: var(--highlight-overlay);\n    }\n  }\n}\n\n.react-aria-GridListLoadingIndicator {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  height: 24px;\n  width: 100%;\n}\n\n.react-aria-GridListSection {\n  display: grid;\n  justify-content: center;\n  gap: var(--spacing-4);\n  color: var(--text-color);\n  width: 100%;\n\n  > .react-aria-GridListHeader {\n    grid-column: 1 / -1;\n  }\n}\n\n.react-aria-GridListHeader {\n  position: sticky;\n  z-index: 2;\n  top: calc(var(--spacing-2) * -1);\n  font-size: var(--font-size-lg);\n  font-weight: 500;\n  background: var(--gray-100);\n  border: 0.5px solid var(--gray-400);\n  cursor: default;\n  user-select: none;\n  box-shadow:\n    inset 0px 1px 0px white,\n    inset 0px -4px 8px var(--gray-200);\n  border-radius: var(--radius);\n  padding: var(--spacing-1) var(--spacing-4);\n\n  @media (prefers-color-scheme: dark) {\n    box-shadow: inset 0px 4px 8px var(--gray-200);\n  }\n}\n"
    },
    {
      "path": "components/ui/theme.css",
      "type": "registry:component",
      "content": "/* colors */\n:root {\n  /* Change this variable to set the theme color for all components. */\n  /* You can use the below presets, or choose a custom color. */\n  --tint: var(--indigo);\n\n  /* theme colors */\n  /* lightness channel is only used as a multiplier for chroma (see below) */\n  --gray: oklch(0.5 0 0);\n  --red: oklch(0.6 0.181447 27.0726);\n  --orange: oklch(0.7 0.150492 54);\n  --yellow: oklch(0.8 0.128516 73.8032);\n  --turquoise: oklch(0.5 0.081146 205.114);\n  --cyan: oklch(0.4 0.142107 243.926);\n  --green: oklch(0.5 0.121276 155.372);\n  --blue: oklch(0.5 0.22049 266.315);\n  --indigo: oklch(1 0.25049 284.23);\n  --purple: oklch(0.7 0.223324 302);\n  --pink: oklch(0.6 0.177717 347.813);\n\n  /** tint color scale */\n  --tint-100: oklch(from var(--tint) var(--lightness-100) var(--chroma-100) h);\n  --tint-200: oklch(from var(--tint) var(--lightness-200) var(--chroma-200) h);\n  --tint-300: oklch(from var(--tint) var(--lightness-300) var(--chroma-300) h);\n  --tint-400: oklch(from var(--tint) var(--lightness-400) var(--chroma-400) h);\n  --tint-500: oklch(from var(--tint) var(--lightness-500) var(--chroma-500) h);\n  --tint-600: oklch(from var(--tint) var(--lightness-600) var(--chroma-600) h);\n  --tint-700: oklch(from var(--tint) var(--lightness-700) var(--chroma-700) h);\n  --tint-800: oklch(from var(--tint) var(--lightness-800) var(--chroma-800) h);\n  --tint-900: oklch(from var(--tint) var(--lightness-900) var(--chroma-900) h);\n  --tint-1000: oklch(from var(--tint) var(--lightness-1000) var(--chroma-1000) h);\n  --tint-1100: oklch(from var(--tint) var(--lightness-1100) var(--chroma-1100) h);\n  --tint-1200: oklch(from var(--tint) var(--lightness-1200) var(--chroma-1200) h);\n  --tint-1300: oklch(from var(--tint) var(--lightness-1300) var(--chroma-1300) h);\n  --tint-1400: oklch(from var(--tint) var(--lightness-1400) var(--chroma-1400) h);\n  --tint-1500: oklch(from var(--tint) var(--lightness-1500) var(--chroma-1500) h);\n  --tint-1600: oklch(from var(--tint) var(--lightness-1600) var(--chroma-1600) h);\n\n  /* gray scale */\n  --gray-100: oklch(from var(--gray) var(--lightness-100) c h);\n  --gray-200: oklch(from var(--gray) var(--lightness-200) c h);\n  --gray-300: oklch(from var(--gray) var(--lightness-300) c h);\n  --gray-400: oklch(from var(--gray) var(--lightness-400) c h);\n  --gray-500: oklch(from var(--gray) var(--lightness-500) c h);\n  --gray-600: oklch(from var(--gray) var(--lightness-600) c h);\n  --gray-700: oklch(from var(--gray) var(--lightness-700) c h);\n  --gray-800: oklch(from var(--gray) var(--lightness-800) c h);\n  --gray-900: oklch(from var(--gray) var(--lightness-900) c h);\n  --gray-1000: oklch(from var(--gray) var(--lightness-1000) c h);\n  --gray-1100: oklch(from var(--gray) var(--lightness-1100) c h);\n  --gray-1200: oklch(from var(--gray) var(--lightness-1200) c h);\n  --gray-1300: oklch(from var(--gray) var(--lightness-1300) c h);\n  --gray-1400: oklch(from var(--gray) var(--lightness-1400) c h);\n  --gray-1500: oklch(from var(--gray) var(--lightness-1500) c h);\n  --gray-1600: oklch(from var(--gray) var(--lightness-1600) c h);\n}\n\n/* light mode colors */\n:root {\n  --background-color: #f8f8f8;\n  --gray-50: #ffffff;\n\n  --lightness-100: 98.1187%;\n  --lightness-200: 95.2045%;\n  --lightness-300: 91.1434%;\n  --lightness-400: 85.1751%;\n  --lightness-500: 79.1773%;\n  --lightness-600: 72.3297%;\n  --lightness-700: 67.0121%;\n  --lightness-800: 62.3039%;\n  --lightness-900: 57.9699%;\n  --lightness-1000: 51.9076%;\n  --lightness-1100: 46.9058%;\n  --lightness-1200: 41.0821%;\n  --lightness-1300: 35.3616%;\n  --lightness-1400: 29.6725%;\n  --lightness-1500: 24.5366%;\n  --lightness-1600: 16.6959%;\n\n  /* lower chroma at low lightness levels */\n  --chroma-100: calc(l * c * 0.5);\n  --chroma-200: calc(l * c * 0.6);\n  --chroma-300: calc(l * c * 0.7);\n  --chroma-400: calc(l * c * 0.8);\n  --chroma-500: calc(l * c * 0.9);\n  --chroma-600: c;\n  --chroma-700: c;\n  --chroma-800: c;\n  --chroma-900: c;\n  --chroma-1000: c;\n  --chroma-1100: c;\n  --chroma-1200: c;\n  --chroma-1300: c;\n  --chroma-1400: c;\n  --chroma-1500: c;\n  --chroma-1600: c;\n\n  --highlight-hover: rgb(0 0 0 / 0.07);\n  --highlight-pressed: rgb(0 0 0 / 0.15);\n  --overlay-background: var(--gray-50);\n  --overlay-border: rgb(0 0 0 / 0.06);\n  --popover-shadow: 0 8px 20px rgba(0 0 0 / 0.12);\n}\n\n/* dark mode colors */\n@media (prefers-color-scheme: dark) {\n  :root {\n    --background-color: #1b1b1b;\n    --gray-50: oklch(22% 0 0);\n\n    --lightness-100: 29.6725%;\n    --lightness-200: 35.3616%;\n    --lightness-300: 41.0821%;\n    --lightness-400: 46.9058%;\n    --lightness-500: 51.9076%;\n    --lightness-600: 57.9699%;\n    --lightness-700: 56.1347%;\n    --lightness-800: 59.2866%;\n    --lightness-900: 62.3039%;\n    --lightness-1000: 67.0121%;\n    --lightness-1100: 72.3297%;\n    --lightness-1200: 79.1773%;\n    --lightness-1300: 85.1751%;\n    --lightness-1400: 91.1434%;\n    --lightness-1500: 95.2045%;\n    --lightness-1600: 100%;\n\n    --highlight-hover: rgb(255 255 255 / 0.1);\n    --highlight-pressed: rgb(255 255 255 / 0.2);\n    --overlay-background: var(--gray-100);\n    --overlay-border: rgb(255 255 255 / 0.2);\n    --popover-shadow: 0 8px 20px rgba(0 0 0 / 0.5);\n  }\n}\n\n/* Semantic colors */\n:root {\n  --focus-ring-color: var(--tint-1000);\n  --text-color: var(--gray-1200);\n  --text-color-hover: var(--gray-1300);\n  --text-color-disabled: var(--gray-600);\n  --text-color-placeholder: var(--gray-1000);\n  --link-color: var(--tint-1200);\n  --link-color-secondary: var(--gray-1200);\n  --link-color-pressed: var(--tint-1300);\n  --border-color: var(--gray-400);\n  --border-color-hover: var(--gray-500);\n  --border-color-disabled: var(--gray-300);\n  --field-text-color: var(--gray-1400);\n  --button-background: var(--tint-100);\n  --button-background-pressed: var(--tint-200);\n  /* these colors are the same between light and dark themes\n   * to ensure contrast with the foreground color */\n  --highlight-background: oklch(from var(--tint) 55% c h);\n  --highlight-background-pressed: oklch(from var(--tint) 50% c h);\n  --highlight-background-invalid: oklch(from var(--red) var(--lightness-900) c h);\n  --highlight-foreground: white;\n  --highlight-overlay: oklch(from var(--tint-1000) l c h / 15%);\n  --invalid-color: oklch(from var(--red) var(--lightness-1000) c h);\n  --field-background: var(--gray-50);\n}\n\n/* Windows high contrast mode overrides */\n@media (forced-colors: active) {\n  :root {\n    --background-color: Canvas;\n    --focus-ring-color: Highlight;\n    --text-color: ButtonText;\n    --text-color-hover: ButtonText;\n    --text-color-disabled: GrayText;\n    --text-color-placeholder: ButtonText;\n    --link-color: LinkText;\n    --link-color-secondary: LinkText;\n    --link-color-pressed: LinkText;\n    --border-color: ButtonBorder;\n    --border-color-hover: ButtonBorder;\n    --border-color-pressed: ButtonBorder;\n    --border-color-disabled: GrayText;\n    --field-background: Field;\n    --field-text-color: FieldText;\n    --overlay-background: Canvas;\n    --overlay-border: ButtonBorder;\n    --button-background: ButtonFace;\n    --button-background-pressed: ButtonFace;\n    --highlight-background: Highlight;\n    --highlight-background-pressed: Highlight;\n    --highlight-background-invalid: LinkText;\n    --highlight-foreground: HighlightText;\n    --invalid-color: LinkText;\n  }\n}\n\n/* typography and spacing scale */\n:root {\n  --font-size: 0.875rem; /* 14px */\n  --font-size-sm: 0.75rem; /* 12px */\n  --font-size-lg: 1rem; /* 16px */\n  --radius: 8px;\n  --radius-sm: 6px;\n  --radius-lg: 10px;\n  --radius-xl: 16px;\n  --spacing: 0.25rem; /* 4px */\n  --spacing-1: var(--spacing);\n  --spacing-2: calc(2 * var(--spacing));\n  --spacing-3: calc(3 * var(--spacing));\n  --spacing-4: calc(4 * var(--spacing));\n  --spacing-5: calc(5 * var(--spacing));\n  --spacing-6: calc(6 * var(--spacing));\n  --spacing-7: calc(7 * var(--spacing));\n  --spacing-8: calc(8 * var(--spacing));\n  --spacing-9: calc(9 * var(--spacing));\n  --spacing-10: calc(10 * var(--spacing));\n}\n\n/* Scale up hit targets on high resolution mobile devices. */\n@media (min-resolution: 200dpi) {\n  :root {\n    --spacing: calc(0.25rem * 1.25);\n    --font-size: 1.0625rem; /* 17px */\n    --font-size-sm: 0.9375rem; /* 15px */\n    --font-size-lg: 1.25rem; /* 20px */\n  }\n}\n"
    }
  ]
}
