{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "components-date-picker",
  "type": "registry:component",
  "title": "Date picker",
  "description": "A day or a span of days, chosen from a Calendar",
  "author": "sudo-kw <https://github.com/sudo-kw>",
  "dependencies": [
    "@gpuix/native@0.11.0",
    "@gpuix/react@0.11.0",
    "effect@4.1.2",
    "react@^19.2.4"
  ],
  "registryDependencies": [
    "https://gpuixui.sudokw.com/gpuix-icons.json",
    "https://gpuixui.sudokw.com/gpuix-motion.json",
    "https://gpuixui.sudokw.com/gpuix-primitives.json",
    "https://gpuixui.sudokw.com/gpuix-tokens.json",
    "https://gpuixui.sudokw.com/gpuix-tw.json"
  ],
  "files": [
    {
      "path": "packages/components/src/calendar.tsx",
      "target": "@ui/gpuixui/components/calendar.tsx",
      "type": "registry:component",
      "content": "/** @jsxImportSource @gpuix/react */\nimport type { KeyEvent, StyleDesc } from \"@gpuix/react\";\nimport { useGpuix } from \"@gpuix/react\";\nimport { Select, type SelectOption } from \"../primitives/select.js\";\nimport {\n  CALENDAR_DAY,\n  CALENDAR_GRID,\n  CALENDAR_MONTH,\n  CALENDAR_MONTH_LABEL,\n  CALENDAR_ROOT,\n  CALENDAR_WEEKDAY,\n  cn,\n} from \"../tw/index.js\";\nimport { Match, pipe } from \"effect\";\nimport * as Arr from \"effect/Array\";\nimport * as DateTime from \"effect/DateTime\";\nimport * as Option from \"effect/Option\";\nimport { useLayoutEffect, useRef } from \"react\";\nimport {\n  addMonths,\n  boundsOfMatchers,\n  calendarLabel,\n  canBrowseMonth,\n  clampToBounds,\n  dayAriaLabel,\n  dayInMonth,\n  formatIsoDay,\n  formatMonthLabel,\n  isDayAvailable,\n  isPainted,\n  isSameDay,\n  moveDay,\n  moveKeyOf,\n  monthGrid,\n  monthShortName,\n  monthWindow,\n  nextDay,\n  nextRange,\n  paintOf,\n  parseIsoDay,\n  startOfMonth,\n  todayUtc,\n  toggleDay,\n  unbounded,\n  visibleMonth,\n  weekdayLabels,\n  yearRange,\n  type CalendarMode,\n  type CaptionLayout,\n  type DayMatchers,\n  type DayRange,\n  type MonthCount,\n  type Selection,\n  type WeekStart,\n} from \"./calendar/logic.js\";\nimport { makeCalendarStore } from \"./calendar/store.js\";\nimport { IconButton } from \"./internal/button.js\";\nimport { Icon } from \"../icons/index.js\";\nimport { isActivation, isDismiss, swallowsDefault } from \"./internal/key.js\";\nimport { send, useLocalState, useLocalStore } from \"./internal/local-state.js\";\nimport { recipeStyle } from \"./internal/recipe.js\";\nimport { mergeStyles } from \"@gpuix/react/floating\";\nimport {\n  controlRing,\n  disabledOpacity,\n  useTheme,\n  type Theme,\n} from \"./internal/theme.js\";\n\nconst CELL = 34;\n\nconst DEFAULT_FROM_YEAR = 1900;\n\nconst DEFAULT_YEARS_AHEAD = 100;\n\nexport interface CalendarBaseProps {\n  readonly numberOfMonths?: MonthCount;\n\n  readonly showOutsideDays?: boolean;\n\n  readonly captionLayout?: CaptionLayout;\n\n  readonly weekStartsOn?: WeekStart;\n\n  readonly fromYear?: number;\n\n  readonly toYear?: number;\n\n  readonly disabled?: DayMatchers;\n\n  readonly today?: string;\n\n  readonly defaultMonth?: string;\n\n  readonly autoFocus?: boolean;\n\n  readonly label?: string;\n\n  readonly onDismiss?: () => void;\n\n  readonly className?: string;\n}\n\nexport interface SingleCalendarProps extends CalendarBaseProps {\n  readonly mode?: \"single\";\n  readonly selected?: string | null;\n  readonly onSelect?: (day: string | null) => void;\n}\n\nexport interface MultipleCalendarProps extends CalendarBaseProps {\n  readonly mode: \"multiple\";\n  readonly selected?: ReadonlyArray<string>;\n  readonly onSelect?: (days: ReadonlyArray<string>) => void;\n}\n\nexport interface RangeCalendarProps extends CalendarBaseProps {\n  readonly mode: \"range\";\n  readonly selected?: DayRange | null;\n  readonly onSelect?: (range: DayRange | null) => void;\n}\n\nexport type CalendarProps =\n  | SingleCalendarProps\n  | MultipleCalendarProps\n  | RangeCalendarProps;\n\ninterface SelectionAdapter {\n  readonly selection: Selection;\n  readonly select: (day: string) => void;\n}\n\nconst adapterOf = (props: CalendarProps): SelectionAdapter => {\n  if (props.mode === \"range\") {\n    const range = props.selected ?? null;\n    return {\n      selection: { mode: \"range\", range },\n      select: (day) => props.onSelect?.(nextRange(range, day)),\n    };\n  }\n  if (props.mode === \"multiple\") {\n    const days = props.selected ?? [];\n    return {\n      selection: { mode: \"multiple\", days },\n      select: (day) => props.onSelect?.(toggleDay(days, day)),\n    };\n  }\n  const day = props.selected ?? null;\n  return {\n    selection: { mode: \"single\", day },\n    select: (next) => props.onSelect?.(nextDay(day, next)),\n  };\n};\n\nconst anchorOf = (selection: Selection, today: DateTime.Utc): DateTime.Utc =>\n  pipe(\n    Match.value(selection).pipe(\n      Match.when({ mode: \"single\" }, (current) =>\n        Option.flatMap(Option.fromNullishOr(current.day), parseIsoDay),\n      ),\n      Match.when({ mode: \"multiple\" }, (current) =>\n        Option.flatMap(Arr.head(current.days), parseIsoDay),\n      ),\n      Match.when({ mode: \"range\" }, (current) =>\n        Option.flatMap(Option.fromNullishOr(current.range?.from), parseIsoDay),\n      ),\n      Match.exhaustive,\n    ),\n    Option.getOrElse(() => today),\n  );\n\nconst monthIndexOf = (value: DateTime.Utc): string =>\n  String(DateTime.toPartsUtc(value).month);\n\nconst Caption = ({\n  month,\n  layout,\n  months,\n  years,\n  onMonth,\n  onYear,\n  testId,\n}: {\n  readonly month: DateTime.Utc;\n  readonly layout: CaptionLayout;\n  readonly months: ReadonlyArray<SelectOption>;\n  readonly years: ReadonlyArray<SelectOption>;\n  readonly onMonth: (month: number) => void;\n  readonly onYear: (year: number) => void;\n  readonly testId: string;\n}) => {\n  const theme = useTheme();\n  return (\n    <div\n      style={{\n        display: \"flex\",\n        flexDirection: \"row\",\n        alignItems: \"center\",\n        justifyContent: \"center\",\n        gap: theme.spacing.xs,\n        minHeight: CELL,\n      }}\n    >\n      {layout === \"dropdown\" ? (\n        <>\n          <Select\n            label=\"Month\"\n            options={months}\n            value={monthIndexOf(month)}\n            onValueChange={(next) => onMonth(Number(next))}\n            triggerTestId={`${testId}-select`}\n            itemTestId={(value) => `${testId}-month-${value}`}\n            size=\"sm\"\n          />\n          <Select\n            label=\"Year\"\n            options={years}\n            value={String(DateTime.toPartsUtc(month).year)}\n            onValueChange={(next) => onYear(Number(next))}\n            triggerTestId={`${testId}-year`}\n            itemTestId={(value) => `${testId}-year-${value}`}\n            size=\"sm\"\n          />\n        </>\n      ) : (\n        <text testId={testId} style={recipeStyle(CALENDAR_MONTH_LABEL, theme)}>\n          {formatMonthLabel(month)}\n        </text>\n      )}\n    </div>\n  );\n};\n\nconst cellStyle = (\n  theme: Theme,\n  paint: ReturnType<typeof paintOf>,\n  outside: boolean,\n  today: boolean,\n  available: boolean,\n): StyleDesc => ({\n  width: CELL,\n  height: CELL,\n  backgroundColor: isPainted(paint)\n    ? theme.colors.primary\n    : paint === \"range-middle\"\n      ? theme.colors.muted\n      : undefined,\n  color: isPainted(paint)\n    ? theme.colors.primaryForeground\n    : paint === \"range-middle\"\n      ? theme.colors.foreground\n      : available\n        ? outside\n          ? theme.colors.mutedForeground\n          : theme.colors.foreground\n        : theme.colors.mutedForeground,\n  borderWidth: today && !isPainted(paint) ? theme.borderWidth.thin : undefined,\n  borderColor: today ? theme.colors.primary : undefined,\n  cursor: available ? \"pointer\" : \"not-allowed\",\n  opacity: available ? undefined : disabledOpacity,\n  hover:\n    isPainted(paint) || !available\n      ? undefined\n      : { backgroundColor: theme.colors.hover },\n  ...controlRing(theme, { disabled: !available }),\n});\n\nexport const Calendar = (props: CalendarProps) => {\n  const theme = useTheme();\n  const renderer = useGpuix().renderer;\n  const {\n    numberOfMonths = 1,\n    showOutsideDays = true,\n    captionLayout = \"label\",\n    weekStartsOn = 1,\n    label = \"Calendar\",\n    autoFocus = false,\n    onDismiss,\n  } = props;\n  const today = pipe(\n    Option.flatMap(Option.fromNullishOr(props.today), parseIsoDay),\n    Option.getOrElse(() => todayUtc(DateTime.nowUnsafe())),\n  );\n  const bounds = Option.match(Option.fromNullishOr(props.disabled), {\n    onNone: () => unbounded,\n    onSome: boundsOfMatchers,\n  });\n  const adapter = adapterOf(props);\n  const { selection, select } = adapter;\n  const anchor = clampToBounds(anchorOf(selection, today), bounds);\n  const initialMonth = pipe(\n    Option.flatMap(Option.fromNullishOr(props.defaultMonth), parseIsoDay),\n    Option.getOrElse(() => startOfMonth(anchor)),\n  );\n  const store = useLocalStore(\n    makeCalendarStore({\n      month: visibleMonth(startOfMonth(initialMonth), numberOfMonths, anchor),\n      focus: anchor,\n      count: numberOfMonths,\n      pending: autoFocus,\n    }),\n  );\n  const view = useLocalState(store.local);\n  const cells = useRef<Record<string, number>>({});\n  const months = monthWindow(view.month, numberOfMonths);\n  const year = DateTime.toPartsUtc(today).year;\n\n  const fromYear =\n    props.fromYear ??\n    Math.max(\n      DEFAULT_FROM_YEAR,\n      Option.match(bounds.min, {\n        onNone: () => Number.NEGATIVE_INFINITY,\n        onSome: (min) => DateTime.toPartsUtc(min).year,\n      }),\n    );\n  const toYear =\n    props.toYear ??\n    Math.min(\n      year + DEFAULT_YEARS_AHEAD,\n      Option.match(bounds.max, {\n        onNone: () => Number.POSITIVE_INFINITY,\n        onSome: (max) => DateTime.toPartsUtc(max).year,\n      }),\n    );\n\n  const monthFocus = (month: DateTime.Utc): DateTime.Utc =>\n    clampToBounds(dayInMonth(view.focus, month), bounds);\n\n  useLayoutEffect(() => {\n    if (!view.pending) return;\n    send(store.settle);\n    const panel = Arr.findFirstIndex(months, (month) =>\n      isSameDay(startOfMonth(month), startOfMonth(view.focus)),\n    );\n    const key = `${Option.getOrElse(panel, () => 0)}-${formatIsoDay(view.focus)}`;\n    const id = cells.current[key];\n    if (id !== undefined) renderer?.focusElement?.(id);\n  }, [view, months, renderer, store]);\n\n  const movement = (event: KeyEvent): void => {\n    if (swallowsDefault(event, \"down\")) event.preventDefault();\n    if (isDismiss(event) && onDismiss !== undefined) {\n      onDismiss();\n      return;\n    }\n    pipe(\n      moveKeyOf(event.key ?? \"\"),\n      Option.match({\n        onNone: () => undefined,\n        onSome: (key) => {\n          event.preventDefault();\n          send(\n            store.focusDay(\n              clampToBounds(\n                moveDay(\n                  view.focus,\n                  { key, year: event.modifiers?.shift === true },\n                  {\n                    weekStartsOn,\n                    viewMonth: view.month,\n                    months: numberOfMonths,\n                    showOutsideDays,\n                    bounds,\n                    matchers: props.disabled,\n                    fromYear,\n                    toYear,\n                  },\n                ),\n                bounds,\n              ),\n            ),\n          );\n        },\n      }),\n    );\n  };\n\n  const page = (direction: -1 | 1): void => {\n    const next = addMonths(view.month, direction);\n    send(store.show(next, monthFocus(next)));\n  };\n\n  const monthOptions: ReadonlyArray<SelectOption> = Arr.map(\n    Arr.range(1, 12),\n    (index) => ({ value: String(index), label: monthShortName(index) }),\n  );\n  const yearOptions: ReadonlyArray<SelectOption> = Arr.map(\n    yearRange(fromYear, toYear),\n    (year) => ({ value: String(year), label: String(year) }),\n  );\n\n  return (\n    <div\n      data-calendar=\"\"\n      aria-label={calendarLabel(label, selection)}\n      role=\"group\"\n      onKeyDown={movement}\n      style={mergeStyles(\n        recipeStyle(cn(CALENDAR_ROOT, props.className), theme),\n        {\n          gap: theme.spacing.md,\n        },\n      )}\n    >\n      {Arr.map(months, (month, index) => {\n        const grid = monthGrid(month, weekStartsOn, showOutsideDays);\n        return (\n          <div\n            key={formatIsoDay(month)}\n            style={recipeStyle(CALENDAR_MONTH, theme)}\n          >\n            <div\n              style={{\n                display: \"flex\",\n                flexDirection: \"row\",\n                alignItems: \"center\",\n                justifyContent: \"space-between\",\n                gap: theme.spacing.xs,\n              }}\n            >\n              {index === 0 ? (\n                <IconButton\n                  label=\"Previous month\"\n                  size=\"sm\"\n                  testId=\"date-prev\"\n                  disabled={!canBrowseMonth(month, -1, bounds)}\n                  onClick={() => page(-1)}\n                >\n                  <Icon\n                    name=\"chevron-left\"\n                    size=\"md\"\n                    color={theme.colors.foreground}\n                  />\n                </IconButton>\n              ) : (\n                <div style={{ width: CELL }} />\n              )}\n              <Caption\n                month={month}\n                layout={captionLayout}\n                months={monthOptions}\n                years={yearOptions}\n                testId={index === 0 ? \"date-month\" : `date-month-${index}`}\n                onMonth={(next) => {\n                  const target = addMonths(\n                    startOfMonth(month),\n                    next - DateTime.toPartsUtc(month).month,\n                  );\n                  send(store.show(target, monthFocus(target)));\n                }}\n                onYear={(year) => {\n                  const target = addMonths(\n                    startOfMonth(month),\n                    (year - DateTime.toPartsUtc(month).year) * 12,\n                  );\n                  send(store.show(target, monthFocus(target)));\n                }}\n              />\n              {index === numberOfMonths - 1 ? (\n                <IconButton\n                  label=\"Next month\"\n                  size=\"sm\"\n                  testId=\"date-next\"\n                  disabled={!canBrowseMonth(month, 1, bounds)}\n                  onClick={() => page(1)}\n                >\n                  <Icon\n                    name=\"chevron-right\"\n                    size=\"md\"\n                    color={theme.colors.foreground}\n                  />\n                </IconButton>\n              ) : (\n                <div style={{ width: CELL }} />\n              )}\n            </div>\n            <div\n              role=\"grid\"\n              aria-label={calendarLabel(\n                `${label}, ${formatMonthLabel(month)}`,\n                selection,\n              )}\n              style={recipeStyle(CALENDAR_GRID, theme)}\n            >\n              <div role=\"row\" style={{ display: \"flex\", flexDirection: \"row\" }}>\n                {Arr.map(weekdayLabels(weekStartsOn), (name) => (\n                  <text\n                    key={name}\n                    role=\"columnheader\"\n                    aria-label={name}\n                    style={mergeStyles(recipeStyle(CALENDAR_WEEKDAY, theme), {\n                      width: CELL,\n                    })}\n                  >\n                    {name}\n                  </text>\n                ))}\n              </div>\n              {Arr.map(grid, (week, weekIndex) => (\n                <div\n                  key={weekIndex}\n                  role=\"row\"\n                  style={{ display: \"flex\", flexDirection: \"row\" }}\n                >\n                  {Arr.map(week, (cell, dayIndex) =>\n                    Option.match(cell, {\n                      onNone: () => (\n                        <div\n                          key={dayIndex}\n                          style={{ width: CELL, height: CELL }}\n                        />\n                      ),\n                      onSome: (day) => {\n                        const iso = formatIsoDay(day);\n                        const available = isDayAvailable(\n                          day,\n                          bounds,\n                          props.disabled,\n                        );\n                        const paint = paintOf(selection, iso);\n                        const focused = isSameDay(day, view.focus);\n                        const panel = Arr.findFirstIndex(months, (entry) =>\n                          isSameDay(startOfMonth(entry), startOfMonth(day)),\n                        );\n                        const tabbable =\n                          focused && Option.getOrElse(panel, () => 0) === index;\n                        return (\n                          <div\n                            key={`${index}-${iso}`}\n                            role=\"gridcell\"\n                            aria-label={dayAriaLabel(day, paint, available)}\n                            aria-selected={paint !== \"none\"}\n                            tabIndex={tabbable ? 0 : -1}\n                            ref={(instance) => {\n                              const key = `${index}-${iso}`;\n                              if (instance === null) delete cells.current[key];\n                              else cells.current[key] = instance.id;\n                            }}\n                            testId={`date-day-${iso}`}\n                            onClick={\n                              available\n                                ? () => {\n                                    select(iso);\n                                    send(store.visited(day));\n                                  }\n                                : undefined\n                            }\n                            onFocus={() => send(store.visited(day))}\n                            onKeyDown={(event: KeyEvent) => {\n                              if (swallowsDefault(event, \"down\"))\n                                event.preventDefault();\n                              if (available && isActivation(event, \"down\"))\n                                select(iso);\n                            }}\n                            onKeyUp={(event: KeyEvent) => {\n                              if (available && isActivation(event, \"up\"))\n                                select(iso);\n                            }}\n                            style={mergeStyles(\n                              recipeStyle(CALENDAR_DAY, theme),\n                              cellStyle(\n                                theme,\n                                paint,\n                                !isSameDay(startOfMonth(day), month),\n                                isSameDay(day, today),\n                                available,\n                              ),\n                            )}\n                          >\n                            {DateTime.toPartsUtc(day).day}\n                          </div>\n                        );\n                      },\n                    }),\n                  )}\n                </div>\n              ))}\n            </div>\n          </div>\n        );\n      })}\n    </div>\n  );\n};\n\nexport type { CalendarMode };\n\nexport const calendarMeta = {\n  name: \"Calendar\",\n  tier: 2,\n  status: \"done\",\n  gpuixSupport: \"partial\",\n  limitations: [\n    \"day, month and weekday labels are fixed English strings: the repo has no i18n layer\",\n    \"0.11.0 has no aria-current, so today is marked by a border only\",\n    \"0.11.0 has no aria-disabled and no live region: an unavailable day leaves the tab order, and a selection change is announced by the focused cell's name rather than a live region\",\n    \"no week numbers and no time of day: a time is the separate TimePicker\",\n  ],\n  docs: \"docs/calendar.mdx\",\n  example: \"examples/calendar.example.tsx\",\n  testFile: \"src/behaviour/calendar.test.tsx\",\n} as const;\n"
    },
    {
      "path": "packages/components/src/calendar/logic.ts",
      "target": "@ui/gpuixui/components/calendar/logic.ts",
      "type": "registry:lib",
      "content": "import { Match, pipe } from \"effect\";\nimport * as Arr from \"effect/Array\";\nimport * as DateTime from \"effect/DateTime\";\nimport * as Option from \"effect/Option\";\nimport * as P from \"effect/Predicate\";\n\nexport type WeekStart = 0 | 1;\n\nexport type DayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6;\n\nexport type CalendarMode = \"single\" | \"multiple\" | \"range\";\n\nexport type MonthCount = 1 | 2;\n\nexport type CaptionLayout = \"label\" | \"dropdown\";\n\nconst MONTHS: ReadonlyArray<string> = [\n  \"January\",\n  \"February\",\n  \"March\",\n  \"April\",\n  \"May\",\n  \"June\",\n  \"July\",\n  \"August\",\n  \"September\",\n  \"October\",\n  \"November\",\n  \"December\",\n];\n\nconst SHORT_MONTHS: ReadonlyArray<string> = [\n  \"Jan\",\n  \"Feb\",\n  \"Mar\",\n  \"Apr\",\n  \"May\",\n  \"Jun\",\n  \"Jul\",\n  \"Aug\",\n  \"Sep\",\n  \"Oct\",\n  \"Nov\",\n  \"Dec\",\n];\n\nconst WEEKDAYS: ReadonlyArray<string> = [\n  \"Sun\",\n  \"Mon\",\n  \"Tue\",\n  \"Wed\",\n  \"Thu\",\n  \"Fri\",\n  \"Sat\",\n];\n\nconst monthName = (parts: DateTime.DateTime.Parts): string =>\n  Option.getOrElse(Arr.get(MONTHS, parts.month - 1), () => String(parts.month));\n\nconst shortMonthName = (parts: DateTime.DateTime.Parts): string =>\n  Option.getOrElse(Arr.get(SHORT_MONTHS, parts.month - 1), () =>\n    String(parts.month),\n  );\n\nexport const weekdayLabels = (weekStartsOn: WeekStart): ReadonlyArray<string> =>\n  weekStartsOn === 1\n    ? [...Arr.drop(WEEKDAYS, 1), ...Arr.take(WEEKDAYS, 1)]\n    : WEEKDAYS;\n\nexport const formatMonthLabel = (value: DateTime.Utc): string => {\n  const parts = DateTime.toPartsUtc(value);\n  return `${monthName(parts)} ${parts.year}`;\n};\n\nexport const monthShortName = (month: number): string =>\n  Option.getOrElse(Arr.get(SHORT_MONTHS, month - 1), () => String(month));\n\nexport const formatDayLabel = (value: DateTime.Utc): string => {\n  const parts = DateTime.toPartsUtc(value);\n  return `${parts.day} ${formatMonthLabel(value)}`;\n};\n\nexport const formatShortDay = (value: DateTime.Utc): string => {\n  const parts = DateTime.toPartsUtc(value);\n  return `${shortMonthName(parts)} ${parts.day}, ${parts.year}`;\n};\n\nexport interface DayRange {\n  readonly from: string;\n  readonly to: string | null;\n}\n\nexport const formatRangeLabel = (range: DayRange): string => {\n  const from = parseIsoDay(range.from);\n  const to = Option.flatMap(Option.fromNullishOr(range.to), parseIsoDay);\n  return Option.match(to, {\n    onNone: () =>\n      Option.match(from, {\n        onNone: () => range.from,\n        onSome: formatShortDay,\n      }),\n    onSome: (end) => {\n      const start = Option.getOrNull(from);\n      if (start === null) return formatShortDay(end);\n      const startParts = DateTime.toPartsUtc(start);\n      const endParts = DateTime.toPartsUtc(end);\n      return startParts.year === endParts.year\n        ? `${shortMonthName(startParts)} ${startParts.day} – ${shortMonthName(endParts)} ${endParts.day}, ${endParts.year}`\n        : `${formatShortDay(start)} – ${formatShortDay(end)}`;\n    },\n  });\n};\n\nexport const startOfMonth = (value: DateTime.Utc): DateTime.Utc =>\n  DateTime.startOf(\"month\")(value);\n\nexport const addMonths = (value: DateTime.Utc, amount: number): DateTime.Utc =>\n  DateTime.add({ months: amount })(startOfMonth(value));\n\nexport const addDays = (value: DateTime.Utc, amount: number): DateTime.Utc =>\n  DateTime.add({ days: amount })(value);\n\nexport const lastDayOfMonth = (value: DateTime.Utc): DateTime.Utc =>\n  DateTime.add({ days: -1 })(addMonths(value, 1));\n\nexport const isSameDay = (left: DateTime.Utc, right: DateTime.Utc): boolean => {\n  const a = DateTime.toPartsUtc(left);\n  const b = DateTime.toPartsUtc(right);\n  return a.year === b.year && a.month === b.month && a.day === b.day;\n};\n\nexport const formatIsoDay = (value: DateTime.Utc): string =>\n  DateTime.formatIsoDateUtc(value);\n\nconst ISO_DAY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport const parseIsoDay = (value: string): Option.Option<DateTime.Utc> =>\n  pipe(\n    ISO_DAY.test(value) ? Option.some(value) : Option.none(),\n    Option.flatMap((day) => DateTime.make(`${day}T00:00:00.000Z`)),\n    Option.filter((parsed) => DateTime.formatIsoDateUtc(parsed) === value),\n    Option.map((parsed) => DateTime.startOf(\"day\")(parsed)),\n  );\n\nexport const todayUtc = (now: DateTime.Utc): DateTime.Utc =>\n  DateTime.startOf(\"day\")(now);\n\nexport const monthGrid = (\n  month: DateTime.Utc,\n  weekStartsOn: WeekStart,\n  showOutsideDays = true,\n): ReadonlyArray<ReadonlyArray<Option.Option<DateTime.Utc>>> => {\n  const start = startOfMonth(month);\n  const monthParts = DateTime.toPartsUtc(start);\n  const offset = (monthParts.weekDay - weekStartsOn + 7) % 7;\n  const firstCell = addDays(start, -offset);\n\n  const cell = (index: number): Option.Option<DateTime.Utc> => {\n    const day = addDays(firstCell, index);\n    const parts = DateTime.toPartsUtc(day);\n    const own =\n      parts.year === monthParts.year && parts.month === monthParts.month;\n    return own || showOutsideDays ? Option.some(day) : Option.none();\n  };\n\n  return Arr.map(Arr.range(0, 5), (week) =>\n    Arr.map(Arr.range(0, 6), (day) => cell(week * 7 + day)),\n  );\n};\n\nexport const monthWindow = (\n  viewMonth: DateTime.Utc,\n  count: MonthCount,\n): ReadonlyArray<DateTime.Utc> =>\n  Arr.map(Arr.range(0, count - 1), (index) => addMonths(viewMonth, index));\n\nexport const windowStart = (viewMonth: DateTime.Utc): DateTime.Utc =>\n  startOfMonth(viewMonth);\n\nexport const windowEnd = (\n  viewMonth: DateTime.Utc,\n  count: MonthCount,\n): DateTime.Utc => lastDayOfMonth(addMonths(viewMonth, count - 1));\n\nexport const visibleMonth = (\n  viewMonth: DateTime.Utc,\n  count: MonthCount,\n  day: DateTime.Utc,\n): DateTime.Utc => {\n  const millis = DateTime.toEpochMillis(day);\n  if (millis < DateTime.toEpochMillis(windowStart(viewMonth)))\n    return startOfMonth(day);\n  if (millis > DateTime.toEpochMillis(windowEnd(viewMonth, count)))\n    return addMonths(startOfMonth(day), -(count - 1));\n  return startOfMonth(viewMonth);\n};\n\nconst gridStart = (\n  month: DateTime.Utc,\n  weekStartsOn: WeekStart,\n): DateTime.Utc => {\n  const start = startOfMonth(month);\n  const offset = (DateTime.toPartsUtc(start).weekDay - weekStartsOn + 7) % 7;\n  return addDays(start, -offset);\n};\n\nconst gridEnd = (month: DateTime.Utc, weekStartsOn: WeekStart): DateTime.Utc =>\n  addDays(gridStart(month, weekStartsOn), 41);\n\nexport interface DayBounds {\n  readonly min: Option.Option<DateTime.Utc>;\n  readonly max: Option.Option<DateTime.Utc>;\n}\n\nexport const unbounded: DayBounds = {\n  min: Option.none(),\n  max: Option.none(),\n};\n\nexport const boundsOf = (\n  min?: string | null,\n  max?: string | null,\n): DayBounds => ({\n  min: Option.flatMap(Option.fromNullishOr(min), parseIsoDay),\n  max: Option.flatMap(Option.fromNullishOr(max), parseIsoDay),\n});\n\nexport interface DayMatchers {\n  readonly before?: string;\n\n  readonly after?: string;\n\n  readonly range?: {\n    readonly from?: string;\n    readonly to?: string;\n  };\n\n  readonly weekdays?: ReadonlyArray<DayOfWeek>;\n\n  readonly filter?: (day: string) => boolean;\n}\n\nexport const boundsOfMatchers = (\n  matchers: DayMatchers | undefined,\n): DayBounds => {\n  const shift = (end: \"before\" | \"after\") =>\n    Option.flatMap(\n      Option.fromNullishOr(\n        end === \"before\" ? matchers?.before : matchers?.after,\n      ),\n      (iso) =>\n        Option.map(parseIsoDay(iso), (day) =>\n          addDays(day, end === \"before\" ? 1 : -1),\n        ),\n    );\n  return { min: shift(\"before\"), max: shift(\"after\") };\n};\n\nexport const isAvailable = (day: DateTime.Utc, bounds: DayBounds): boolean => {\n  const millis = DateTime.toEpochMillis(day);\n  return (\n    Option.match(bounds.min, {\n      onNone: () => true,\n      onSome: (min) => millis >= DateTime.toEpochMillis(min),\n    }) &&\n    Option.match(bounds.max, {\n      onNone: () => true,\n      onSome: (max) => millis <= DateTime.toEpochMillis(max),\n    })\n  );\n};\n\nexport const isDisabled = (\n  day: DateTime.Utc,\n  matchers: DayMatchers | undefined,\n): boolean => {\n  if (matchers === undefined) return false;\n  const iso = formatIsoDay(day);\n  const millis = DateTime.toEpochMillis(day);\n  const edge = (value: string | undefined): Option.Option<number> =>\n    Option.map(\n      Option.flatMap(Option.fromNullishOr(value), parseIsoDay),\n      DateTime.toEpochMillis,\n    );\n  const atOrAfter = (bound: Option.Option<number>): boolean =>\n    Option.match(bound, {\n      onNone: () => true,\n      onSome: (value) => millis >= value,\n    });\n  const atOrBefore = (bound: Option.Option<number>): boolean =>\n    Option.match(bound, {\n      onNone: () => true,\n      onSome: (value) => millis <= value,\n    });\n  const inSpan =\n    matchers.range !== undefined &&\n    atOrAfter(edge(matchers.range.from)) &&\n    atOrBefore(edge(matchers.range.to));\n  return (\n    Option.exists(edge(matchers.before), (before) => millis < before) ||\n    Option.exists(edge(matchers.after), (after) => millis > after) ||\n    inSpan ||\n    Arr.contains(DateTime.toPartsUtc(day).weekDay as DayOfWeek)(\n      matchers.weekdays ?? [],\n    ) ||\n    (matchers.filter !== undefined && matchers.filter(iso))\n  );\n};\n\nexport const isDayAvailable = (\n  day: DateTime.Utc,\n  bounds: DayBounds,\n  matchers: DayMatchers | undefined,\n): boolean => isAvailable(day, bounds) && !isDisabled(day, matchers);\n\nexport const clampToBounds = (\n  day: DateTime.Utc,\n  bounds: DayBounds,\n): DateTime.Utc => {\n  const millis = DateTime.toEpochMillis(day);\n  const lower = Option.match(bounds.min, {\n    onNone: () => day,\n    onSome: (min) => (millis < DateTime.toEpochMillis(min) ? min : day),\n  });\n  return Option.match(bounds.max, {\n    onNone: () => lower,\n    onSome: (max) =>\n      DateTime.toEpochMillis(lower) > DateTime.toEpochMillis(max) ? max : lower,\n  });\n};\n\nexport const canBrowseMonth = (\n  viewMonth: DateTime.Utc,\n  direction: -1 | 1,\n  bounds: DayBounds,\n): boolean => {\n  const current = DateTime.toEpochMillis(startOfMonth(viewMonth));\n  return Match.value(direction).pipe(\n    Match.when(-1, () =>\n      Option.match(bounds.min, {\n        onNone: () => true,\n        onSome: (min) => current > DateTime.toEpochMillis(startOfMonth(min)),\n      }),\n    ),\n    Match.when(1, () =>\n      Option.match(bounds.max, {\n        onNone: () => true,\n        onSome: (max) => current < DateTime.toEpochMillis(startOfMonth(max)),\n      }),\n    ),\n    Match.exhaustive,\n  );\n};\n\nexport type MoveKey =\n  | \"left\"\n  | \"right\"\n  | \"up\"\n  | \"down\"\n  | \"home\"\n  | \"end\"\n  | \"page-up\"\n  | \"page-down\";\n\nexport interface Move {\n  readonly key: MoveKey;\n  readonly year?: boolean;\n}\n\nexport interface MoveOptions {\n  readonly weekStartsOn: WeekStart;\n  readonly viewMonth: DateTime.Utc;\n  readonly months: MonthCount;\n  readonly showOutsideDays: boolean;\n  readonly bounds: DayBounds;\n  readonly matchers: DayMatchers | undefined;\n  readonly fromYear: number;\n  readonly toYear: number;\n}\n\nconst stepOf = (\n  from: DateTime.Utc,\n  move: Move,\n  options: MoveOptions,\n): DateTime.Utc => {\n  const parts = DateTime.toPartsUtc(from);\n  const offset = (parts.weekDay - options.weekStartsOn + 7) % 7;\n  const inMonth = (amount: number): DateTime.Utc => {\n    const target = addMonths(from, amount);\n    const last = DateTime.toPartsUtc(lastDayOfMonth(target)).day;\n    return addDays(startOfMonth(target), Math.min(parts.day, last) - 1);\n  };\n  return Match.value(move.key).pipe(\n    Match.when(\"left\", () => addDays(from, -1)),\n    Match.when(\"right\", () => addDays(from, 1)),\n    Match.when(\"up\", () => addDays(from, -7)),\n    Match.when(\"down\", () => addDays(from, 7)),\n    Match.when(\"home\", () => addDays(from, -offset)),\n    Match.when(\"end\", () => addDays(from, 6 - offset)),\n    Match.when(\"page-up\", () => inMonth(move.year === true ? -12 : -1)),\n    Match.when(\"page-down\", () => inMonth(move.year === true ? 12 : 1)),\n    Match.exhaustive,\n  );\n};\n\nconst clampYear = (\n  day: DateTime.Utc,\n  fromYear: number,\n  toYear: number,\n): DateTime.Utc => {\n  const parts = DateTime.toPartsUtc(day);\n  const year = Math.min(Math.max(parts.year, fromYear), toYear);\n  if (year === parts.year) return day;\n  const first = DateTime.make(\n    `${String(year).padStart(4, \"0\")}-${String(parts.month).padStart(2, \"0\")}-01T00:00:00.000Z`,\n  );\n  return Option.match(first, {\n    onNone: () => day,\n    onSome: (month) =>\n      addDays(\n        month,\n        Math.min(parts.day, DateTime.toPartsUtc(lastDayOfMonth(month)).day) - 1,\n      ),\n  });\n};\n\nexport const moveDay = (\n  from: DateTime.Utc,\n  move: Move,\n  options: MoveOptions,\n): DateTime.Utc => {\n  const raw =\n    move.year === true\n      ? clampYear(stepOf(from, move, options), options.fromYear, options.toYear)\n      : stepOf(from, move, options);\n\n  const bounded = clampToBounds(raw, options.bounds);\n  const paging = move.key === \"page-up\" || move.key === \"page-down\";\n  const windowFirst = paging ? startOfMonth(bounded) : options.viewMonth;\n  const windowLast = paging\n    ? startOfMonth(bounded)\n    : addMonths(options.viewMonth, options.months - 1);\n  const ownFirst = paging ? startOfMonth(bounded) : startOfMonth(from);\n  const ownLast = paging ? lastDayOfMonth(bounded) : lastDayOfMonth(from);\n  const lower = options.showOutsideDays\n    ? gridStart(windowFirst, options.weekStartsOn)\n    : ownFirst;\n  const upper = options.showOutsideDays\n    ? gridEnd(windowLast, options.weekStartsOn)\n    : ownLast;\n  const clamp = (day: DateTime.Utc): DateTime.Utc => {\n    const millis = DateTime.toEpochMillis(day);\n    if (millis < DateTime.toEpochMillis(lower)) return lower;\n    if (millis > DateTime.toEpochMillis(upper)) return upper;\n    return day;\n  };\n  const target = clamp(bounded);\n  const direction =\n    DateTime.toEpochMillis(target) < DateTime.toEpochMillis(from) ? -1 : 1;\n  const inside = (day: DateTime.Utc): boolean => {\n    const millis = DateTime.toEpochMillis(day);\n    return (\n      millis >= DateTime.toEpochMillis(lower) &&\n      millis <= DateTime.toEpochMillis(upper)\n    );\n  };\n  const search = (steps: number): DateTime.Utc => {\n    const candidate = addDays(target, steps * direction);\n    return steps > 84 || !inside(candidate)\n      ? from\n      : isDayAvailable(candidate, options.bounds, options.matchers)\n        ? candidate\n        : search(steps + 1);\n  };\n  return isDayAvailable(target, options.bounds, options.matchers)\n    ? target\n    : search(0);\n};\n\nexport const yearRange = (\n  fromYear: number,\n  toYear: number,\n): ReadonlyArray<number> =>\n  fromYear <= toYear ? Arr.range(fromYear, toYear) : Arr.empty();\n\nexport type Selection =\n  | { readonly mode: \"single\"; readonly day: string | null }\n  | { readonly mode: \"multiple\"; readonly days: ReadonlyArray<string> }\n  | { readonly mode: \"range\"; readonly range: DayRange | null };\n\nexport const singleSelection = (day: string | null): Selection => ({\n  mode: \"single\",\n  day,\n});\n\nexport const multipleSelection = (days: ReadonlyArray<string>): Selection => ({\n  mode: \"multiple\",\n  days,\n});\n\nexport const rangeSelection = (range: DayRange | null): Selection => ({\n  mode: \"range\",\n  range,\n});\n\nexport const rangeOf = (value: unknown): DayRange | null => {\n  if (typeof value !== \"object\" || value === null) return null;\n  const source = value as { readonly from?: unknown; readonly to?: unknown };\n  if (!P.isString(source.from) || Option.isNone(parseIsoDay(source.from)))\n    return null;\n  return {\n    from: source.from,\n    to:\n      P.isString(source.to) && Option.isSome(parseIsoDay(source.to))\n        ? source.to\n        : null,\n  };\n};\n\nexport const rangeContains = (range: DayRange | null, day: string): boolean => {\n  if (range === null) return false;\n  const millis = Option.match(parseIsoDay(day), {\n    onNone: () => null,\n    onSome: DateTime.toEpochMillis,\n  });\n  const start = Option.match(parseIsoDay(range.from), {\n    onNone: () => null,\n    onSome: DateTime.toEpochMillis,\n  });\n  const end = Option.match(Option.fromNullishOr(range.to), {\n    onNone: () => start,\n    onSome: (iso) =>\n      Option.match(parseIsoDay(iso), {\n        onNone: () => start,\n        onSome: DateTime.toEpochMillis,\n      }),\n  });\n  return millis !== null && start !== null && end !== null\n    ? millis >= start && millis <= end\n    : false;\n};\n\nexport const nextRange = (range: DayRange | null, day: string): DayRange =>\n  range === null || range.to !== null || day < range.from\n    ? { from: day, to: null }\n    : { from: range.from, to: day };\n\nexport const nextDay = (current: string | null, day: string): string | null =>\n  current === day ? null : day;\n\nexport const toggleDay = (\n  days: ReadonlyArray<string>,\n  day: string,\n): ReadonlyArray<string> =>\n  Arr.contains(day)(days)\n    ? Arr.filter(days, (held) => held !== day)\n    : [...days, day];\n\nexport const dayInMonth = (\n  value: DateTime.Utc,\n  month: DateTime.Utc,\n): DateTime.Utc => {\n  const parts = DateTime.toPartsUtc(value);\n  const target = startOfMonth(month);\n  const last = DateTime.toPartsUtc(lastDayOfMonth(target)).day;\n  return addDays(target, Math.min(parts.day, last) - 1);\n};\n\nexport type DayPaint =\n  | \"none\"\n  | \"selected\"\n  | \"range-start\"\n  | \"range-middle\"\n  | \"range-end\";\n\nexport const paintOf = (selection: Selection, day: string): DayPaint => {\n  if (selection.mode === \"single\")\n    return selection.day === day ? \"selected\" : \"none\";\n  if (selection.mode === \"multiple\")\n    return Arr.contains(day)(selection.days) ? \"selected\" : \"none\";\n  const range = selection.range;\n  if (range === null) return \"none\";\n  if (range.from === day) return \"range-start\";\n  if (range.to === day) return \"range-end\";\n  return rangeContains(range, day) ? \"range-middle\" : \"none\";\n};\n\nexport const isPainted = (paint: DayPaint): boolean =>\n  paint === \"selected\" || paint === \"range-start\" || paint === \"range-end\";\n\nexport const dayAriaLabel = (\n  day: DateTime.Utc,\n  paint: DayPaint,\n  available: boolean,\n): string => {\n  const name = formatDayLabel(day);\n  const state = Match.value(paint).pipe(\n    Match.when(\"selected\", () => \", selected\"),\n    Match.when(\"range-start\", () => \", range start\"),\n    Match.when(\"range-middle\", () => \", in range\"),\n    Match.when(\"range-end\", () => \", range end\"),\n    Match.orElse(() => \"\"),\n  );\n  return `${name}${state}${available ? \"\" : \", unavailable\"}`;\n};\n\nexport const describeSelection = (selection: Selection): string => {\n  if (selection.mode === \"single\")\n    return Option.match(\n      Option.flatMap(Option.fromNullishOr(selection.day), parseIsoDay),\n      {\n        onNone: () => \"no day selected\",\n        onSome: (day) => `${formatDayLabel(day)} selected`,\n      },\n    );\n  if (selection.mode === \"multiple\")\n    return selection.days.length === 0\n      ? \"no days selected\"\n      : `${selection.days.length} selected`;\n  return selection.range === null\n    ? \"no range selected\"\n    : `range ${formatRangeLabel(selection.range)}`;\n};\n\nexport const calendarLabel = (label: string, selection: Selection): string =>\n  `${label}, ${describeSelection(selection)}`;\n\nexport const hasSelection = (selection: Selection): boolean =>\n  Match.value(selection).pipe(\n    Match.when({ mode: \"single\" }, (current) => current.day !== null),\n    Match.when({ mode: \"multiple\" }, (current) => current.days.length > 0),\n    Match.when({ mode: \"range\" }, (current) => current.range !== null),\n    Match.exhaustive,\n  );\n\nexport const formatSelectionLabel = (\n  selection: Selection,\n  placeholder: string,\n): string => {\n  if (!hasSelection(selection)) return placeholder;\n  return Match.value(selection).pipe(\n    Match.when({ mode: \"single\" }, (current) =>\n      Option.match(\n        Option.flatMap(Option.fromNullishOr(current.day), parseIsoDay),\n        { onNone: () => placeholder, onSome: formatShortDay },\n      ),\n    ),\n    Match.when({ mode: \"multiple\" }, (current) =>\n      current.days.length === 1\n        ? formatSelectionLabel(\n            singleSelection(current.days[0] ?? null),\n            placeholder,\n          )\n        : `${current.days.length} days`,\n    ),\n    Match.when({ mode: \"range\" }, (current) =>\n      current.range === null ? placeholder : formatRangeLabel(current.range),\n    ),\n    Match.exhaustive,\n  );\n};\n\nexport const isOutsideMonth = (\n  day: DateTime.Utc,\n  month: DateTime.Utc,\n): boolean => !isSameDay(startOfMonth(day), startOfMonth(month));\n\nexport const moveKeyOf = (key: string): Option.Option<MoveKey> =>\n  Match.value(key).pipe(\n    Match.when(\"left\", () => Option.some(\"left\" as const)),\n    Match.when(\"right\", () => Option.some(\"right\" as const)),\n    Match.when(\"up\", () => Option.some(\"up\" as const)),\n    Match.when(\"down\", () => Option.some(\"down\" as const)),\n    Match.when(\"home\", () => Option.some(\"home\" as const)),\n    Match.when(\"end\", () => Option.some(\"end\" as const)),\n    Match.when(\"pageup\", () => Option.some(\"page-up\" as const)),\n    Match.when(\"pagedown\", () => Option.some(\"page-down\" as const)),\n    Match.orElse(() => Option.none()),\n  );\n"
    },
    {
      "path": "packages/components/src/calendar/store.ts",
      "target": "@ui/gpuixui/components/calendar/store.ts",
      "type": "registry:lib",
      "content": "import { Effect } from \"effect\";\nimport * as DateTime from \"effect/DateTime\";\nimport * as SubscriptionRef from \"effect/SubscriptionRef\";\nimport { makeLocalState, type LocalState } from \"../internal/local-state.js\";\nimport { visibleMonth, type MonthCount } from \"./logic.js\";\n\nexport interface CalendarViewState {\n  readonly month: DateTime.Utc;\n\n  readonly focus: DateTime.Utc;\n\n  readonly pending: boolean;\n}\n\nexport interface CalendarStore {\n  readonly local: LocalState<CalendarViewState>;\n\n  readonly count: MonthCount;\n\n  readonly focusDay: (day: DateTime.Utc) => Effect.Effect<void>;\n\n  readonly show: (\n    month: DateTime.Utc,\n    day: DateTime.Utc,\n  ) => Effect.Effect<void>;\n\n  readonly visited: (day: DateTime.Utc) => Effect.Effect<void>;\n\n  readonly settle: Effect.Effect<void>;\n}\n\nexport const makeCalendarStore = (initial: {\n  readonly month: DateTime.Utc;\n  readonly focus: DateTime.Utc;\n  readonly count: MonthCount;\n  readonly pending?: boolean;\n}): Effect.Effect<CalendarStore> =>\n  Effect.gen(function* () {\n    const count = initial.count;\n    const local = yield* makeLocalState<CalendarViewState>({\n      month: initial.month,\n      focus: initial.focus,\n      pending: initial.pending ?? false,\n    });\n\n    const focusDay = Effect.fnUntraced(function* (day: DateTime.Utc) {\n      const current = yield* SubscriptionRef.get(local.state);\n      yield* local.write({\n        month: visibleMonth(current.month, count, day),\n        focus: day,\n        pending: true,\n      });\n    });\n\n    const show = Effect.fnUntraced(function* (\n      month: DateTime.Utc,\n      day: DateTime.Utc,\n    ) {\n      yield* local.write({ month, focus: day, pending: true });\n    });\n\n    const visited = Effect.fnUntraced(function* (day: DateTime.Utc) {\n      const current = yield* SubscriptionRef.get(local.state);\n      if (DateTime.toEpochMillis(current.focus) === DateTime.toEpochMillis(day))\n        return;\n      yield* local.write({\n        month: visibleMonth(current.month, count, day),\n        focus: day,\n        pending: false,\n      });\n    });\n\n    const settle = Effect.flatMap(SubscriptionRef.get(local.state), (current) =>\n      current.pending\n        ? local.write({ ...current, pending: false })\n        : Effect.void,\n    );\n\n    return { local, count, focusDay, show, visited, settle };\n  });\n"
    },
    {
      "path": "packages/components/src/date-picker.tsx",
      "target": "@ui/gpuixui/components/date-picker.tsx",
      "type": "registry:component",
      "content": "/** @jsxImportSource @gpuix/react */\nimport type { EventPayload, PublicInstance } from \"@gpuix/react\";\nimport { useGpuix } from \"@gpuix/react\";\nimport {\n  mergeStyles,\n  resolveStyle,\n  type FloatingContentProps,\n} from \"@gpuix/react/floating\";\nimport { Icon } from \"../icons/index.js\";\nimport type { ButtonProps as PrimitiveButtonProps } from \"../primitives/button.js\";\nimport {\n  cn,\n  DATE_PICKER_CARET,\n  DATE_PICKER_CONTENT,\n  DATE_PICKER_TRIGGER,\n  DATE_PICKER_TRIGGER_TEXT,\n} from \"../tw/index.js\";\nimport * as DateTime from \"effect/DateTime\";\nimport * as Option from \"effect/Option\";\nimport {\n  createContext,\n  useCallback,\n  useContext,\n  useLayoutEffect,\n  useRef,\n  type ReactElement,\n} from \"react\";\nimport { Calendar } from \"./calendar.js\";\nimport {\n  boundsOf,\n  formatIsoDay,\n  formatSelectionLabel,\n  hasSelection,\n  parseIsoDay,\n  rangeOf,\n  rangeSelection,\n  singleSelection,\n  todayUtc,\n  type CaptionLayout,\n  type DayBounds,\n  type DayMatchers,\n  type DayRange,\n  type MonthCount,\n  type Selection,\n  type WeekStart,\n} from \"./calendar/logic.js\";\nimport { makePickerOpen } from \"./date-picker/store.js\";\nimport { Button } from \"./internal/button.js\";\nimport { useControllableState } from \"./internal/controllable.js\";\nimport { send, useLocalState, useLocalStore } from \"./internal/local-state.js\";\nimport {\n  assertParts,\n  type PartChildren,\n  type PartComponent,\n  type PartsContract,\n} from \"./internal/parts.js\";\nimport { recipeStyle } from \"./internal/recipe.js\";\nimport { useMergedRef } from \"./internal/ref.js\";\nimport { controlHeight, useTheme } from \"./internal/theme.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./popover.js\";\n\ninterface DatePickerContextValue {\n  readonly selection: Selection;\n  readonly bounds: DayBounds;\n  readonly matchers: DayMatchers | undefined;\n  readonly weekStartsOn: WeekStart;\n  readonly todayDay: DateTime.Utc;\n  readonly clearable: boolean;\n  readonly disabled: boolean;\n  readonly open: boolean;\n  readonly numberOfMonths: MonthCount;\n  readonly showOutsideDays: boolean;\n  readonly captionLayout: CaptionLayout;\n  readonly fromYear: number | undefined;\n  readonly toYear: number | undefined;\n  readonly chooseSingle: (day: string | null) => void;\n  readonly chooseRange: (range: DayRange | null) => void;\n  readonly clear: () => void;\n  readonly closeToTrigger: () => void;\n  readonly registerTrigger: (instance: PublicInstance | null) => void;\n}\n\nconst DatePickerContext = createContext<DatePickerContextValue | undefined>(\n  undefined,\n);\n\nconst useDatePicker = (): DatePickerContextValue => {\n  const value = useContext(DatePickerContext);\n  if (value === undefined) {\n    throw new Error(\"DatePicker parts must be used inside DatePicker\");\n  }\n  return value;\n};\n\nexport interface DatePickerBaseProps {\n  readonly weekStartsOn?: WeekStart;\n\n  readonly min?: string;\n\n  readonly max?: string;\n\n  readonly clearable?: boolean;\n  readonly disabled?: boolean;\n\n  readonly today?: string;\n\n  readonly numberOfMonths?: MonthCount;\n\n  readonly showOutsideDays?: boolean;\n\n  readonly captionLayout?: CaptionLayout;\n  readonly fromYear?: number;\n  readonly toYear?: number;\n  readonly children?: PartChildren;\n}\n\nexport interface SingleDatePickerProps extends DatePickerBaseProps {\n  readonly mode?: \"single\";\n\n  readonly value?: string | null;\n  readonly defaultValue?: string | null;\n  readonly onValueChange?: (value: string | null) => void;\n}\n\nexport interface RangeDatePickerProps extends DatePickerBaseProps {\n  readonly mode: \"range\";\n\n  readonly value?: DayRange | null;\n  readonly defaultValue?: DayRange | null;\n  readonly onValueChange?: (value: DayRange | null) => void;\n}\n\nexport type DatePickerProps = SingleDatePickerProps | RangeDatePickerProps;\n\ninterface PickerRootProps {\n  readonly base: DatePickerBaseProps;\n  readonly selection: Selection;\n\n  readonly commit: (next: Selection) => boolean;\n  readonly clear: () => void;\n}\n\nconst todayOf = (value: string | undefined): DateTime.Utc =>\n  Option.getOrElse(\n    Option.flatMap(Option.fromNullishOr(value), parseIsoDay),\n    () => todayUtc(DateTime.nowUnsafe()),\n  );\n\nconst matchersOf = (\n  bounds: DayBounds,\n  disabled: boolean,\n): DayMatchers | undefined => {\n  const before = Option.map(bounds.min, (min) =>\n    formatIsoDay(DateTime.add({ days: -1 })(min)),\n  );\n  const after = Option.map(bounds.max, (max) =>\n    formatIsoDay(DateTime.add({ days: 1 })(max)),\n  );\n  const edges: DayMatchers = {\n    ...Option.match(before, {\n      onNone: () => ({}),\n      onSome: (day) => ({ before: day }),\n    }),\n    ...Option.match(after, {\n      onNone: () => ({}),\n      onSome: (day) => ({ after: day }),\n    }),\n  };\n  if (disabled) return { ...edges, filter: () => true };\n  return Option.isNone(before) && Option.isNone(after) ? undefined : edges;\n};\n\nconst PickerRoot = ({\n  base,\n  selection,\n  commit,\n  clear,\n}: PickerRootProps): ReactElement => {\n  const renderer = useGpuix().renderer;\n  const store = useLocalStore(makePickerOpen);\n  const open = useLocalState(store.local);\n  const trigger = useRef<PublicInstance | null>(null);\n  const bounds = boundsOf(base.min, base.max);\n  const todayDay = todayOf(base.today);\n  const clearable = base.clearable === true;\n  const disabled = base.disabled === true;\n\n  const closeToTrigger = useCallback((): void => {\n    send(store.set(false));\n    const instance = trigger.current;\n    if (instance !== null) renderer?.focusElement?.(instance.id);\n  }, [renderer, store]);\n\n  useLayoutEffect(() => {\n    if (disabled) send(store.set(false));\n  }, [disabled, store]);\n\n  const report = (next: Selection): void => {\n    if (commit(next)) closeToTrigger();\n  };\n\n  assertParts(datePickerRoot, base.children);\n\n  return (\n    <DatePickerContext.Provider\n      value={{\n        selection,\n        bounds,\n        matchers: matchersOf(bounds, disabled),\n        weekStartsOn: base.weekStartsOn ?? 1,\n        todayDay,\n        clearable,\n        disabled,\n        open,\n        numberOfMonths:\n          base.numberOfMonths ?? (selection.mode === \"range\" ? 2 : 1),\n        showOutsideDays: base.showOutsideDays ?? true,\n        captionLayout: base.captionLayout ?? \"label\",\n        fromYear: base.fromYear,\n        toYear: base.toYear,\n        chooseSingle: (day) => report(singleSelection(day)),\n        chooseRange: (range) => report(rangeSelection(range)),\n        clear: () => {\n          clear();\n          closeToTrigger();\n        },\n        closeToTrigger,\n        registerTrigger: (instance) => {\n          trigger.current = instance;\n        },\n      }}\n    >\n      <Popover\n        open={open}\n        onOpenChange={(next) => {\n          if (disabled && next) return;\n          send(store.set(next));\n        }}\n      >\n        {base.children}\n      </Popover>\n    </DatePickerContext.Provider>\n  );\n};\n\nconst SinglePicker = (props: SingleDatePickerProps): ReactElement => {\n  const [value, setValue] = useControllableState<string | null>({\n    value: props.value,\n    defaultValue: props.defaultValue ?? null,\n    onChange: props.onValueChange,\n  });\n  const selection: Selection = { mode: \"single\", day: value };\n\n  return (\n    <PickerRoot\n      base={props}\n      selection={selection}\n      commit={(next) => {\n        if (next.mode === \"single\") setValue(next.day);\n        return true;\n      }}\n      clear={() => setValue(null)}\n    />\n  );\n};\n\nconst RangePicker = (props: RangeDatePickerProps): ReactElement => {\n  const [value, setValue] = useControllableState<DayRange | null>({\n    value: props.value,\n    defaultValue: props.defaultValue ?? null,\n    onChange: props.onValueChange,\n  });\n  const selection: Selection = { mode: \"range\", range: rangeOf(value) };\n\n  return (\n    <PickerRoot\n      base={props}\n      selection={selection}\n      commit={(next) => {\n        if (next.mode !== \"range\") return false;\n        setValue(next.range);\n        return next.range?.to != null;\n      }}\n      clear={() => setValue(null)}\n    />\n  );\n};\n\nexport const DatePicker = (props: DatePickerProps): ReactElement =>\n  props.mode === \"range\" ? (\n    <RangePicker {...props} />\n  ) : (\n    <SinglePicker {...props} />\n  );\n\nexport interface DatePickerTriggerProps extends Omit<\n  PrimitiveButtonProps,\n  \"children\"\n> {\n  readonly placeholder?: string;\n\n  readonly label?: string;\n\n  readonly className?: string;\n\n  readonly testId?: string;\n\n  readonly onClick?: (event: EventPayload) => void;\n}\n\nexport const DatePickerTrigger = ({\n  placeholder = \"Pick a date\",\n  className,\n  testId = \"date-picker-trigger\",\n  style,\n  ...rest\n}: DatePickerTriggerProps) => {\n  const theme = useTheme();\n  const { selection, disabled, registerTrigger } = useDatePicker();\n  const setTrigger = useMergedRef<PublicInstance | null>(\n    registerTrigger,\n    rest.ref,\n  );\n  const labelText = formatSelectionLabel(selection, placeholder);\n  const isPlaceholder = !hasSelection(selection);\n  const fieldStyle = mergeStyles(\n    recipeStyle(cn(DATE_PICKER_TRIGGER, className), theme),\n    {\n      height: controlHeight(theme, \"md\"),\n      color: isPlaceholder\n        ? theme.colors.mutedForeground\n        : theme.colors.foreground,\n    },\n  );\n\n  return (\n    <PopoverTrigger\n      {...rest}\n      ref={setTrigger}\n      testId={testId}\n      disabled={disabled}\n      style={(state) =>\n        mergeStyles(fieldStyle, resolveStyle(style, state)) ?? {}\n      }\n    >\n      <text\n        style={mergeStyles(recipeStyle(DATE_PICKER_TRIGGER_TEXT, theme), {\n          color: isPlaceholder\n            ? theme.colors.mutedForeground\n            : theme.colors.foreground,\n        })}\n      >\n        {labelText}\n      </text>\n      <div style={recipeStyle(DATE_PICKER_CARET, theme)}>\n        <Icon\n          name=\"chevron-down\"\n          size=\"xs\"\n          color={theme.colors.mutedForeground}\n        />\n      </div>\n    </PopoverTrigger>\n  );\n};\n\nexport interface DatePickerContentProps extends FloatingContentProps {\n  readonly side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n\n  readonly align?: \"start\" | \"center\" | \"end\";\n\n  readonly sideOffset?: number;\n\n  readonly className?: string;\n  readonly children?: PartChildren;\n}\n\nexport const DatePickerContent = ({\n  side = \"bottom\",\n  align = \"start\",\n  sideOffset = 6,\n  className,\n  children,\n  style,\n  ...rest\n}: DatePickerContentProps) => {\n  const theme = useTheme();\n  assertParts(datePickerContent, children);\n\n  return (\n    <PopoverContent\n      autoFocus={false}\n      side={side}\n      align={align}\n      sideOffset={sideOffset}\n      testId=\"date-picker-content\"\n      {...rest}\n      style={mergeStyles(\n        recipeStyle(cn(DATE_PICKER_CONTENT, className), theme),\n        style,\n      )}\n    >\n      {children}\n    </PopoverContent>\n  );\n};\n\nexport interface DatePickerCalendarProps {\n  readonly label?: string;\n}\n\nexport const DatePickerCalendar = ({\n  label = \"Calendar\",\n}: DatePickerCalendarProps): ReactElement => {\n  const {\n    selection,\n    matchers,\n    weekStartsOn,\n    todayDay,\n    clearable,\n    open,\n    numberOfMonths,\n    showOutsideDays,\n    captionLayout,\n    fromYear,\n    toYear,\n    chooseSingle,\n    chooseRange,\n    clear,\n    closeToTrigger,\n  } = useDatePicker();\n  const shared = {\n    weekStartsOn,\n    today: formatIsoDay(todayDay),\n    numberOfMonths,\n    showOutsideDays,\n    captionLayout,\n    fromYear,\n    toYear,\n    disabled: matchers,\n    label,\n    autoFocus: open,\n    onDismiss: closeToTrigger,\n  } as const;\n\n  return (\n    <>\n      {selection.mode === \"range\" ? (\n        <Calendar\n          {...shared}\n          mode=\"range\"\n          selected={selection.range}\n          onSelect={chooseRange}\n        />\n      ) : (\n        <Calendar\n          {...shared}\n          mode=\"single\"\n          selected={selection.mode === \"single\" ? selection.day : null}\n          onSelect={chooseSingle}\n        />\n      )}\n      {clearable && hasSelection(selection) ? (\n        <div style={{ display: \"flex\", justifyContent: \"flex-end\" }}>\n          <Button variant=\"ghost\" size=\"sm\" testId=\"date-clear\" onClick={clear}>\n            Clear\n          </Button>\n        </div>\n      ) : null}\n    </>\n  );\n};\n\nconst datePickerParts: ReadonlyArray<PartComponent> = [\n  DatePicker,\n  DatePickerTrigger,\n  DatePickerContent,\n  DatePickerCalendar,\n];\n\nconst datePickerRoot: PartsContract = {\n  parent: \"DatePicker\",\n  family: datePickerParts,\n  accepts: [DatePickerTrigger, DatePickerContent],\n  hint: \"Put DatePickerTrigger and DatePickerContent directly inside DatePicker.\",\n};\n\nconst datePickerContent: PartsContract = {\n  parent: \"DatePickerContent\",\n  family: datePickerParts,\n  accepts: [DatePickerCalendar],\n  hint: \"Put DatePickerCalendar directly inside DatePickerContent.\",\n};\n\nexport const datePickerMeta = {\n  name: \"Date pickers\",\n  tier: 2,\n  status: \"done\",\n  gpuixSupport: \"partial\",\n  limitations: [\n    \"day, month and weekday labels are fixed English strings: the repo has no i18n layer\",\n    \"no adjacent-month selection rule is hidden: outside days are painted and selectable by default\",\n    \"time is a separate TimePicker: this control owns days only\",\n    \"0.11.0 has no aria-current, so today is marked by a border only\",\n    \"0.11.0 has no aria-disabled: an unavailable day leaves the tab order and its accessible name ends in ', unavailable'\",\n    \"a min after max makes no day selectable; the grid is visible and inert rather than throwing from render\",\n    \"a picker disabled while its calendar is open closes with it, and no day or Clear writes the value\",\n  ],\n  docs: \"docs/date-picker.mdx\",\n  example: \"examples/date-picker.example.tsx\",\n  testFile: \"src/behaviour/date-picker.test.tsx\",\n} as const;\n"
    },
    {
      "path": "packages/components/src/date-picker/store.ts",
      "target": "@ui/gpuixui/components/date-picker/store.ts",
      "type": "registry:lib",
      "content": "import { Effect } from \"effect\";\nimport { makeLocalState, type LocalState } from \"../internal/local-state.js\";\n\nexport interface PickerOpen {\n  readonly local: LocalState<boolean>;\n  readonly set: (open: boolean) => Effect.Effect<void>;\n}\n\nexport const makePickerOpen = Effect.gen(function* () {\n  const local = yield* makeLocalState(false);\n  return { local, set: local.write };\n});\n"
    },
    {
      "path": "packages/components/src/internal/button.tsx",
      "target": "@ui/gpuixui/components/internal/button.tsx",
      "type": "registry:component",
      "content": "/** @jsxImportSource @gpuix/react */\nimport type { Props } from \"@gpuix/react\";\nimport type { ReactNode } from \"react\";\nimport {\n  Button as PrimitiveButton,\n  IconButton as PrimitiveIconButton,\n  actionOnColor as primitiveActionOnColor,\n  type ButtonVariant as PrimitiveVariant,\n} from \"../../primitives/button.js\";\nimport { cn } from \"../../tw/index.js\";\nimport * as Schema from \"effect/Schema\";\nimport type { Theme } from \"./theme.js\";\n\nconst ButtonVariants = Schema.Literals([\n  \"primary\",\n  \"secondary\",\n  \"ghost\",\n  \"danger\",\n  \"link\",\n]);\n\nexport type ButtonVariant = typeof ButtonVariants.Type;\n\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ButtonProps extends Props {\n  readonly variant?: ButtonVariant;\n\n  readonly size?: ButtonSize;\n\n  readonly disabled?: boolean;\n\n  readonly loading?: boolean;\n\n  readonly loadingLabel?: string;\n\n  readonly reducedMotion?: boolean;\n\n  readonly leading?: ReactNode;\n\n  readonly trailing?: ReactNode;\n}\n\nexport interface IconButtonProps extends Props {\n  readonly label: string;\n\n  readonly size?: ButtonSize;\n  readonly disabled?: boolean;\n}\n\ninterface Look {\n  readonly variant: PrimitiveVariant;\n  readonly className: string;\n}\n\nconst LOOKS: Readonly<Record<ButtonVariant, Look>> = {\n  primary: { variant: \"primary\", className: \"\" },\n  secondary: { variant: \"secondary\", className: \"border border-strong\" },\n  ghost: { variant: \"ghost\", className: \"\" },\n  danger: { variant: \"destructive\", className: \"\" },\n\n  link: { variant: \"link\", className: \"underline underline-offset-4\" },\n};\n\nconst lookOf = (variant: unknown): Look =>\n  LOOKS[Schema.is(ButtonVariants)(variant) ? variant : \"secondary\"];\n\nexport const actionOnColor = (theme: Theme, variant: ButtonVariant): string =>\n  primitiveActionOnColor(theme, lookOf(variant).variant);\n\nexport const Button = ({\n  variant = \"secondary\",\n  size = \"md\",\n  disabled = false,\n  onClick,\n  style,\n  \"aria-label\": ariaLabel,\n  ...rest\n}: ButtonProps) => {\n  const look = lookOf(variant);\n  return (\n    <PrimitiveButton\n      {...rest}\n      variant={look.variant}\n      size={size}\n      disabled={disabled}\n      label={ariaLabel}\n      className={cn(look.className)}\n      onActivate={onClick}\n      style={style}\n    />\n  );\n};\n\nexport const IconButton = ({\n  label,\n  size = \"md\",\n  disabled = false,\n  onClick,\n  style,\n  children,\n  ...rest\n}: IconButtonProps) => (\n  <PrimitiveIconButton\n    {...rest}\n    icon={children}\n    variant=\"ghost\"\n    size={size}\n    disabled={disabled}\n    label={label}\n    className=\"text-muted-foreground hover:text-foreground\"\n    onActivate={onClick}\n    style={style}\n  />\n);\n"
    },
    {
      "path": "packages/components/src/internal/clock.ts",
      "target": "@ui/gpuixui/components/internal/clock.ts",
      "type": "registry:lib",
      "content": "import { Effect } from \"effect\";\nimport * as Clock from \"effect/Clock\";\n\nexport const monotonicNanos = (): bigint =>\n  Effect.runSync(Clock.monotonicTimeNanos);\n\nexport const hoverDelay = (value: number, fallback: number): number =>\n  Number.isFinite(value) ? Math.max(0, value) : fallback;\n"
    },
    {
      "path": "packages/components/src/internal/controllable.ts",
      "target": "@ui/gpuixui/components/internal/controllable.ts",
      "type": "registry:lib",
      "content": "import { useCallback, useState } from \"react\";\n\nexport type ControllableState<Value> = readonly [Value, (next: Value) => void];\n\nexport interface ControllableStateOptions<Value> {\n  readonly value: Value | undefined;\n\n  readonly defaultValue: Value;\n\n  readonly onChange?: (next: Value) => void;\n}\n\nexport const useControllableState = <Value>({\n  value,\n  defaultValue,\n  onChange,\n}: ControllableStateOptions<Value>): ControllableState<Value> => {\n  const [internal, setInternal] = useState(defaultValue);\n  const controlled = value !== undefined;\n\n  const setValue = useCallback(\n    (next: Value) => {\n      if (!controlled) setInternal(next);\n      if (value !== next) onChange?.(next);\n    },\n    [controlled, value, onChange],\n  );\n\n  return [controlled ? value : internal, setValue];\n};\n"
    },
    {
      "path": "packages/components/src/internal/dismiss-layer.ts",
      "target": "@ui/gpuixui/components/internal/dismiss-layer.ts",
      "type": "registry:lib",
      "content": "import type { EventPayload } from \"@gpuix/react\";\nimport * as Arr from \"effect/Array\";\nimport * as Duration from \"effect/Duration\";\nimport * as Option from \"effect/Option\";\nimport * as Order from \"effect/Order\";\nimport { monotonicNanos } from \"./clock.js\";\n\nexport type DismissHandler = (event: EventPayload) => void;\n\ninterface Layer {\n  readonly onDismiss: DismissHandler;\n  readonly depth: number;\n}\n\nlet layers: ReadonlyArray<Layer> = [];\n\nlet dismissedKeystroke: Option.Option<number> = Option.none();\n\ninterface Press {\n  readonly shape: string;\n  readonly at: bigint;\n}\n\nlet dismissedPress: Option.Option<Press> = Option.none();\n\nexport const pointerGestureWindow: Duration.Duration = Duration.millis(64);\n\nconst PRESS_WINDOW_NANOS =\n  BigInt(Duration.toMillis(pointerGestureWindow)) * 1_000_000n;\n\nconst pressShape = (event: EventPayload): string =>\n  Arr.join(\":\")(\n    Arr.map(\n      [event.eventType, event.x, event.y, event.button, event.clickCount],\n      (part) => (part === undefined ? \"\" : `${part}`),\n    ),\n  );\n\nconst consumedPress = (event: EventPayload, now: bigint): boolean => {\n  const shape = pressShape(event);\n  const repeated = Option.exists(\n    dismissedPress,\n    (press) => press.shape === shape && now - press.at <= PRESS_WINDOW_NANOS,\n  );\n  if (!repeated) dismissedPress = Option.some({ shape, at: now });\n  return repeated;\n};\n\nlet lastDismissedPoint: Option.Option<{\n  readonly point: string;\n  readonly at: bigint;\n}> = Option.none();\n\nconst pointOf = (event: EventPayload): string =>\n  Arr.join(\":\")(\n    Arr.map([event.x, event.y, event.button], (part) =>\n      part === undefined ? \"\" : `${part}`,\n    ),\n  );\n\nexport const isDismissalClick = (\n  event: EventPayload,\n  now: bigint = monotonicNanos(),\n): boolean =>\n  Option.exists(\n    lastDismissedPoint,\n    (dismissed) =>\n      dismissed.point === pointOf(event) &&\n      now - dismissed.at <= PRESS_WINDOW_NANOS,\n  );\n\nconst consumedKeystroke = (keystrokeId: number): boolean => {\n  if (Option.contains(dismissedKeystroke, keystrokeId)) return true;\n  dismissedKeystroke = Option.some(keystrokeId);\n  return false;\n};\n\nconst consume = (event: EventPayload, now: bigint): boolean =>\n  Option.match(Option.fromNullishOr(event.keystrokeId), {\n    onNone: () => consumedPress(event, now),\n    onSome: consumedKeystroke,\n  });\n\nconst byDepth: Order.Order<Layer> = Order.mapInput(\n  Order.Number,\n  (layer: Layer) => layer.depth,\n);\n\nconst topmost = (): Option.Option<DismissHandler> =>\n  Option.map(Arr.last(Arr.sort(layers, byDepth)), (layer) => layer.onDismiss);\n\nexport const pushDismissLayer = (\n  onDismiss: DismissHandler,\n  depth: number,\n): (() => void) => {\n  const layer: Layer = { onDismiss, depth };\n  layers = Arr.append(layers, layer);\n  return () => {\n    layers = Arr.filter(layers, (candidate) => candidate !== layer);\n    if (Arr.length(layers) === 0) {\n      dismissedKeystroke = Option.none();\n      dismissedPress = Option.none();\n    }\n  };\n};\n\nexport const dismissTopLayer = (\n  event: EventPayload,\n  now: bigint = monotonicNanos(),\n): boolean => {\n  if (consume(event, now)) return false;\n  return Option.match(topmost(), {\n    onNone: () => false,\n    onSome: (onDismiss) => {\n      lastDismissedPoint = Option.some({ point: pointOf(event), at: now });\n      onDismiss(event);\n      return true;\n    },\n  });\n};\n\nexport const dismissLayerCount = (): number => Arr.length(layers);\n"
    },
    {
      "path": "packages/components/src/internal/dismiss-scope.tsx",
      "target": "@ui/gpuixui/components/internal/dismiss-scope.tsx",
      "type": "registry:component",
      "content": "/** @jsxImportSource @gpuix/react */\nimport { createContext, useContext, type ReactNode } from \"react\";\n\nconst AmbientDepth = createContext(0);\n\nexport const useDismissDepth = (): number => useContext(AmbientDepth) + 1;\n\nexport const DismissScope = ({\n  children,\n}: {\n  readonly children: ReactNode;\n}) => (\n  <AmbientDepth.Provider value={useDismissDepth()}>\n    {children}\n  </AmbientDepth.Provider>\n);\n"
    },
    {
      "path": "packages/components/src/internal/key.ts",
      "target": "@ui/gpuixui/components/internal/key.ts",
      "type": "registry:lib",
      "content": "import type { EventPayload, KeyEvent, Props } from \"@gpuix/react\";\nimport * as Option from \"effect/Option\";\n\nexport type KeyPhase = \"down\" | \"up\";\n\nexport const isActivation = (event: EventPayload, phase: KeyPhase): boolean => {\n  if (event.isHeld === true) return false;\n  if (event.key === \"enter\") return phase === \"down\";\n  return event.key === \"space\" && phase === \"up\";\n};\n\nexport const swallowsDefault = (\n  event: EventPayload,\n  phase: KeyPhase,\n): boolean => event.key === \"space\" && phase === \"down\";\n\nexport const activationHandlers = (\n  activate: (event: KeyEvent) => void,\n  observe: Pick<Props, \"onKeyDown\" | \"onKeyUp\"> = {},\n): Pick<Props, \"onKeyDown\" | \"onKeyUp\"> => ({\n  onKeyDown: (event: KeyEvent) => {\n    if (swallowsDefault(event, \"down\")) event.preventDefault();\n    if (isActivation(event, \"down\")) activate(event);\n    observe.onKeyDown?.(event);\n  },\n  onKeyUp: (event: KeyEvent) => {\n    if (isActivation(event, \"up\")) activate(event);\n    observe.onKeyUp?.(event);\n  },\n});\n\nexport const isEnter = (event: EventPayload): boolean => event.key === \"enter\";\n\nexport const isDown = (event: EventPayload): boolean =>\n  event.key === \"down\" || (event.key === \"n\" && event.modifiers?.ctrl === true);\n\nexport const isUp = (event: EventPayload): boolean =>\n  event.key === \"up\" || (event.key === \"p\" && event.modifiers?.ctrl === true);\n\nexport const isRight = (event: EventPayload): boolean => event.key === \"right\";\n\nexport const isLeft = (event: EventPayload): boolean => event.key === \"left\";\n\nexport const isFirst = (event: EventPayload): boolean => event.key === \"home\";\n\nexport const isLast = (event: EventPayload): boolean => event.key === \"end\";\n\nexport const isPageUp = (event: EventPayload): boolean =>\n  event.key === \"pageup\";\n\nexport const isPageDown = (event: EventPayload): boolean =>\n  event.key === \"pagedown\";\n\nexport const isDismiss = (event: EventPayload): boolean =>\n  event.key === \"escape\";\n\nexport const isTab = (event: EventPayload): boolean => event.key === \"tab\";\n\nexport const isSelectAll = (event: EventPayload): boolean =>\n  event.key === \"a\" &&\n  (event.modifiers?.cmd === true || event.modifiers?.ctrl === true);\n\nexport const isMenuKey = (event: EventPayload): boolean =>\n  (event.key === \"f10\" && event.modifiers?.shift === true) ||\n  event.key === \"contextmenu\";\n\nexport const axisDirection = (\n  event: EventPayload,\n  orientation: \"horizontal\" | \"vertical\",\n): Option.Option<1 | -1> => {\n  if (event.key === \"right\") return Option.some(1);\n  if (event.key === \"left\") return Option.some(-1);\n  if (orientation === \"vertical\") {\n    if (isDown(event)) return Option.some(1);\n    if (isUp(event)) return Option.some(-1);\n  }\n  return Option.none();\n};\n"
    },
    {
      "path": "packages/components/src/internal/local-state.ts",
      "target": "@ui/gpuixui/components/internal/local-state.ts",
      "type": "registry:lib",
      "content": "import { Effect } from \"effect\";\nimport * as Arr from \"effect/Array\";\nimport * as Duration from \"effect/Duration\";\nimport * as Fiber from \"effect/Fiber\";\nimport * as Option from \"effect/Option\";\nimport * as Ref from \"effect/Ref\";\nimport * as SubscriptionRef from \"effect/SubscriptionRef\";\nimport { useEffect, useState, useSyncExternalStore } from \"react\";\n\nexport interface LocalState<A> {\n  readonly state: SubscriptionRef.SubscriptionRef<A>;\n\n  readonly read: () => A;\n\n  readonly subscribe: (listener: () => void) => () => void;\n\n  readonly write: (next: A) => Effect.Effect<void>;\n\n  readonly after: (\n    millis: number,\n    effect: Effect.Effect<void>,\n  ) => Effect.Effect<void>;\n\n  readonly cancel: Effect.Effect<void>;\n\n  readonly running: () => boolean;\n}\n\nexport const makeLocalState = <A>(initial: A): Effect.Effect<LocalState<A>> =>\n  Effect.gen(function* () {\n    const state = yield* SubscriptionRef.make(initial);\n    const timer = yield* Ref.make(Option.none<Fiber.Fiber<void>>());\n    const listeners = yield* Ref.make<ReadonlyArray<() => void>>(Arr.empty());\n\n    const write = Effect.fnUntraced(function* (next: A) {\n      yield* SubscriptionRef.set(state, next);\n      const subscribers = yield* Ref.get(listeners);\n      yield* Effect.sync(() => {\n        Arr.forEach(subscribers, (listener) => listener());\n      });\n    });\n\n    const cancel = Effect.gen(function* () {\n      const held = yield* Ref.getAndSet(timer, Option.none());\n      yield* Option.match(held, {\n        onNone: () => Effect.void,\n        onSome: Fiber.interrupt,\n      });\n    });\n\n    const after = Effect.fnUntraced(function* (\n      millis: number,\n      effect: Effect.Effect<void>,\n    ) {\n      yield* cancel;\n      const fiber = yield* Effect.forkDetach(\n        Effect.sleep(Duration.millis(millis)).pipe(Effect.andThen(effect)),\n      );\n      yield* Ref.set(timer, Option.some(fiber));\n    });\n\n    const running = (): boolean =>\n      Option.exists(\n        Ref.getUnsafe(timer),\n        (fiber) => fiber.pollUnsafe() === undefined,\n      );\n\n    const subscribe = (listener: () => void): (() => void) => {\n      Effect.runSync(\n        Ref.update(listeners, (current) => Arr.append(current, listener)),\n      );\n      return () => {\n        Effect.runSync(\n          Ref.update(listeners, (current) =>\n            Arr.filter(current, (held) => held !== listener),\n          ),\n        );\n      };\n    };\n\n    return {\n      state,\n\n      read: () => SubscriptionRef.getUnsafe(state),\n      subscribe,\n      write,\n      after,\n      cancel,\n      running,\n    };\n  });\n\ninterface Teardown {\n  readonly local: { readonly cancel: Effect.Effect<void> };\n}\n\nexport const useLocalStore = <Store extends Teardown>(\n  make: Effect.Effect<Store>,\n): Store => {\n  const [store] = useState(() => Effect.runSync(make));\n  useEffect(() => () => send(store.local.cancel), [store]);\n  return store;\n};\n\nexport const send = (command: Effect.Effect<void>): void => {\n  Effect.runFork(command);\n};\n\nexport const useLocalState = <A>(local: LocalState<A>): A =>\n  useSyncExternalStore(local.subscribe, local.read, local.read);\n\nexport const useLocalSlice = <A, B>(\n  local: LocalState<A>,\n  select: (state: A) => B,\n): B =>\n  useSyncExternalStore(\n    local.subscribe,\n    () => select(local.read()),\n    () => select(local.read()),\n  );\n"
    },
    {
      "path": "packages/components/src/internal/overlay.ts",
      "target": "@ui/gpuixui/components/internal/overlay.ts",
      "type": "registry:lib",
      "content": "import type { StyleDesc } from \"@gpuix/react\";\nimport { cn } from \"../../tw/index.js\";\nimport * as Arr from \"effect/Array\";\nimport * as Option from \"effect/Option\";\nimport { recipeStyle } from \"./recipe.js\";\nimport {\n  alpha,\n  elevationShadow,\n  type BoxShadow,\n  type ElevationLevel,\n  type Theme,\n} from \"./theme.js\";\n\nexport const OVERLAY_WASH = 0.55;\n\nexport const overlayVeilColor = (theme: Theme): string =>\n  alpha(theme.colors.background, OVERLAY_WASH);\n\nconst isEdge = (shadow: BoxShadow): boolean =>\n  shadow.blurRadius === 0 && shadow.spreadRadius > 0;\n\nconst shadows = (painted: StyleDesc[\"boxShadow\"]): ReadonlyArray<BoxShadow> =>\n  Option.match(Option.fromNullishOr(painted), {\n    onNone: () => [],\n    onSome: (value) => Arr.ensure(value),\n  });\n\nexport const overlaySurfaceStyle = (\n  recipe: string,\n  className: string | undefined,\n  theme: Theme,\n  elevation?: ElevationLevel,\n): StyleDesc => {\n  const style = recipeStyle(cn(recipe, className), theme);\n  const lift = Option.fromNullishOr(elevation).pipe(\n    Option.flatMap((level) =>\n      Option.fromNullishOr(elevationShadow(theme, level)),\n    ),\n  );\n\n  return Option.match(lift, {\n    onNone: () => style,\n    onSome: (shadow) => {\n      const painted = shadows(style.boxShadow);\n      const lost = Arr.every(painted, isEdge) && painted.length > 0;\n      return lost ? { ...style, boxShadow: [shadow, ...painted] } : style;\n    },\n  });\n};\n"
    },
    {
      "path": "packages/components/src/internal/parts.ts",
      "target": "@ui/gpuixui/components/internal/parts.ts",
      "type": "registry:lib",
      "content": "import * as Arr from \"effect/Array\";\nimport * as P from \"effect/Predicate\";\nimport {\n  Children,\n  Fragment,\n  isValidElement,\n  type ReactElement,\n  type ReactNode,\n} from \"react\";\n\nexport type PartComponent = (props: never) => ReactNode;\n\nexport type PartChildren =\n  | ReactElement<unknown>\n  | boolean\n  | null\n  | undefined\n  | ReadonlyArray<PartChildren>;\n\nexport interface PartsContract {\n  readonly parent: string;\n\n  readonly family: ReadonlyArray<PartComponent>;\n\n  readonly accepts: ReadonlyArray<PartComponent>;\n\n  readonly hint?: string;\n}\n\nconst componentName = (type: unknown): string =>\n  P.isString(type)\n    ? type\n    : P.isFunction(type)\n      ? type.name || \"anonymous\"\n      : \"element\";\n\nconst fragmentChildren = (element: ReactElement<unknown>): ReactNode =>\n  hasChildren(element.props) ? element.props.children : undefined;\n\nconst hasChildren = (\n  value: unknown,\n): value is { readonly children?: ReactNode } =>\n  P.isObject(value) && \"children\" in value;\n\nconst leaves = (children: ReactNode): ReadonlyArray<unknown> =>\n  Arr.flatMap(Children.toArray(children), (child) =>\n    isValidElement<unknown>(child) && child.type === Fragment\n      ? leaves(fragmentChildren(child))\n      : [child],\n  );\n\nexport const assertParts = (\n  contract: PartsContract,\n  children: ReactNode,\n): void => {\n  Arr.forEach(leaves(children), (leaf) => {\n    if (!isValidElement(leaf)) return;\n    if (Arr.some(contract.accepts, (part) => part === leaf.type)) return;\n    if (!Arr.some(contract.family, (part) => part === leaf.type)) return;\n\n    throw new Error(\n      `${componentName(leaf.type)} cannot be used inside ${contract.parent}.` +\n        (contract.hint === undefined ? \"\" : ` ${contract.hint}`),\n    );\n  });\n};\n"
    },
    {
      "path": "packages/components/src/internal/placement.ts",
      "target": "@ui/gpuixui/components/internal/placement.ts",
      "type": "registry:lib",
      "content": "import type { FloatingAlign, FloatingSide } from \"@gpuix/react/floating\";\nimport { Match } from \"effect\";\nimport * as Schema from \"effect/Schema\";\n\nexport interface FloatingBounds {\n  readonly x: number;\n  readonly y: number;\n  readonly width: number;\n  readonly height: number;\n}\n\nexport interface WindowBounds {\n  readonly width: number;\n  readonly height: number;\n}\n\nexport interface PlacementInput {\n  readonly side: unknown;\n\n  readonly align: unknown;\n  readonly trigger: FloatingBounds;\n\n  readonly surface: FloatingBounds;\n  readonly window: WindowBounds;\n  readonly margin: number;\n}\n\nexport interface Placement {\n  readonly side: FloatingSide;\n  readonly align: FloatingAlign;\n  readonly alignOffset: number;\n}\n\nconst PlacementSide = Schema.Literals([\"top\", \"right\", \"bottom\", \"left\"]);\n\nexport const isAlign = Schema.is(Schema.Literals([\"start\", \"center\", \"end\"]));\n\nconst sideOf = (side: unknown): FloatingSide =>\n  Schema.is(PlacementSide)(side) ? side : \"bottom\";\n\nconst alignOf = (align: unknown): FloatingAlign =>\n  isAlign(align) ? align : \"start\";\n\nconst oppositeSide = (side: unknown): FloatingSide =>\n  Match.value(sideOf(side)).pipe(\n    Match.when(\"top\", () => \"bottom\" as const),\n    Match.when(\"bottom\", () => \"top\" as const),\n    Match.when(\"left\", () => \"right\" as const),\n    Match.when(\"right\", () => \"left\" as const),\n    Match.exhaustive,\n  );\n\nconst roomOn = (side: unknown, input: PlacementInput): number =>\n  Match.value(sideOf(side)).pipe(\n    Match.when(\"top\", () => input.trigger.y - input.margin),\n    Match.when(\n      \"bottom\",\n      () =>\n        input.window.height -\n        input.margin -\n        (input.trigger.y + input.trigger.height),\n    ),\n    Match.when(\"left\", () => input.trigger.x - input.margin),\n    Match.when(\n      \"right\",\n      () =>\n        input.window.width -\n        input.margin -\n        (input.trigger.x + input.trigger.width),\n    ),\n    Match.exhaustive,\n  );\n\nconst extentOn = (side: unknown, surface: FloatingBounds): number =>\n  Match.value(sideOf(side)).pipe(\n    Match.when(\"top\", () => surface.height),\n    Match.when(\"bottom\", () => surface.height),\n    Match.when(\"left\", () => surface.width),\n    Match.when(\"right\", () => surface.width),\n    Match.exhaustive,\n  );\n\nexport const resolveSide = (input: PlacementInput): FloatingSide => {\n  const side = sideOf(input.side);\n  const extent = extentOn(side, input.surface);\n  if (roomOn(side, input) >= extent) return side;\n\n  const opposite = oppositeSide(side);\n  const oppositeRoom = roomOn(opposite, input);\n  if (oppositeRoom >= extentOn(opposite, input.surface)) return opposite;\n\n  return oppositeRoom > roomOn(side, input) ? opposite : side;\n};\n\nconst alignOffsetOn = (\n  side: unknown,\n  align: unknown,\n  trigger: FloatingBounds,\n  surface: FloatingBounds,\n): number =>\n  Match.value(alignOf(align)).pipe(\n    Match.when(\"center\", () =>\n      Match.value(sideOf(side)).pipe(\n        Match.when(\"top\", () => (trigger.width - surface.width) / 2),\n        Match.when(\"bottom\", () => (trigger.width - surface.width) / 2),\n        Match.when(\"left\", () => (trigger.height - surface.height) / 2),\n        Match.when(\"right\", () => (trigger.height - surface.height) / 2),\n        Match.exhaustive,\n      ),\n    ),\n    Match.when(\"start\", () => 0),\n    Match.when(\"end\", () => 0),\n    Match.exhaustive,\n  );\n\nconst hostAlign = (align: FloatingAlign): \"start\" | \"end\" =>\n  align === \"end\" ? \"end\" : \"start\";\n\nexport const requestedPlacement = (\n  side: unknown,\n  align: unknown,\n): Placement => ({\n  side: sideOf(side),\n  align: hostAlign(alignOf(align)),\n  alignOffset: 0,\n});\n\nexport const resolvePlacement = (input: PlacementInput): Placement => {\n  const side = resolveSide(input);\n  return {\n    side,\n    align: hostAlign(alignOf(input.align)),\n    alignOffset: alignOffsetOn(side, input.align, input.trigger, input.surface),\n  };\n};\n"
    },
    {
      "path": "packages/components/src/internal/presence.tsx",
      "target": "@ui/gpuixui/components/internal/presence.tsx",
      "type": "registry:component",
      "content": "/** @jsxImportSource @gpuix/react */\nimport type { MotionProps } from \"@gpuix/react\";\nimport {\n  delayedTiming,\n  exitWindowMs,\n  fadeFrom,\n  fadeFromAnchor,\n  fadeFromSide,\n  fadeOnly,\n  presenceMotion as motionOfPresence,\n  presenceStyle,\n  transitionWindowMs,\n  type PresenceFrames,\n  type PresenceHitRule,\n  type PresenceSide,\n  type PresenceTiming,\n  type PresenceTransition,\n} from \"../../motion/presence.js\";\nimport {\n  MotionProvider,\n  useMotionPreference,\n  useSurfacePresence,\n  useSurfaceTiming,\n  type MotionProviderProps,\n  type SurfacePresence,\n} from \"../../motion/react/presence.js\";\nimport {\n  motionTiming,\n  type MotionLevel,\n  type MotionPreference,\n} from \"../../motion/timing.js\";\n\nexport { MotionProvider, useMotionPreference, type MotionProviderProps };\n\nexport type SurfaceFrames = PresenceFrames;\n\nexport type SurfaceTiming = PresenceTiming;\n\nexport type PanelSide = PresenceSide;\n\nexport {\n  delayedTiming,\n  exitWindowMs,\n  fadeFrom,\n  fadeFromAnchor,\n  fadeFromSide,\n  fadeOnly,\n  presenceStyle,\n  transitionWindowMs,\n};\nexport type { PresenceHitRule };\n\nexport { useSurfacePresence, useSurfaceTiming, type SurfacePresence };\n\nexport const moveTiming = (\n  level: MotionLevel,\n  preference: MotionPreference,\n): PresenceTransition => motionTiming(level, { phase: \"standard\", preference });\n\nexport const useMoveTiming = (level: MotionLevel): PresenceTransition =>\n  moveTiming(level, useMotionPreference());\n\nexport const presenceMotion = (\n  frames: SurfaceFrames,\n  presence: SurfacePresence,\n  timing: SurfaceTiming = presence.timing,\n): MotionProps => motionOfPresence(frames, presence.present, timing);\n\nexport const PresenceShield = ({ present }: { readonly present: boolean }) =>\n  present ? null : (\n    <div\n      testId=\"presence-shield\"\n      style={{ position: \"absolute\", top: 0, right: 0, bottom: 0, left: 0 }}\n    />\n  );\n\nexport const presenceTabStop = (\n  present: boolean,\n): { readonly tabIndex?: number } => (present ? {} : { tabIndex: -1 });\n"
    },
    {
      "path": "packages/components/src/internal/recipe.ts",
      "target": "@ui/gpuixui/components/internal/recipe.ts",
      "type": "registry:lib",
      "content": "import type { StyleDesc } from \"@gpuix/react\";\nimport { createRecipeCache } from \"../../tw/index.js\";\nimport type { Theme } from \"./theme.js\";\n\nexport const recipeStyle: (recipe: string, theme: Theme) => StyleDesc =\n  createRecipeCache(512);\n"
    },
    {
      "path": "packages/components/src/internal/ref.ts",
      "target": "@ui/gpuixui/components/internal/ref.ts",
      "type": "registry:lib",
      "content": "import type { Ref, RefCallback } from \"react\";\nimport { useCallback } from \"react\";\n\nconst assign = <T>(ref: Ref<T> | undefined, value: T): void => {\n  if (ref === null || ref === undefined) return;\n  if (typeof ref === \"function\") {\n    ref(value);\n    return;\n  }\n  ref.current = value;\n};\n\nexport const useMergedRef = <T>(\n  internal: Ref<T>,\n  caller: Ref<T> | undefined,\n): RefCallback<T> =>\n  useCallback(\n    (value: T) => {\n      assign(internal, value);\n      assign(caller, value);\n    },\n    [internal, caller],\n  );\n"
    },
    {
      "path": "packages/components/src/internal/theme.ts",
      "target": "@ui/gpuixui/components/internal/theme.ts",
      "type": "registry:lib",
      "content": "import type { StyleDesc } from \"@gpuix/react\";\nimport * as Schema from \"effect/Schema\";\nimport {\n  alpha,\n  avatarPixels,\n  avatarSize,\n  brandTextOn,\n  controlFocusRing,\n  controlHeight,\n  controlPaddingX,\n  currentPlatform,\n  darkTheme,\n  disabledAction,\n  disabledOpacity,\n  elevationShadow,\n  filledHover,\n  filledPressed,\n  findHighlight,\n  focusRing,\n  keyboardFocusRing,\n  lightTheme,\n  nativeTextTheme,\n  pointerWash,\n  selectionOn,\n  statusTone,\n  syntaxColors,\n  targetSize,\n  textStyle,\n  type BoxShadow,\n  type ElevationLevel,\n  type FindHighlightSource,\n  type NativeTextFill,\n  type PlatformName,\n  type PointerWashSurface,\n  type StatusTone,\n  type SyntaxColors,\n  type SyntaxRole,\n  type TextRole,\n  type Theme,\n  type ThemeColors,\n} from \"../../tokens/index.js\";\n\nexport {\n  alpha,\n  avatarPixels,\n  avatarSize,\n  controlFocusRing,\n  controlHeight,\n  controlPaddingX,\n  currentPlatform,\n  darkTheme,\n  disabledAction,\n  disabledOpacity,\n  elevationShadow,\n  filledHover,\n  filledPressed,\n  findHighlight,\n  focusRing,\n  keyboardFocusRing,\n  lightTheme,\n  nativeTextTheme,\n  statusTone,\n  syntaxColors,\n  targetSize,\n  textStyle,\n};\nexport type {\n  BoxShadow,\n  ElevationLevel,\n  FindHighlightSource,\n  NativeTextFill,\n  PlatformName,\n  StatusTone,\n  SyntaxColors,\n  SyntaxRole,\n  TextRole,\n  Theme,\n};\nexport { ThemeProvider, useTheme } from \"../../tokens/react.js\";\n\nexport const keyboardRing = (theme: Theme, invalid = false): StyleDesc =>\n  controlFocusRing(theme, { invalid }) ?? {};\n\nexport interface ControlRingState {\n  readonly disabled?: boolean;\n\n  readonly invalid?: boolean;\n}\n\nexport const controlRing = (\n  theme: Theme,\n  state: ControlRingState = {},\n): StyleDesc => controlFocusRing(theme, state) ?? {};\n\nexport const pressWash = (theme: Theme, replaced: PointerWashSurface): string =>\n  pointerWash(theme, \"active\", replaced) ?? theme.colors.active;\n\nexport const selectionWash = (theme: Theme): StyleDesc => ({\n  selectionColor: theme.colors.selection,\n});\n\nexport const keepContent: StyleDesc = { keyboardFocusDim: false };\n\nexport const disabledFade = (\n  disabled: boolean,\n): { readonly opacity: number } | undefined =>\n  disabled ? { opacity: disabledOpacity } : undefined;\n\nconst Tones = Schema.Literals([\"info\", \"success\", \"warning\", \"danger\"]);\n\nexport type Tone = typeof Tones.Type;\n\nexport const toneOf = (value: unknown): Tone =>\n  Schema.is(Tones)(value) ? value : \"info\";\n\nexport interface ToneStyle {\n  readonly fg: string;\n  readonly bg: string;\n  readonly border: string;\n}\n\nconst TOKEN_TONE: Readonly<Record<Tone, StatusTone>> = {\n  info: \"info\",\n  success: \"success\",\n  warning: \"warning\",\n  danger: \"destructive\",\n};\n\nexport const tone = (theme: Theme, value: Tone): ToneStyle => {\n  const { background, border, foreground } = statusTone(\n    theme,\n    TOKEN_TONE[value],\n  );\n  return { bg: background, border, fg: foreground };\n};\n\nconst softRoles: Readonly<Record<Tone, keyof ThemeColors>> = {\n  info: \"infoSoft\",\n  success: \"successSoft\",\n  warning: \"warningSoft\",\n  danger: \"destructiveSoft\",\n};\n\nexport const messageLink = (theme: Theme, value: Tone): string =>\n  brandTextOn(theme, softRoles[value]);\n\nexport const messageSelection = (theme: Theme, value: Tone): string =>\n  selectionOn(theme, softRoles[value]);\n\nexport const toneSurface = (theme: Theme, value: Tone): StyleDesc => {\n  const { bg, border, fg } = tone(theme, value);\n  return {\n    backgroundColor: bg,\n    color: fg,\n    borderWidth: theme.borderWidth.thin,\n    borderColor: border,\n  };\n};\n"
    },
    {
      "path": "packages/components/src/internal/use-placement.ts",
      "target": "@ui/gpuixui/components/internal/use-placement.ts",
      "type": "registry:lib",
      "content": "import { useGpuix, type PublicInstance } from \"@gpuix/react\";\nimport type { FloatingAlign, FloatingSide } from \"@gpuix/react/floating\";\nimport * as Option from \"effect/Option\";\nimport { useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport {\n  requestedPlacement,\n  resolvePlacement,\n  type Placement,\n} from \"./placement.js\";\n\nexport interface UsePlacementInput {\n  readonly open: boolean;\n  readonly side: FloatingSide;\n  readonly align: FloatingAlign;\n  readonly margin: number;\n  readonly trigger: RefObject<PublicInstance | null>;\n  readonly surface: RefObject<PublicInstance | null>;\n}\n\nconst boundsOf = (\n  renderer: ReturnType<typeof useGpuix>[\"renderer\"],\n  instance: PublicInstance | null,\n): Option.Option<{ x: number; y: number; width: number; height: number }> =>\n  Option.flatMap(Option.fromNullishOr(instance), (element) =>\n    Option.fromNullishOr(renderer?.getElementBounds?.(element.id)),\n  );\n\nexport const usePlacement = ({\n  open,\n  side,\n  align,\n  margin,\n  trigger,\n  surface,\n}: UsePlacementInput): Placement => {\n  const renderer = useGpuix().renderer;\n  const [placement, setPlacement] = useState<Option.Option<Placement>>(\n    Option.none(),\n  );\n  const measuredFor = useRef<string | null>(null);\n  const key = `${side}:${align}:${margin}`;\n\n  useLayoutEffect(() => {\n    if (!open) {\n      measuredFor.current = null;\n      setPlacement(Option.none());\n      return;\n    }\n    if (measuredFor.current === key) return;\n\n    const measured = Option.all({\n      trigger: boundsOf(renderer, trigger.current),\n      surface: boundsOf(renderer, surface.current),\n      window: Option.fromNullishOr(renderer?.getWindowSize?.()),\n    });\n    if (Option.isNone(measured)) return;\n\n    measuredFor.current = key;\n    setPlacement(\n      Option.some(resolvePlacement({ ...measured.value, side, align, margin })),\n    );\n  }, [align, key, margin, open, renderer, side, surface, trigger]);\n\n  return Option.getOrElse(placement, () => requestedPlacement(side, align));\n};\n"
    },
    {
      "path": "packages/components/src/popover.tsx",
      "target": "@ui/gpuixui/components/popover.tsx",
      "type": "registry:component",
      "content": "/** @jsxImportSource @gpuix/react */\nimport type { EventPayload, PublicInstance } from \"@gpuix/react\";\nimport { useGpuix } from \"@gpuix/react\";\nimport {\n  FloatingLayer,\n  floatingRootStyle,\n  mergeStyles,\n  type FloatingAlign,\n  type FloatingContentProps,\n} from \"@gpuix/react/floating\";\nimport { POPOVER_CONTENT } from \"../tw/index.js\";\nimport {\n  Button,\n  type ButtonProps as PrimitiveButtonProps,\n} from \"../primitives/button.js\";\nimport { Match } from \"effect\";\nimport {\n  createContext,\n  useContext,\n  useLayoutEffect,\n  useMemo,\n  useRef,\n  type RefObject,\n} from \"react\";\nimport { useControllableState } from \"./internal/controllable.js\";\nimport { dismissTopLayer, pushDismissLayer } from \"./internal/dismiss-layer.js\";\nimport { DismissScope, useDismissDepth } from \"./internal/dismiss-scope.js\";\nimport { isDismiss, isTab } from \"./internal/key.js\";\nimport { overlaySurfaceStyle } from \"./internal/overlay.js\";\nimport {\n  assertParts,\n  type PartChildren,\n  type PartComponent,\n  type PartsContract,\n} from \"./internal/parts.js\";\nimport {\n  fadeFromAnchor,\n  PresenceShield,\n  presenceMotion,\n  presenceStyle,\n  useSurfacePresence,\n  useSurfaceTiming,\n} from \"./internal/presence.js\";\nimport { isAlign } from \"./internal/placement.js\";\nimport { isDismissalClick } from \"./internal/dismiss-layer.js\";\nimport { useMergedRef } from \"./internal/ref.js\";\nimport { useTheme } from \"./internal/theme.js\";\nimport { usePlacement } from \"./internal/use-placement.js\";\n\nconst popoverAlign = (align: unknown): FloatingAlign =>\n  isAlign(align) ? align : \"center\";\n\ninterface PopoverContextValue {\n  readonly open: boolean;\n  readonly setOpen: (open: boolean) => void;\n  readonly trigger: RefObject<PublicInstance | null>;\n}\n\nconst PopoverContext = createContext<PopoverContextValue | undefined>(\n  undefined,\n);\n\nconst usePopoverContext = (): PopoverContextValue => {\n  const value = useContext(PopoverContext);\n  if (value === undefined) {\n    throw new Error(\"Popover parts must be used inside Popover\");\n  }\n  return value;\n};\n\nexport interface PopoverProps {\n  readonly open?: boolean;\n\n  readonly defaultOpen?: boolean;\n  readonly onOpenChange?: (open: boolean) => void;\n  readonly children?: PartChildren;\n}\n\nexport const Popover = ({\n  open: openProp,\n  defaultOpen = false,\n  onOpenChange,\n  children,\n}: PopoverProps) => {\n  const [open, setOpen] = useControllableState({\n    value: openProp,\n    defaultValue: defaultOpen,\n    onChange: onOpenChange,\n  });\n  const trigger = useRef<PublicInstance | null>(null);\n\n  const context = useMemo<PopoverContextValue>(\n    () => ({ open, setOpen, trigger }),\n    [open, setOpen],\n  );\n\n  assertParts(popoverRoot, children);\n\n  return (\n    <PopoverContext.Provider value={context}>\n      <div style={floatingRootStyle()}>{children}</div>\n    </PopoverContext.Provider>\n  );\n};\n\nexport interface PopoverTriggerProps extends PrimitiveButtonProps {\n  readonly onClick?: (event: EventPayload) => void;\n}\n\nexport const PopoverTrigger = ({\n  onClick,\n  onActivate,\n  ref,\n  variant = \"secondary\",\n  ...rest\n}: PopoverTriggerProps) => {\n  const { open, setOpen, trigger } = usePopoverContext();\n  const setTrigger = useMergedRef<PublicInstance | null>(trigger, ref);\n\n  return (\n    <Button\n      {...rest}\n      ref={setTrigger}\n      variant={variant}\n      aria-expanded={open}\n      onActivate={(event) => {\n        (onActivate ?? onClick)?.(event);\n\n        if (isDismissalClick(event)) return;\n        setOpen(!open);\n      }}\n    />\n  );\n};\n\nexport interface PopoverContentProps extends FloatingContentProps {\n  readonly className?: string;\n\n  readonly side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n\n  readonly align?: \"start\" | \"center\" | \"end\";\n\n  readonly sideOffset?: number;\n\n  readonly collisionPadding?: number;\n\n  readonly alignOffset?: number;\n}\n\nexport const PopoverContent = ({\n  className,\n  side = \"bottom\",\n  align = \"center\",\n  sideOffset = 6,\n  alignOffset = 0,\n  collisionPadding = 8,\n  children,\n  onKeyDown,\n  onMouseDownOutside,\n  style,\n  ref,\n  ...rest\n}: PopoverContentProps) => {\n  const theme = useTheme();\n  const { open, setOpen, trigger } = usePopoverContext();\n  const renderer = useGpuix().renderer;\n  const surface = useRef<PublicInstance | null>(null);\n  const setSurface = useMergedRef<PublicInstance | null>(surface, ref);\n  const timing = useSurfaceTiming(\"normal\");\n  const presence = useSurfacePresence(open, timing);\n  const placement = usePlacement({\n    open: presence.mounted,\n    side,\n    align: popoverAlign(align),\n    margin: collisionPadding,\n    trigger,\n    surface,\n  });\n\n  const close = useRef<() => void>(() => undefined);\n  useLayoutEffect(() => {\n    close.current = () => setOpen(false);\n  });\n\n  const depth = useDismissDepth();\n  useLayoutEffect(() => {\n    if (!open) return;\n    return pushDismissLayer((event) => {\n      close.current();\n      if (event.eventType === \"keyDown\") {\n        const target = trigger.current;\n        if (target !== null) renderer?.focusElement?.(target.id);\n        return;\n      }\n    }, depth);\n  }, [depth, open, renderer, trigger]);\n\n  if (!presence.mounted) return null;\n\n  return (\n    <FloatingLayer\n      motion={presenceMotion(fadeFromAnchor(placement.side, 8), presence)}\n      side={placement.side}\n      align={placement.align}\n      sideOffset={sideOffset}\n      alignOffset={placement.alignOffset + alignOffset}\n      collisionPadding={collisionPadding}\n      tabIndex={-1}\n      autoFocus\n      ref={setSurface}\n      {...rest}\n      onMouseDownOutside={(event) => {\n        onMouseDownOutside?.(event);\n        dismissTopLayer(event);\n      }}\n      onKeyDown={(event) => {\n        onKeyDown?.(event);\n        Match.value(event).pipe(\n          Match.when(isDismiss, (value) => {\n            dismissTopLayer(value);\n          }),\n\n          Match.when(isTab, () => setOpen(false)),\n          Match.orElse(() => undefined),\n        );\n      }}\n      style={mergeStyles(\n        mergeStyles(\n          overlaySurfaceStyle(POPOVER_CONTENT, className, theme, \"lg\"),\n\n          {\n            minWidth: 200,\n            position: \"relative\",\n            ...presenceStyle(presence.present),\n          },\n        ),\n        style,\n      )}\n    >\n      <DismissScope>{children}</DismissScope>\n      <PresenceShield present={presence.present} />\n    </FloatingLayer>\n  );\n};\n\nconst popoverParts: ReadonlyArray<PartComponent> = [\n  Popover,\n  PopoverTrigger,\n  PopoverContent,\n];\n\nconst popoverRoot: PartsContract = {\n  parent: \"Popover\",\n  family: popoverParts,\n  accepts: [PopoverTrigger, PopoverContent],\n  hint: \"Put PopoverTrigger and PopoverContent directly inside Popover.\",\n};\n\nexport const popoverMeta = {\n  name: \"Popovers\",\n  tier: 2,\n  status: \"done\",\n  gpuixSupport: \"partial\",\n  limitations: [\n    \"positioning is GPUix's anchored layer: it snaps but does not flip, so the component flips once when the snapped surface would cover its trigger; no arrow or custom anchor element\",\n    'the runtime\\'s `align=\"center\"` centres on the containing block, so the component maps it to a measured `start` offset; the snap margin wins near a window edge',\n    \"an outside press gives focus to whatever was pressed, so focus is not returned to the trigger (Escape is)\",\n  ],\n  docs: \"docs/popover.mdx\",\n  example: \"examples/popover.example.tsx\",\n  testFile: \"src/behaviour/popover.test.tsx\",\n} as const;\n"
    }
  ],
  "docs": "[Date picker](https://gpuixui.sudokw.com/components/date-picker) — These are GPUix native components: the files render through GPUix's reconciler against `@gpuix/react`, not the DOM, and need the per-platform `@gpuix/native` binding. The CLI installs the `@gpuixui/*` runtime the components import as registry items, so the copied tree resolves on its own; wrap it in `ThemeProvider` before it renders.",
  "meta": {
    "url": "/components/date-picker",
    "kind": "component",
    "runtime": "gpuix",
    "registry": "gpuixui"
  }
}