{"id":50592178,"url":"https://github.com/roastedbeans/smart-date-picker","last_synced_at":"2026-06-05T11:03:27.527Z","repository":{"id":358597306,"uuid":"1239568078","full_name":"roastedbeans/smart-date-picker","owner":"roastedbeans","description":"Natural-language React date and date range picker. Type 'next Friday' or 'this month' and the calendar follows. No LLM, no API key — built with chrono-node, Next.js, and shadcn/ui.","archived":false,"fork":false,"pushed_at":"2026-05-18T04:45:00.000Z","size":124,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-18T06:46:56.284Z","etag":null,"topics":["calendar","chrono-node","date-picker","date-range-picker","natural-language","nextjs","react","shadcn-ui","tailwindcss","typescript"],"latest_commit_sha":null,"homepage":"https://github.com/roastedbeans/smart-date-picker","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/roastedbeans.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-15T08:09:08.000Z","updated_at":"2026-05-18T04:45:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/roastedbeans/smart-date-picker","commit_stats":null,"previous_names":["roastedbeans/smart-date-picker"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/roastedbeans/smart-date-picker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastedbeans%2Fsmart-date-picker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastedbeans%2Fsmart-date-picker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastedbeans%2Fsmart-date-picker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastedbeans%2Fsmart-date-picker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roastedbeans","download_url":"https://codeload.github.com/roastedbeans/smart-date-picker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roastedbeans%2Fsmart-date-picker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33939227,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calendar","chrono-node","date-picker","date-range-picker","natural-language","nextjs","react","shadcn-ui","tailwindcss","typescript"],"created_at":"2026-06-05T11:03:26.740Z","updated_at":"2026-06-05T11:03:27.520Z","avatar_url":"https://github.com/roastedbeans.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Smart Date Picker — Natural-Language React Date \u0026 Range Picker\n\nA React date picker and date range picker that you control by **typing**. Type **\"next Friday\"**, **\"this month\"**, or even **\"Janury 15\"** (with a typo) and the calendar follows. Built on [chrono-node](https://github.com/wanasit/chrono) + a rule-based range parser. **No LLM, no API key, no network calls** — fully deterministic and offline.\n\n\u003e _Stop clicking through 12 months of arrows. Just type what you mean._\n\n![Smart date picker demo](public/next.svg)\n\n## Why this exists\n\nMost date pickers force users to navigate a grid of cells. Power users (analysts, schedulers, anyone who knows roughly the date they want) end up clicking next-month-next-month-next-month. A natural-language input is faster for them — but every \"smart\" date picker on npm either pulls in a 100MB LLM dependency, calls a paid API, or breaks on typos. This project ships a small, deterministic alternative built from `chrono-node` plus a tiny custom rule layer.\n\n## Features\n\n- **Three picker modes from one component:** single date, range with one input, or range with split `from` / `to` inputs.\n- **Natural-language parsing.** Understands relative dates (`tomorrow`, `in 3 days`, `2 weeks ago`), weekdays (`next Monday`, `last Friday`), ranges (`this week`, `next month`, `last year`), and absolute dates (`May 20`, `January 1, 2027`).\n- **Typo correction.** `Janury 15` resolves to `January 15` automatically — a Levenshtein-distance pass over month names.\n- **Autosuggest dropdown.** Ranks suggestions by relevance; surfaces a \"did you mean\" hint when your input fuzzy-matches a known phrase.\n- **Keyboard-first.** `↑` / `↓` to navigate suggestions, `Enter` to commit, `Esc` to dismiss.\n- **Range expansion.** When you type a single future date into the range picker (e.g. `June`), it expands to \"today through that date\" automatically.\n- **Zero dependencies on AI.** No LLM, no Anthropic / OpenAI key required. The entire parser is ~250 lines of TypeScript.\n- **Accessible.** Combobox pattern with proper ARIA roles (`role=\"combobox\"`, `role=\"listbox\"`, `aria-selected`, etc.).\n\n## Live demo\n\nRun locally:\n\n```bash\ngit clone https://github.com/roastedbeans/smart-date-picker.git\ncd smart-date-picker\npnpm install\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000).\n\n## Tech stack\n\n- **Next.js 16** (App Router) + **React 19** + **TypeScript**\n- **Tailwind CSS v4**\n- **shadcn/ui** (base-nova preset, Base UI primitives)\n- **chrono-node** for NLP date parsing\n- **react-day-picker** for the calendar widget\n\n## Usage\n\n```tsx\nimport { SmartDatePicker } from \"@/components/smart-date-picker\"\n\nexport default function Example() {\n  return (\n    \u003c\u003e\n      \u003cSmartDatePicker /\u003e                  {/* Single date */}\n      \u003cSmartDatePicker range /\u003e            {/* Range, one input */}\n      \u003cSmartDatePicker range separate /\u003e   {/* Range, separate from/to */}\n    \u003c/\u003e\n  )\n}\n```\n\nEach picker is uncontrolled by default and accepts an `onValueChange` callback:\n\n```tsx\n\u003cSmartDatePicker\n  onValueChange={(date) =\u003e console.log(\"picked:\", date)}\n/\u003e\n```\n\n## Supported phrases\n\nThe deterministic parser handles all of these out of the box. Anything chrono-node understands works, plus the rule-based range phrases below.\n\n### Single-date phrases\n\n| Phrase | Resolves to |\n|--------|-------------|\n| `today` / `tomorrow` / `yesterday` | Anchor day |\n| `Monday`, `next Friday`, `last Wednesday` | The closest matching weekday |\n| `in 3 days`, `in 2 weeks`, `in a month` | Today + offset |\n| `2 days ago`, `a week ago`, `a year ago` | Today − offset |\n| `May 20`, `December 25`, `January 1, 2027` | Absolute date |\n| `Janury 15`, `Feburary 20`, `Decmber 25` | Auto-corrected absolute date |\n\n### Range phrases\n\n| Phrase | Resolves to |\n|--------|-------------|\n| `this week` / `next week` / `last week` | Monday–Sunday of the relevant week |\n| `this weekend` / `next weekend` | Saturday–Sunday |\n| `this month` / `next month` / `last month` | First–last day of the month |\n| `this year` / `next year` / `last year` | January 1 – December 31 |\n\nIn **range mode**, typing a single future date (e.g. `June`, `Christmas`, `next Friday`) expands to a range that starts **today** and ends on the parsed date — a common \"from now until X\" pattern.\n\n## Project structure\n\n```\napp/                            Next.js demo pages\n  page.tsx                      Landing page\n  layout.tsx\n  globals.css\ncomponents/\n  smart-date-picker.tsx         Dispatcher: range? separate?\n  single-date-picker.tsx        Single-date picker\n  range-date-picker.tsx         Range picker (1-input + 2-input variants)\n  phrase-input.tsx              Combobox input with autosuggest\n  picker-showcase.tsx           Demo mode toggle (landing page)\n  ui/                           shadcn primitives\nlib/\n  parse-date.ts                 Rule-based + chrono parser\n  score-suggestions.ts          Levenshtein-based suggestion scoring\n  levenshtein.ts\n  suggestions.ts                Curated phrase lists\n  use-parse-phrase.ts           Client-side parsing hook\n  utils.ts                      cn() helper\ndocs/\n  superpowers/specs/            Design docs\n```\n\n## How parsing works\n\n```\n                ┌──────────────────────┐\n\"next week\" ──▶ │ tryRangePhrase()     │ ── rule match ──▶ { 2026-05-18, 2026-05-24 }\n                └──────────────────────┘\n                          │ no match\n                          ▼\n                ┌──────────────────────┐\n                │ correctMonthSpelling │  (\"Janury\" → \"January\")\n                └──────────────────────┘\n                          │\n                          ▼\n                ┌──────────────────────┐\n                │ chrono.parse()       │ ── result ──▶ { start: \"2027-01-15\", end: \"2027-01-15\" }\n                └──────────────────────┘\n                          │ no result\n                          ▼\n                        null (UI shows \"Couldn't understand …\")\n```\n\nThe whole pipeline is synchronous and runs in the browser. No backend round-trip.\n\n## Customization\n\nThis repo is structured as a Next.js demo, not yet published to npm. To adapt the pickers for your own project:\n\n1. Copy `components/smart-date-picker.tsx`, `single-date-picker.tsx`, `range-date-picker.tsx`, and `phrase-input.tsx` into your project.\n2. Copy `lib/parse-date.ts`, `levenshtein.ts`, `score-suggestions.ts`, `suggestions.ts`, and `use-parse-phrase.ts`.\n3. The components depend on shadcn/ui primitives (`Input`, `Calendar`, `Popover`, etc.). Either run `npx shadcn@latest add input calendar popover command button` or swap in your own equivalents.\n4. Override the suggestion lists in `lib/suggestions.ts` to fit your locale or use case.\n\n## Keywords\n\nReact date picker · natural language date picker · date range picker · React calendar · chrono-node React · typo-tolerant date input · combobox date picker · shadcn date picker · Next.js date picker · accessible date picker · offline date picker · no-LLM date parser.\n\n## License\n\nMIT. See [LICENSE](LICENSE) if present, otherwise treat as MIT-licensed.\n\n## Contributing\n\nIssues and PRs welcome at [github.com/roastedbeans/smart-date-picker](https://github.com/roastedbeans/smart-date-picker).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froastedbeans%2Fsmart-date-picker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froastedbeans%2Fsmart-date-picker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froastedbeans%2Fsmart-date-picker/lists"}