{"version":3,"file":"task-composer-form-WW_Dvf9R.mjs","names":["Calendar"],"sources":["../../../contacts/core/src/contacts-api-context.ts","../../../contacts/core/src/translation-api-context.ts","../../../contacts/core/src/parse-task-body.ts","../../../contacts/core/src/iso-date.ts","../../../contacts/ui/src/portal/utils/format-date.ts","../../../contacts/core/src/query-keys.ts","../../../contacts/core/src/hooks/use-infinite-contacts.ts","../../../contacts/ui/src/portal/components/tasks/task-composer-form.tsx"],"sourcesContent":["import { createContext, use, type Provider } from \"react\";\nimport type { ContactsApi } from \"./contacts-api\";\nimport type { NotesApi } from \"./notes-api\";\nimport type { TasksApi } from \"./tasks-api\";\nimport type { GroupsApi } from \"./groups-api\";\n\nexport interface ContactsDomainApi {\n  contacts: ContactsApi;\n  notes: NotesApi;\n  tasks: TasksApi;\n  groups?: GroupsApi;\n}\n\nconst ContactsApiContext = createContext<ContactsDomainApi | null>(null);\n\nexport const ContactsApiProvider: Provider<ContactsDomainApi | null> =\n  ContactsApiContext.Provider;\n\nexport function useContactsDomainApi(): ContactsDomainApi {\n  const api = use(ContactsApiContext);\n  if (!api) {\n    throw new Error(\n      \"useContactsDomainApi must be used within a ContactsApiProvider\",\n    );\n  }\n  return api;\n}\n\nexport function useContactsCrud(): ContactsApi {\n  return useContactsDomainApi().contacts;\n}\n\nexport function useNotesApi(): NotesApi {\n  return useContactsDomainApi().notes;\n}\n\nexport function useTasksApi(): TasksApi {\n  return useContactsDomainApi().tasks;\n}\n\n/** Returns GroupsApi if the provider supplies one, otherwise null. */\nexport function useGroupsApi(): GroupsApi | null {\n  return useContactsDomainApi().groups ?? null;\n}\n","import { use, type Provider } from \"react\";\nimport { createTranslationContext } from \"@fluid-app/i18n/translation-api-context-factory\";\nimport type { TranslationApi } from \"@fluid-app/i18n/translation-api\";\nimport type { ContactsDict } from \"./translation-dictionary\";\n\nconst {\n  Context,\n  Provider: ContactsProvider,\n  useTranslation,\n} = createTranslationContext<ContactsDict>(\"Contacts\");\n\nexport const ContactsTranslationProvider: Provider<TranslationApi<ContactsDict> | null> =\n  ContactsProvider;\nexport const useContactsTranslation = useTranslation;\n\n/**\n * Like `useContactsTranslation()` but returns `null` instead of throwing\n * when no `ContactsTranslationProvider` is present in the tree.\n * Useful for shared hooks consumed by both portal (has provider) and admin (no provider).\n */\nexport function useOptionalContactsTranslation(): TranslationApi<ContactsDict> | null {\n  return use(Context);\n}\n","/**\n * Tasks store both a title (first line) and an optional body separated by a\n * blank line. This is the canonical convention used by the task editor and\n * by every consumer that displays tasks (contacts UI list, portal todo\n * widget). Drift across consumers would mean some surfaces show \"Title\\n\\n\n * body details\" verbatim while others split correctly — keep the delimiter\n * convention in one place.\n */\nexport function parseTaskBody(raw: string): { title: string; body: string } {\n  const split = raw.indexOf(\"\\n\\n\");\n  if (split >= 0) {\n    return {\n      title: raw.slice(0, split),\n      body: raw.slice(split + 2),\n    };\n  }\n  return { title: raw, body: \"\" };\n}\n","/**\n * Format a date as YYYY-MM-DD in the renderer's local timezone, optionally\n * shifted by `offsetDays`. Use this for due-date inputs where \"today\" must\n * resolve to the user's local calendar date — never `toISOString().slice(0, 10)`,\n * which returns the UTC date and silently rolls over a day for users east/west\n * of UTC at the wrong hours.\n */\nexport function isoDate(offsetDays: number, now: Date = new Date()): string {\n  const d = new Date(now);\n  d.setDate(d.getDate() + offsetDays);\n  const yyyy = d.getFullYear();\n  const mm = String(d.getMonth() + 1).padStart(2, \"0\");\n  const dd = String(d.getDate()).padStart(2, \"0\");\n  return `${yyyy}-${mm}-${dd}`;\n}\n\n/**\n * Return a Date pinned to local midnight of the calendar day represented by\n * `input`. Use this whenever you need to compare two due dates by calendar day\n * (overdue / today / tomorrow / future).\n *\n * Why not just `new Date(input)`?  `new Date(\"YYYY-MM-DD\")` parses the string\n * as UTC midnight, which lands on the *previous* calendar day in any UTC−\n * timezone — a task due \"May 1\" then reads as April 30 for a user in the\n * Americas, classifying it as \"Overdue\" all day. Parse the date components\n * directly so the calendar-day intent of the string is preserved.\n */\nexport function startOfLocalDay(input: Date | string): Date {\n  if (typeof input === \"string\") {\n    const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(input);\n    if (match?.[1] && match[2] && match[3]) {\n      return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));\n    }\n  }\n  const d = typeof input === \"string\" ? new Date(input) : input;\n  return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n}\n","import { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\n\n/** Detect bare YYYY-MM-DD and ISO strings whose time is exactly midnight. */\nexport const ALL_DAY_PATTERN =\n  /^\\d{4}-\\d{2}-\\d{2}(?:$|T00:00(?::00(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2}|Z)?)$/;\n\n/**\n * Detect non-Z ISO date-time strings that should stay on the timed path instead\n * of being classified as all-day. Editors may read the written date/time fields\n * directly. A trailing `Z` is intentionally excluded; UTC midnight values may\n * still be handled as all-day by ALL_DAY_PATTERN.\n */\nexport const LOCAL_TIMED_DUE_AT_PATTERN =\n  /^\\d{4}-\\d{2}-\\d{2}T(\\d{2}):(\\d{2})(?::\\d{2}(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2})?$/;\n\nexport function isAllDay(dateStr: string): boolean {\n  return ALL_DAY_PATTERN.test(dateStr);\n}\n\nexport function toDateInputValue(dueDate: string | null | undefined): string {\n  if (!dueDate) return \"\";\n  if (LOCAL_TIMED_DUE_AT_PATTERN.test(dueDate)) {\n    return dueDate.slice(0, 10);\n  }\n\n  if (isAllDay(dueDate)) {\n    const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(dueDate);\n    if (match?.[1] && match[2] && match[3])\n      return `${match[1]}-${match[2]}-${match[3]}`;\n    return \"\";\n  }\n\n  const d = new Date(dueDate);\n  if (Number.isNaN(d.getTime())) return \"\";\n  return isoDate(0, d);\n}\n\nexport function getLocalCalendarDayDiff(\n  dateStr: string,\n  now: Date = new Date(),\n): number | null {\n  const date = startOfLocalDay(dateStr);\n  if (Number.isNaN(date.getTime())) return null;\n\n  const today = startOfLocalDay(now);\n  const dateUtc = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());\n  const todayUtc = Date.UTC(\n    today.getFullYear(),\n    today.getMonth(),\n    today.getDate(),\n  );\n\n  return Math.round((dateUtc - todayUtc) / (1000 * 60 * 60 * 24));\n}\n\nexport function formatDateForDisplay(dateStr: string, locale?: string): string {\n  const normalizedLocale = locale?.replace(/_/g, \"-\") ?? \"en-US\";\n  // All-day / midnight values: preserve the represented calendar date\n  // regardless of local timezone. Genuine timed instants are parsed with\n  // new Date() so the locale string reflects the instant.\n  const date = isAllDay(dateStr) ? startOfLocalDay(dateStr) : new Date(dateStr);\n  return date.toLocaleDateString(normalizedLocale, {\n    month: \"short\",\n    day: \"numeric\",\n    year: \"numeric\",\n  });\n}\n","export const CONTACTS_QUERY_KEYS = {\n  all: (prefix: string) => [prefix] as const,\n  list: (prefix: string) =>\n    [...CONTACTS_QUERY_KEYS.all(prefix), \"list\"] as const,\n  detail: (prefix: string, id: string) =>\n    [...CONTACTS_QUERY_KEYS.all(prefix), \"detail\", id] as const,\n} as const;\n\nexport const contactsKeys = {\n  activities: (contactId: string) =>\n    [\"portal-contacts\", \"activities\", contactId] as const,\n  tasks: (contactId: string) =>\n    [\"portal-contacts\", \"tasks\", contactId] as const,\n  notes: (contactId: string) =>\n    [\"portal-contacts\", \"notes\", contactId] as const,\n  orders: (contactId: string) => [\"rep-contacts\", \"orders\", contactId] as const,\n  subscriptionOrders: (contactId: string) =>\n    [\"rep-contacts\", \"subscription-orders\", contactId] as const,\n  groups: () => [\"portal-contacts\", \"groups\"] as const,\n  groupMembers: (groupName: string) =>\n    [\"portal-contacts\", \"group-members\", groupName] as const,\n  groupAddSearch: (groupName: string, search: string) =>\n    [\"portal-contacts\", \"group-add-search\", groupName, search] as const,\n} as const;\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"../contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"../query-keys\";\n\nexport interface UseInfiniteContactsParams {\n  search_query?: string;\n  status?: string;\n  sort_by?: string;\n  sort_direction?: string;\n  per_page?: number;\n  tags?: string[];\n}\n\nexport function useInfiniteContacts(params: UseInfiniteContactsParams) {\n  const api = useContactsCrud();\n  return useInfiniteQuery({\n    queryKey: [...CONTACTS_QUERY_KEYS.list(\"contacts\"), params],\n    queryFn: ({ pageParam }) =>\n      api.listContacts({\n        ...params,\n        page: pageParam,\n      }),\n    getNextPageParam: (lastPage) => {\n      const currentPage = lastPage.meta.current_page;\n      // Contacts API is page-number based; next_cursor and total_pages\n      // are both used as \"has-next-page\" signals.\n      if (currentPage == null) return undefined;\n      if (lastPage.meta.next_cursor) return currentPage + 1;\n      if (\n        lastPage.meta.total_pages != null &&\n        currentPage < lastPage.meta.total_pages\n      ) {\n        return currentPage + 1;\n      }\n      return undefined;\n    },\n    initialPageParam: 1,\n  });\n}\n","\"use client\";\n\nimport React, { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport {\n  CalendarDays,\n  CalendarIcon,\n  CircleOff,\n  Clock,\n  Sunrise,\n  Sun,\n  X,\n  type LucideIcon,\n} from \"lucide-react\";\nimport {\n  Calendar,\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n  Separator,\n  cn,\n  type CalendarProps,\n} from \"@fluid-app/ui-primitives\";\nimport { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport {\n  formatDateForDisplay,\n  getLocalCalendarDayDiff,\n  isAllDay,\n  LOCAL_TIMED_DUE_AT_PATTERN,\n  toDateInputValue,\n} from \"../../utils/format-date\";\n\nconst RELATIVE_DATE_MAX_DAYS = 30;\nconst DEFAULT_DUE_TIME = \"12:00\";\nconst TIME_INPUT_PATTERN = /^(\\d{2}):(\\d{2})$/;\n\nfunction isValidTimeInput(timeValue: string): boolean {\n  const match = TIME_INPUT_PATTERN.exec(timeValue);\n  const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n  const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n  return (\n    Number.isInteger(hours) &&\n    Number.isInteger(minutes) &&\n    hours >= 0 &&\n    hours <= 23 &&\n    minutes >= 0 &&\n    minutes <= 59\n  );\n}\n\nfunction toTimeInputValue(dueDate: string | null | undefined): string {\n  if (!dueDate) return \"\";\n\n  const localTimedMatch = LOCAL_TIMED_DUE_AT_PATTERN.exec(dueDate);\n  if (localTimedMatch?.[1] && localTimedMatch[2]) {\n    const timeValue = `${localTimedMatch[1]}:${localTimedMatch[2]}`;\n    return isValidTimeInput(timeValue) ? timeValue : \"\";\n  }\n\n  if (isAllDay(dueDate)) return \"\";\n\n  const date = new Date(dueDate);\n  if (Number.isNaN(date.getTime())) return \"\";\n\n  return `${String(date.getHours()).padStart(2, \"0\")}:${String(\n    date.getMinutes(),\n  ).padStart(2, \"0\")}`;\n}\n\nfunction formatTimeForDisplay(timeValue: string, locale: string): string {\n  const match = TIME_INPUT_PATTERN.exec(timeValue);\n  const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n  const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n  if (!isValidTimeInput(timeValue)) return timeValue;\n\n  const date = new Date();\n  date.setHours(hours, minutes, 0, 0);\n\n  return new Intl.DateTimeFormat(locale, {\n    hour: \"numeric\",\n    minute: \"2-digit\",\n  }).format(date);\n}\n\nfunction formatOffset(date: Date): string {\n  const offsetMinutes = -date.getTimezoneOffset();\n  const sign = offsetMinutes >= 0 ? \"+\" : \"-\";\n  const absoluteOffset = Math.abs(offsetMinutes);\n  const hours = String(Math.floor(absoluteOffset / 60)).padStart(2, \"0\");\n  const minutes = String(absoluteOffset % 60).padStart(2, \"0\");\n\n  return `${sign}${hours}:${minutes}`;\n}\n\nfunction composeDueAt(dateOnlyValue: string, timeValue: string): string | null {\n  if (!dateOnlyValue) return null;\n  if (isValidTimeInput(timeValue)) {\n    const dateMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(dateOnlyValue);\n    const timeMatch = TIME_INPUT_PATTERN.exec(timeValue);\n    if (\n      dateMatch?.[1] &&\n      dateMatch[2] &&\n      dateMatch[3] &&\n      timeMatch?.[1] &&\n      timeMatch[2]\n    ) {\n      const localDate = new Date(\n        Number(dateMatch[1]),\n        Number(dateMatch[2]) - 1,\n        Number(dateMatch[3]),\n        Number(timeMatch[1]),\n        Number(timeMatch[2]),\n        0,\n        0,\n      );\n\n      return `${dateOnlyValue}T${timeValue}:00${formatOffset(localDate)}`;\n    }\n  }\n\n  return dateOnlyValue;\n}\n\ninterface QuickDateRowProps {\n  icon: LucideIcon;\n  label: string;\n  rightLabel?: string;\n  onSelect: () => void;\n}\n\nfunction QuickDateRow({\n  icon: Icon,\n  label,\n  rightLabel,\n  onSelect,\n}: QuickDateRowProps): React.JSX.Element {\n  return (\n    <button\n      type=\"button\"\n      onClick={onSelect}\n      className=\"text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:ring-ring flex w-full min-w-0 items-center gap-3 rounded-lg px-2 py-2 text-sm transition-colors outline-none focus-visible:ring-2\"\n    >\n      <Icon className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n      <span className=\"min-w-0 flex-1 truncate text-left font-medium\">\n        {label}\n      </span>\n      {rightLabel && (\n        <span className=\"ml-auto max-w-[50%] min-w-0 truncate text-right text-xs font-medium text-current/80\">\n          {rightLabel}\n        </span>\n      )}\n    </button>\n  );\n}\n\nexport interface TaskComposerFormValues {\n  body: string;\n  due_at: string | null;\n}\n\nexport interface TaskComposerFormProps {\n  /** Caller-controlled submit handler. */\n  onSubmit: (values: TaskComposerFormValues) => void;\n  /** Disable the submit button while the parent mutation is in flight. */\n  isSubmitting?: boolean;\n  /** Label for the submit button. Defaults to translated \"add_task\". */\n  submitLabel?: string;\n  /** Label shown while submitting. Defaults to translated \"adding\". */\n  submittingLabel?: string;\n  /** Optional initial body — used for edit mode. */\n  initialBody?: string;\n  /** Optional initial due date (ISO string) — used for edit mode. */\n  initialDueAt?: string | null;\n  /** Optional controls rendered after the date controls in the metadata row. */\n  metadataControls?: React.ReactNode;\n  /** When provided, an X button is rendered and Escape closes the form. */\n  onClose?: () => void;\n  /** Focus the body input on mount. Default true. */\n  autoFocus?: boolean;\n}\n\nexport function TaskComposerForm({\n  onSubmit,\n  isSubmitting = false,\n  submitLabel,\n  submittingLabel,\n  initialBody = \"\",\n  initialDueAt = null,\n  metadataControls,\n  onClose,\n  autoFocus = true,\n}: TaskComposerFormProps): React.JSX.Element {\n  const { t, locale } = useContactsTranslation();\n  const [body, setBody] = useState(initialBody);\n  const [dueDate, setDueDate] = useState<string | null>(initialDueAt ?? null);\n  const [dueTime, setDueTime] = useState(\n    () => toTimeInputValue(initialDueAt) || DEFAULT_DUE_TIME,\n  );\n  const [dateTimeControlsChanged, setDateTimeControlsChanged] = useState(false);\n  const [datePopoverOpen, setDatePopoverOpen] = useState(false);\n  const [labelNow, setLabelNow] = useState(() => new Date());\n  const timeInputId = useId();\n  const inputRef = useRef<HTMLInputElement | null>(null);\n\n  useEffect(() => {\n    if (autoFocus) inputRef.current?.focus();\n  }, [autoFocus]);\n\n  useEffect(() => {\n    let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n    const scheduleNextMidnightUpdate = () => {\n      const now = new Date();\n      setLabelNow(now);\n\n      const nextMidnight = new Date(now);\n      nextMidnight.setHours(24, 0, 0, 0);\n\n      timeoutId = setTimeout(\n        scheduleNextMidnightUpdate,\n        nextMidnight.getTime() - now.getTime(),\n      );\n    };\n\n    scheduleNextMidnightUpdate();\n\n    return () => {\n      if (timeoutId != null) clearTimeout(timeoutId);\n    };\n  }, []);\n\n  const dateOnlyValue = useMemo(() => toDateInputValue(dueDate), [dueDate]);\n  const hasDateSelected = dateOnlyValue !== \"\";\n  const hasInitialTimedDueAt = toTimeInputValue(initialDueAt) !== \"\";\n  const hasTimeSelected =\n    dueTime !== \"\" &&\n    hasDateSelected &&\n    (dateTimeControlsChanged || hasInitialTimedDueAt);\n  const selectedCalendarDate = useMemo(\n    () => (dateOnlyValue === \"\" ? undefined : startOfLocalDay(dateOnlyValue)),\n    [dateOnlyValue],\n  );\n  const todayLocalMidnight = useMemo(\n    () => startOfLocalDay(labelNow),\n    [labelNow],\n  );\n  const normalizedLocale = useMemo(\n    () => locale?.replace(/_/g, \"-\") ?? \"en-US\",\n    [locale],\n  );\n  const calendarDefaultMonth = useMemo(() => {\n    if (!selectedCalendarDate) return todayLocalMidnight;\n\n    return selectedCalendarDate.getTime() < todayLocalMidnight.getTime()\n      ? todayLocalMidnight\n      : selectedCalendarDate;\n  }, [selectedCalendarDate, todayLocalMidnight]);\n\n  const quickDates = useMemo(() => {\n    const tomorrow = isoDate(1, labelNow);\n    const nextWeek = isoDate(7, labelNow);\n    const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n      weekday: \"short\",\n    });\n    const nextWeekFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n      weekday: \"short\",\n      month: \"short\",\n      day: \"numeric\",\n    });\n\n    return {\n      tomorrow,\n      tomorrowLabel: weekdayFormatter.format(startOfLocalDay(tomorrow)),\n      nextWeek,\n      nextWeekLabel: nextWeekFormatter.format(startOfLocalDay(nextWeek)),\n    };\n  }, [labelNow, normalizedLocale]);\n\n  const calendarFormatters = useMemo<\n    NonNullable<CalendarProps[\"formatters\"]>\n  >(() => {\n    const monthYearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n      month: \"long\",\n      year: \"numeric\",\n    });\n    const monthFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n      month: \"long\",\n    });\n    const yearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n      year: \"numeric\",\n    });\n    const dayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n      day: \"numeric\",\n    });\n    const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n      weekday: \"short\",\n    });\n    const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n    return {\n      formatCaption: (month) => monthYearFormatter.format(month),\n      formatMonthCaption: (month) => monthFormatter.format(month),\n      formatYearCaption: (year) => yearFormatter.format(year),\n      formatDay: (day) => dayFormatter.format(day),\n      formatWeekdayName: (weekday) => weekdayFormatter.format(weekday),\n      formatWeekNumber: (weekNumber) => weekNumberFormatter.format(weekNumber),\n    };\n  }, [normalizedLocale]);\n\n  const calendarLabels = useMemo<NonNullable<CalendarProps[\"labels\"]>>(() => {\n    const dayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n      weekday: \"long\",\n      month: \"long\",\n      day: \"numeric\",\n      year: \"numeric\",\n    });\n    const weekdayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n      weekday: \"long\",\n    });\n    const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n    return {\n      labelNext: () => t(\"calendar_next_month\"),\n      labelPrevious: () => t(\"calendar_previous_month\"),\n      labelMonthDropdown: () => t(\"calendar_month_dropdown\"),\n      labelYearDropdown: () => t(\"calendar_year_dropdown\"),\n      labelDay: (day) => dayLabelFormatter.format(day),\n      labelWeekday: (weekday) => weekdayLabelFormatter.format(weekday),\n      labelWeekNumber: (weekNumber) =>\n        t(\"calendar_week_number\", {\n          number: weekNumberFormatter.format(weekNumber),\n        }),\n    };\n  }, [normalizedLocale, t]);\n\n  const dateBadgeLabel = useMemo(() => {\n    if (!hasDateSelected) return t(\"task_select_date\");\n\n    const diffDays = getLocalCalendarDayDiff(dateOnlyValue, labelNow);\n    if (diffDays === 0) return t(\"quick_today\");\n    if (diffDays === 1) return t(\"quick_tomorrow\");\n    if (\n      diffDays != null &&\n      diffDays >= 2 &&\n      diffDays <= RELATIVE_DATE_MAX_DAYS\n    ) {\n      return t(\"task_due_in_days\", { count: diffDays });\n    }\n\n    return formatDateForDisplay(dateOnlyValue, normalizedLocale);\n  }, [dateOnlyValue, hasDateSelected, labelNow, normalizedLocale, t]);\n\n  const timeBadgeLabel = useMemo(\n    () =>\n      hasTimeSelected ? formatTimeForDisplay(dueTime, normalizedLocale) : \"\",\n    [dueTime, hasTimeSelected, normalizedLocale],\n  );\n  const dateBadgeAriaLabel = hasTimeSelected\n    ? `${dateBadgeLabel}, ${timeBadgeLabel}`\n    : dateBadgeLabel;\n\n  const submit = () => {\n    const trimmed = body.trim();\n    if (!trimmed || isSubmitting) return;\n\n    onSubmit({\n      body: trimmed,\n      due_at: dateTimeControlsChanged\n        ? composeDueAt(dateOnlyValue, dueTime)\n        : (initialDueAt ?? null),\n    });\n  };\n\n  const canSubmit = body.trim().length > 0 && !isSubmitting;\n\n  const selectDueDate = (value: string) => {\n    setDateTimeControlsChanged(true);\n    setDueDate(value);\n    setDueTime((currentTime) => currentTime || DEFAULT_DUE_TIME);\n  };\n\n  const clearDueDate = () => {\n    setDateTimeControlsChanged(true);\n    setDueDate(null);\n    setDueTime(DEFAULT_DUE_TIME);\n    setDatePopoverOpen(false);\n  };\n\n  const handleTimeChange = (value: string) => {\n    setDateTimeControlsChanged(true);\n    setDueTime(value);\n    if (value && !hasDateSelected) setDueDate(isoDate(0, labelNow));\n  };\n\n  return (\n    <div className=\"border-border/50 focus-within:border-foreground/30 rounded-xl border p-3 transition-colors\">\n      <div className=\"flex items-start gap-3\">\n        <div\n          className=\"border-muted-foreground/50 mt-1.5 size-5 shrink-0 rounded-full border-2\"\n          aria-hidden=\"true\"\n        />\n        <input\n          ref={inputRef}\n          value={body}\n          onChange={(e) => setBody(e.target.value)}\n          onKeyDown={(e) => {\n            if (e.key === \"Enter\" && !e.shiftKey) {\n              e.preventDefault();\n              submit();\n            } else if (e.key === \"Escape\" && onClose) {\n              e.preventDefault();\n              onClose();\n            }\n          }}\n          placeholder={t(\"task_describe_placeholder\")}\n          aria-label={t(\"task_description_aria\")}\n          className=\"placeholder:text-muted-foreground/80 text-foreground flex-1 border-0 bg-transparent text-sm font-medium outline-none pointer-coarse:text-base\"\n        />\n        {onClose && (\n          <button\n            type=\"button\"\n            onClick={onClose}\n            aria-label={t(\"task_discard_aria\")}\n            className=\"text-muted-foreground hover:bg-muted hover:text-foreground -mt-0.5 -mr-0.5 flex size-7 shrink-0 items-center justify-center rounded-md transition-colors\"\n          >\n            <X className=\"size-4\" />\n          </button>\n        )}\n      </div>\n\n      {/* --row-indent aligns the date row with the input text above (size-5\n          circle + gap-3 = 2rem). The mobile Add button cancels it via\n          -ml-(--row-indent) + w-[calc(100%+var(--row-indent))] so the two\n          values stay locked to a single source. */}\n      <div className=\"mt-3 flex flex-wrap items-center gap-1.5 pl-(--row-indent) [--row-indent:2rem]\">\n        <Popover open={datePopoverOpen} onOpenChange={setDatePopoverOpen}>\n          <PopoverTrigger asChild>\n            <button\n              type=\"button\"\n              aria-label={\n                hasDateSelected\n                  ? t(\"task_custom_date_selected_aria\", {\n                      date: dateBadgeAriaLabel,\n                    })\n                  : t(\"task_custom_date_aria\")\n              }\n              className={cn(\n                \"flex shrink-0 items-center gap-1 rounded-full px-3 py-1 text-xs font-medium transition-colors\",\n                hasDateSelected\n                  ? \"bg-primary text-primary-foreground\"\n                  : \"bg-muted text-muted-foreground hover:bg-muted/70\",\n              )}\n            >\n              <CalendarIcon className=\"size-3\" aria-hidden=\"true\" />\n              <span>{dateBadgeLabel}</span>\n              {hasTimeSelected && (\n                <span className=\"inline-flex items-center gap-0.5 text-current/80\">\n                  <Clock className=\"size-3\" aria-hidden=\"true\" />\n                  <span>{timeBadgeLabel}</span>\n                </span>\n              )}\n            </button>\n          </PopoverTrigger>\n          <PopoverContent\n            align=\"start\"\n            className=\"bg-popover text-popover-foreground pointer-events-auto z-[9999] w-max max-w-[calc(100vw-2rem)] rounded-xl border p-3 shadow-lg\"\n          >\n            <h3 className=\"text-foreground max-w-full truncate px-1 text-sm font-semibold\">\n              {dateBadgeLabel}\n            </h3>\n            <Separator className=\"bg-border my-3\" />\n            <div className=\"min-w-0 space-y-1\">\n              <QuickDateRow\n                icon={Sun}\n                label={t(\"quick_today\")}\n                onSelect={() => selectDueDate(isoDate(0, labelNow))}\n              />\n              <QuickDateRow\n                icon={Sunrise}\n                label={t(\"quick_tomorrow\")}\n                rightLabel={quickDates.tomorrowLabel}\n                onSelect={() => selectDueDate(quickDates.tomorrow)}\n              />\n              <QuickDateRow\n                icon={CalendarDays}\n                label={t(\"task_next_week\")}\n                rightLabel={quickDates.nextWeekLabel}\n                onSelect={() => selectDueDate(quickDates.nextWeek)}\n              />\n              <QuickDateRow\n                icon={CircleOff}\n                label={t(\"task_no_date\")}\n                onSelect={clearDueDate}\n              />\n            </div>\n            <Separator className=\"bg-border my-3\" />\n            <div>\n              <p className=\"text-muted-foreground px-1 text-xs font-semibold\">\n                {t(\"task_custom_calendar\")}\n              </p>\n              <Calendar\n                mode=\"single\"\n                formatters={calendarFormatters}\n                labels={calendarLabels}\n                disabled={{ before: todayLocalMidnight }}\n                onSelect={(date) => {\n                  if (!date) return;\n\n                  const selectedDate = startOfLocalDay(date);\n                  if (selectedDate.getTime() < todayLocalMidnight.getTime()) {\n                    return;\n                  }\n\n                  selectDueDate(isoDate(0, selectedDate));\n                }}\n                className=\"p-0 pt-2\"\n                classNames={{\n                  cell: \"h-9 w-9 p-0 text-center text-sm focus-within:relative focus-within:z-20\",\n                  day_selected:\n                    \"rounded-md bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground\",\n                }}\n                initialFocus\n                defaultMonth={calendarDefaultMonth}\n                {...(selectedCalendarDate\n                  ? {\n                      selected: selectedCalendarDate,\n                    }\n                  : {})}\n              />\n            </div>\n            <Separator className=\"bg-border my-3\" />\n            <div className=\"flex items-center justify-between gap-4 px-1\">\n              <label\n                htmlFor={timeInputId}\n                className=\"text-muted-foreground text-xs font-semibold\"\n              >\n                {t(\"task_time_label\")}\n              </label>\n              <div className=\"border-input bg-background text-foreground focus-within:ring-ring flex h-9 items-center gap-2 rounded-md border px-2 focus-within:ring-2\">\n                <Clock\n                  className=\"text-muted-foreground size-3.5 shrink-0\"\n                  aria-hidden=\"true\"\n                />\n                <input\n                  id={timeInputId}\n                  type=\"time\"\n                  value={dueTime}\n                  onChange={(event) => handleTimeChange(event.target.value)}\n                  aria-label={t(\"task_time_aria\")}\n                  className=\"h-full border-0 bg-transparent p-0 text-right text-sm outline-none [&::-webkit-calendar-picker-indicator]:hidden\"\n                />\n              </div>\n            </div>\n          </PopoverContent>\n        </Popover>\n        {metadataControls}\n        <button\n          type=\"button\"\n          onClick={submit}\n          disabled={!canSubmit}\n          className=\"bg-primary text-primary-foreground hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground mt-1 -ml-(--row-indent) inline-flex h-10 w-[calc(100%+var(--row-indent))] items-center justify-center rounded-lg text-sm font-semibold transition-colors disabled:cursor-not-allowed sm:mt-0 sm:ml-auto sm:h-auto sm:w-auto sm:shrink-0 sm:gap-1.5 sm:rounded-full sm:px-4 sm:py-1.5 sm:text-xs\"\n        >\n          {isSubmitting\n            ? (submittingLabel ?? t(\"adding\"))\n            : (submitLabel ?? t(\"add_task\"))}\n        </button>\n      </div>\n    </div>\n  );\n}\n"],"mappings":"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"}