{
  "Form": {
    "rules": [
      "When model is supplied, update React state with onChange(nextModel); the library does not mutate the caller's model object. Without model, Form keeps an internal model.",
      "FormItem prop selects a model field; supported child controls receive the field value and change handler automatically.",
      "onSubmit receives { valid }, not a DOM submit event. Save only when valid is true. Button htmlType=submit triggers validation.",
      "disabled and readOnly are inherited by supported form controls; explicit child props override inherited state.",
      "reset clears registered fields to null and emits onChange/onReset; it does not restore an original snapshot."
    ],
    "methods": [
      "ref.current.validate(): Promise<{ valid: boolean }>",
      "ref.current.reset(): void",
      "ref.current.submit(): Promise<void>"
    ]
  },
  "FormItem": {
    "rules": [
      "Use inside Form. prop is the field path, not the field value. Do not copy Vue v-model bindings."
    ]
  },
  "Input": {
    "rules": [
      "Use value and onChange(nextValue). onChange receives a string, not a DOM event.",
      "Input uses synchronized local state: edits can stay local until the parent supplies a different value. Do not promise strict native controlled-input semantics. Keep application state updated through onChange."
    ]
  },
  "Button": {
    "rules": [
      "Use htmlType=submit/reset for form actions; type is visual intent, not native button type.",
      "Button.icon takes IconType[] data imported from kui-icons: import { Search } from 'kui-icons'; use <Button icon={Search} />. Never pass a JSX element (<Icon type={Search} />), a component function, or an icon-name string to icon. For custom rendered content, put <Icon type={Search} /> in Button children. Input prefix/suffix are renderable nodes and must not be confused with Button.icon."
    ]
  },
  "Switch": {
    "rules": [
      "Use checked and onChange. checked initializes local state; interactions update it internally, and changed checked props synchronize it.",
      "checked is boolean. onChange returns boolean/string/number according to valueType; default valueType is boolean."
    ]
  },
  "Modal": {
    "rules": [
      "Use open and onOpenChange. open initializes local visibility; interactions update it internally, and changed open props synchronize it.",
      "onOk does not automatically save or close. Validate/save first, then set open=false. loading blocks user dismissal during saving.",
      "Use children or content and footer props, not Vue named slots."
    ]
  },
  "Drawer": {
    "rules": [
      "Use open and onOpenChange. open initializes local visibility, allows interaction, and synchronizes changed props. Do not use v-model."
    ]
  },
  "Page": {
    "rules": [
      "Pages are one-based. onChange(page, pageSize) reports both values. Update application page/pageSize state and fetch data explicitly."
    ]
  },
  "Table": {
    "rules": [
      "Pass data and columns. Set rowKey to a stable unique field; the default is key.",
      "The component does not call your backend. For remote paging, combine Page with explicit loading/error state and protect against stale responses.",
      "Use render callbacks/ReactNode props from the API; Vue slot syntax is invalid."
    ]
  },
  "Menu": {
    "rules": [
      "Use selectedKeys or value with onChange for selection; openKeys with onOpenChange controls expanded submenus. Do not use Vue update events."
    ]
  },
  "ConfigProvider": {
    "rules": [
      "Wrap children to supply locale, size, theme and shape. Explicit component props override provider values. Import locales from react-kui/locale/<locale>."
    ]
  },
  "Select": {
    "rules": [
      "Use value and onChange(value), not v-model. Multiple selection uses an array.",
      "onSelect(option) supplies the selected option and selected flag; onChange does not supply an option as a second argument."
    ]
  },
  "KImage": {
    "rules": [
      "The public React export is KImage, not the Vue Image component name."
    ]
  },
  "Space": {
    "rules": [
      "Use children and compact. Vertical compact layout supports Button groups. Use className, not class."
    ]
  },
  "Dropdown": {
    "rules": [
      "children is the trigger; overlay supplies popup content. Do not place the menu in children as a translation of the Vue overlay slot."
    ]
  },
  "DatePicker": {
    "rules": [
      "Use value/onChange for a single date or a range array when the selected mode is a range. startDate/endDate with onStartDateChange/onEndDateChange are an alternative binding channel, not the only API.",
      "onChange receives (date, dateStr); output depends on valueType and mode. Handle clear/null values explicitly and avoid supplying conflicting binding channels."
    ]
  },
  "Checkbox": {
    "rules": [
      "Use checked for the checked state; value identifies an item in a CheckboxGroup. onChange receives an object with checked and optional value/label, not the Switch scalar callback."
    ]
  },
  "Popup": {
    "rules": [
      "Use children for the trigger and overlay for the popup content. open/onOpenChange synchronizes visibility; query the callback detail type for dismissal reasons.",
      "The shared Popup manages nested layers; do not implement an extra document-click closer that can close parent pickers during nested selections."
    ]
  },
  "MenuItem": {
    "rules": [
      "Use itemKey to identify the menu item. React key alone is not forwarded as itemKey."
    ]
  }
}
