{
  "aliases": [
    "検索条件",
    "検索フォーム",
    "query-filter",
    "query filter",
    "advanced search",
    "advanced-search",
    "search-panel"
  ],
  "code": "// Live examples: docs page navigation/search-form (l = SearchForm label-top and label-left,\n// n = advanced-search form). Research: Ant Design ProComponents QueryFilter (defaultCollapsed\n// true, defaultFormItemsNumber, layout vertical/horizontal, labelWidth, search/reset text);\n// Google Advanced Search (rows: all these words / this exact phrase / any of these words /\n// none of these words / numbers ranging from; then narrow by language, region, last update,\n// site, terms appearing, file type).\n//\n// WHICH SHAPE (rule #51): few filters applied as they change → FilterBar. Many conditions, a heavy\n// query, or users who expect a 検索 button → SearchForm. Arbitrary field × operator conditions,\n// all/any/custom logic, saved views → pattern condition-builder.\nimport { useState, type FormEvent } from \"react\";\nimport { Card, CardContent, DataTable, type ColumnDef } from \"@godxjp/ui/data-display\";\nimport { DatePicker, FormField, Input, NumberInput, RadioGroup, Select } from \"@godxjp/ui/data-entry\";\nimport { Flex } from \"@godxjp/ui/layout\";\nimport { Text } from \"@godxjp/ui/general\";\nimport { SearchForm } from \"@godxjp/ui/navigation\";\n\ntype Option = { value: string; label: string };\ntype Conditions = {\n  name: string; match: \"partial\" | \"exact\"; nationality: string; occupation: string;\n  monthsMin: number | null; monthsMax: number | null;\n};\nconst EMPTY: Conditions = { name: \"\", match: \"partial\", nationality: \"\", occupation: \"\", monthsMin: null, monthsMax: null };\n\nexport function TraineeSearch<T extends { id: string }>({ rows, columns, nationalities, occupations, search }: {\n  rows: T[]; columns: ColumnDef<T>[]; nationalities: Option[]; occupations: Option[];\n  search: (c: Conditions) => T[];\n}) {\n  // Inputs edit the DRAFT; 検索 copies it to APPLIED; クリア empties both.\n  const [draft, setDraft] = useState<Conditions>(EMPTY);\n  const [applied, setApplied] = useState<Conditions>(EMPTY);\n  const set = (patch: Partial<Conditions>) => setDraft((cur) => ({ ...cur, ...patch }));\n  const results = search(applied);\n  const summary = [\n    applied.name && \"氏名: \" + applied.name + (applied.match === \"exact\" ? \"（完全一致）\" : \"（部分一致）\"),\n    applied.nationality && \"国籍: \" + nationalities.find((o) => o.value === applied.nationality)?.label,\n    (applied.monthsMin != null || applied.monthsMax != null) && \"在籍月数: \" + (applied.monthsMin ?? \"\") + \"〜\" + (applied.monthsMax ?? \"\"),\n  ].filter(Boolean).join(\" / \") || \"指定なし\";\n\n  return (\n    <Flex direction=\"col\" gap=\"md\">\n      <Card>\n        <CardContent>\n          {/* layout=\"horizontal\" labelWidth=\"7rem\" columns={{ base: 1, lg: 2 }} = label-left 表形式 */}\n          <SearchForm\n            controlWidth=\"100%\"\n            onSubmit={(e: FormEvent) => { e.preventDefault(); setApplied(draft); }}\n            onReset={() => { setDraft(EMPTY); setApplied(EMPTY); }}\n            summary={summary}\n            resultCount={results.length}\n          >\n            <FormField label=\"氏名\" id=\"ts-name\">\n              <Flex direction=\"col\" gap=\"xs\">\n                <Input id=\"ts-name\" value={draft.name} onChange={(e) => set({ name: e.target.value })} />\n                <RadioGroup aria-label=\"一致条件\" orientation=\"horizontal\" value={draft.match}\n                  options={[{ value: \"partial\", label: \"部分一致\" }, { value: \"exact\", label: \"完全一致\" }]}\n                  onValueChange={(v) => set({ match: v === \"exact\" ? \"exact\" : \"partial\" })} />\n              </Flex>\n            </FormField>\n            <FormField label=\"国籍\" id=\"ts-nat\">\n              <Select id=\"ts-nat\" options={nationalities} value={draft.nationality} placeholder=\"すべて\" allowClear\n                onValueChange={(v: string) => set({ nationality: v })} />\n            </FormField>\n            <FormField label=\"入国日\" id=\"ts-entry\">\n              <DatePicker id=\"ts-entry\" range />\n            </FormField>\n            {/* past the first row: behind 詳細条件を開く, still mounted */}\n            <FormField label=\"在籍月数\" id=\"ts-min\">\n              <Flex gap=\"xs\" align=\"center\">\n                <NumberInput id=\"ts-min\" aria-label=\"下限\" min={0} value={draft.monthsMin} onValueChange={(v) => set({ monthsMin: v })} />\n                <Text tone=\"muted\">〜</Text>\n                <NumberInput aria-label=\"上限\" min={0} value={draft.monthsMax} onValueChange={(v) => set({ monthsMax: v })} />\n              </Flex>\n            </FormField>\n            <FormField label=\"職種\" id=\"ts-occ\">\n              <Select id=\"ts-occ\" options={occupations} value={draft.occupation} placeholder=\"すべて\" allowClear\n                onValueChange={(v: string) => set({ occupation: v })} />\n            </FormField>\n          </SearchForm>\n        </CardContent>\n      </Card>\n      <Card><CardContent flush><DataTable data={results} columns={columns} getRowId={(r) => r.id} /></CardContent></Card>\n    </Flex>\n  );\n}\n\n// ADVANCED-SEARCH SHAPE (Google): one <Form role=\"search\" layout=\"horizontal\" labelWidth=\"12rem\"\n// controlWidth=\"100%\" onSubmit>; each row is <ResponsiveGrid columns={{ base: 1, lg: 2 }}> holding\n// the FormField and a <Text tone=\"muted\"> that says which search-box syntax the row stands for\n// (\"Put a minus sign before words you don't want: -withdrawn\"); two <Heading level={3}> sections\n// (find… / then narrow the results by…); ONE submit Button at the end of the form, and the\n// equivalent query string shown with the result count after the search.",
  "name": "search-form",
  "tagline": "「検索条件フォーム」 — SearchForm (Ant Design ProComponents QueryFilter): labelled conditions in aligned columns (label-top or label-left 「表形式」), ranges From〜To, 「部分一致」/「完全一致」, explicit 「検索」 + 「クリア」 (search on SUBMIT), the rest behind 「詳細条件を開く」, then a 「検索条件」 summary + result count. Plus the Google Advanced Search shape (label | input | what the row means).",
  "tags": [
    "search",
    "search form",
    "query",
    "filter",
    "検索",
    "検索条件",
    "japanese",
    "business",
    "advanced search",
    "list",
    "datatable"
  ]
}
