From 96880edc1a4ac7c9198dd3e539d7fce2a5c9d64a Mon Sep 17 00:00:00 2001 From: Jiaxi Zhong Date: Mon, 24 Feb 2025 17:37:32 +0800 Subject: [PATCH] DateTime add error render ability --- packages/eagle/src/antd.ts | 8 +- packages/eagle/src/core/DatePicker/index.tsx | 28 + .../FieldsDateTime/__test__/h5_css.test.tsx | 821 ++++++++++++++++++ .../src/core/Fields/FieldsDateTime/index.tsx | 20 +- .../core/Fields/FieldsDateTimeRange/index.tsx | 4 +- packages/eagle/src/core/index.ts | 1 + packages/eagle/src/coreX/CronPlan/index.tsx | 4 +- packages/eagle/src/legacy-antd.tsx | 5 +- packages/eagle/src/spec/base.ts | 2 +- .../stories/docs/core/DatePicker.stories.tsx | 44 + 10 files changed, 919 insertions(+), 18 deletions(-) create mode 100644 packages/eagle/src/core/DatePicker/index.tsx create mode 100644 packages/eagle/src/core/Fields/FieldsDateTime/__test__/h5_css.test.tsx create mode 100644 packages/eagle/stories/docs/core/DatePicker.stories.tsx diff --git a/packages/eagle/src/antd.ts b/packages/eagle/src/antd.ts index f75e2b565..987c898be 100644 --- a/packages/eagle/src/antd.ts +++ b/packages/eagle/src/antd.ts @@ -1,5 +1,5 @@ import { - DatePicker, + DatePicker as AntdDatePicker, List, Menu, Modal, @@ -19,12 +19,14 @@ export { Button as AntdButton, Checkbox as AntdCheckbox, Collapse as AntdCollapse, + DatePicker as AntdDatePicker, Divider as AntdDivider, Drawer as AntdDrawer, Empty as AntdEmpty, Input as AntdInput, message as AntdMessage, Select as AntdSelect, + Skeleton as AntdSkeleton, Steps as AntdSteps, Switch as AntdSwitch, Table as AntdTable, @@ -33,14 +35,12 @@ export { TreeSelect as AntdTreeSelect, AutoComplete, Col, - DatePicker, Dropdown, Layout, List, Menu, Popover, Row, - Skeleton as AntdSkeleton, Tabs, Timeline, Tree, @@ -48,7 +48,7 @@ export { Upload, } from "antd"; -export const DatePickerRangePicker = DatePicker.RangePicker; +export const DatePickerRangePicker = AntdDatePicker.RangePicker; export const ListItem = List.Item; export const MenuItemGroup = Menu.ItemGroup as React.ComponentType; diff --git a/packages/eagle/src/core/DatePicker/index.tsx b/packages/eagle/src/core/DatePicker/index.tsx new file mode 100644 index 000000000..5e9573c18 --- /dev/null +++ b/packages/eagle/src/core/DatePicker/index.tsx @@ -0,0 +1,28 @@ +import { InputStyle } from "@src/core/Styled"; +import { Typo } from "@src/core/Typo"; +import { DatePicker as AntdDatePicker } from "antd"; +import { DatePickerProps } from "antd/lib/date-picker"; +import cs from "classnames"; +import React from "react"; +const DatePicker: React.FC = ({ + className, + error, + size = "middle", + ...props +}) => { + const typo = { + large: Typo.Label.l2_regular, + middle: Typo.Label.l3_regular, + small: Typo.Label.l4_regular, + }[size]; + return ( + + ); +}; + +export default DatePicker; diff --git a/packages/eagle/src/core/Fields/FieldsDateTime/__test__/h5_css.test.tsx b/packages/eagle/src/core/Fields/FieldsDateTime/__test__/h5_css.test.tsx new file mode 100644 index 000000000..c1a093524 --- /dev/null +++ b/packages/eagle/src/core/Fields/FieldsDateTime/__test__/h5_css.test.tsx @@ -0,0 +1,821 @@ +import { render } from "@testing-library/react"; +import dayjs from "dayjs"; +import React from "react"; +import { describe, it, vi } from "vitest"; + +import FieldsDateTime from ".."; + +describe("FieldsDateTime h5_css", () => { + it("h5_css small", ({ expect }) => { + const inputName = "inputName1"; + const onBlur = vi.fn(); + const onChange = vi.fn(); + const onFocus = vi.fn(); + + const { container } = render( + , + ); + + expect({ + linaria: true, + dom: container, + }).toMatchInlineSnapshot(` +
+
.ant-input { + color: $red; + } + + &:hover, + &.__pseudo-states-hover { + border-color: $red; + box-shadow: $shadow-light-hover; + } + + &:active, + &:focus, + &.ant-input-affix-wrapper-focused, + &.__pseudo-states-active, + &.__pseudo-states-focus { + border-color: $red; + box-shadow: $shadow-light-error; + } + } + + &.ant-input-affix-wrapper.ant-input-affix-wrapper-disabled { + background: $fills-trans-terdiary-light; + color: $text-light-tertiary; + border-color: $strokes-light-trans-3; + } + + @at-root { + textarea#{&}.ant-input { + transition-property: height; + transition-delay: 50ms; + &.textarea-large { + min-height: 40px; + height: 40px; + } + &.textarea-large:focus { + height: 80px; + } + &.textarea-middle { + min-height: 32px; + height: 32px; + } + &.textarea-middle:focus { + height: 64px; + } + &.textarea-small { + min-height: 24px; + height: 24px; + } + &.textarea-small:focus { + height: 40px; + } + } + } + , + @include Inter(); + font-size: 12px; + line-height: 18px; + ,ant-picker-small + > +
+ + + + + + + + + + + +
+
+
+ `); + }); + + it("h5_css middle", ({ expect }) => { + const inputName = "inputName2"; + const onBlur = vi.fn(); + const onChange = vi.fn(); + const onFocus = vi.fn(); + + const { container } = render( + , + ); + + expect({ + linaria: true, + dom: container, + }).toMatchInlineSnapshot(` +
+
.ant-input { + color: $red; + } + + &:hover, + &.__pseudo-states-hover { + border-color: $red; + box-shadow: $shadow-light-hover; + } + + &:active, + &:focus, + &.ant-input-affix-wrapper-focused, + &.__pseudo-states-active, + &.__pseudo-states-focus { + border-color: $red; + box-shadow: $shadow-light-error; + } + } + + &.ant-input-affix-wrapper.ant-input-affix-wrapper-disabled { + background: $fills-trans-terdiary-light; + color: $text-light-tertiary; + border-color: $strokes-light-trans-3; + } + + @at-root { + textarea#{&}.ant-input { + transition-property: height; + transition-delay: 50ms; + &.textarea-large { + min-height: 40px; + height: 40px; + } + &.textarea-large:focus { + height: 80px; + } + &.textarea-middle { + min-height: 32px; + height: 32px; + } + &.textarea-middle:focus { + height: 64px; + } + &.textarea-small { + min-height: 24px; + height: 24px; + } + &.textarea-small:focus { + height: 40px; + } + } + } + , + @include Inter(); + font-size: 13px; + line-height: 20px; + ,ant-picker-middle + > +
+ + + + + + + + + + + +
+
+
+ `); + }); + + it("h5_css large", ({ expect }) => { + const inputName = "inputName2"; + const onBlur = vi.fn(); + const onChange = vi.fn(); + const onFocus = vi.fn(); + + const { container } = render( + , + ); + + expect({ + linaria: true, + dom: container, + }).toMatchInlineSnapshot(` +
+
.ant-input { + color: $red; + } + + &:hover, + &.__pseudo-states-hover { + border-color: $red; + box-shadow: $shadow-light-hover; + } + + &:active, + &:focus, + &.ant-input-affix-wrapper-focused, + &.__pseudo-states-active, + &.__pseudo-states-focus { + border-color: $red; + box-shadow: $shadow-light-error; + } + } + + &.ant-input-affix-wrapper.ant-input-affix-wrapper-disabled { + background: $fills-trans-terdiary-light; + color: $text-light-tertiary; + border-color: $strokes-light-trans-3; + } + + @at-root { + textarea#{&}.ant-input { + transition-property: height; + transition-delay: 50ms; + &.textarea-large { + min-height: 40px; + height: 40px; + } + &.textarea-large:focus { + height: 80px; + } + &.textarea-middle { + min-height: 32px; + height: 32px; + } + &.textarea-middle:focus { + height: 64px; + } + &.textarea-small { + min-height: 24px; + height: 24px; + } + &.textarea-small:focus { + height: 40px; + } + } + } + , + @include Inter(); + font-size: 14px; + line-height: 22px; + ,ant-picker-large + > +
+ + + + + + + + + + + +
+
+
+ `); + }); +}); diff --git a/packages/eagle/src/core/Fields/FieldsDateTime/index.tsx b/packages/eagle/src/core/Fields/FieldsDateTime/index.tsx index ad8111b0c..11dca54c7 100644 --- a/packages/eagle/src/core/Fields/FieldsDateTime/index.tsx +++ b/packages/eagle/src/core/Fields/FieldsDateTime/index.tsx @@ -1,16 +1,22 @@ -import { DatePicker } from "antd"; +import { DatePickerProps } from "antd/lib/date-picker"; import React from "react"; +import DatePicker from "../../DatePicker"; import { FieldBaseProps } from "../fields.type"; -const FieldsDateTime = ({ input }: FieldBaseProps) => ( +const FieldsDateTime = ({ + input, + meta, + ...props +}: FieldBaseProps & DatePickerProps) => ( <> input.onFocus?.()} - onBlur={() => input.onBlur?.()} - showTime - defaultValue={input.value} - onOk={input.onChange} + {...input} + error={ + meta.touched && + (meta.error || (!meta.dirtySinceLastSubmit && meta.submitError)) + } + {...props} /> ); diff --git a/packages/eagle/src/core/Fields/FieldsDateTimeRange/index.tsx b/packages/eagle/src/core/Fields/FieldsDateTimeRange/index.tsx index e28d1c311..4753dbe2b 100644 --- a/packages/eagle/src/core/Fields/FieldsDateTimeRange/index.tsx +++ b/packages/eagle/src/core/Fields/FieldsDateTimeRange/index.tsx @@ -1,4 +1,4 @@ -import { DatePicker } from "antd"; +import { DatePicker as AntdDatePicker } from "antd"; import { DatePickerProps } from "antd/lib/date-picker"; import moment from "moment"; import React from "react"; @@ -10,7 +10,7 @@ const FieldsDateTimeRange: React.FC = ({ ...props }) => (
- input.onFocus?.()} onBlur={() => input.onBlur?.()} showTime diff --git a/packages/eagle/src/core/index.ts b/packages/eagle/src/core/index.ts index a1c7800c6..06fbeac04 100644 --- a/packages/eagle/src/core/index.ts +++ b/packages/eagle/src/core/index.ts @@ -132,6 +132,7 @@ export { default as BytePerSecond } from "./BytePerSecond"; export { default as Calendar } from "./Calendar"; export { default as Card } from "./Card"; export { default as Checkbox } from "./Checkbox"; +export { default as DatePicker } from "./DatePicker"; export { default as DeprecatedProgress } from "./DeprecatedProgress"; export { default as DetailCard } from "./DetailCard"; export { default as DonutChart } from "./DonutChart"; diff --git a/packages/eagle/src/coreX/CronPlan/index.tsx b/packages/eagle/src/coreX/CronPlan/index.tsx index e8e3ea15f..fe41fd4f9 100644 --- a/packages/eagle/src/coreX/CronPlan/index.tsx +++ b/packages/eagle/src/coreX/CronPlan/index.tsx @@ -20,7 +20,7 @@ import { toMonthlyString, toWeeklyString, } from "@src/utils"; -import { DatePicker } from "antd"; +import { DatePicker as AntdDatePicker } from "antd"; import dayjs from "dayjs"; import { i18n as Ii18n } from "i18next"; import _ from "lodash"; @@ -660,7 +660,7 @@ const CronPlan: React.FC = (props) => { {t("components.start_date")}
- { diff --git a/packages/eagle/src/legacy-antd.tsx b/packages/eagle/src/legacy-antd.tsx index 32a6598c1..f9d910abf 100644 --- a/packages/eagle/src/legacy-antd.tsx +++ b/packages/eagle/src/legacy-antd.tsx @@ -5,7 +5,7 @@ import { Checkbox as AntdCheckbox, Col, Collapse as AntdCollapse, - DatePicker, + DatePicker as AntdDatePicker, Divider, Drawer as AntdDrawer, Dropdown, @@ -49,6 +49,7 @@ import BytePerSecond from "./core/BytePerSecond"; import Calendar from "./core/Calendar"; import Card from "./core/Card"; import Checkbox from "./core/Checkbox"; +import DatePicker from "./core/DatePicker"; import DeprecatedProgress from "./core/DeprecatedProgress"; import DetailCard from "./core/DetailCard"; import DonutChart from "./core/DonutChart"; @@ -176,7 +177,7 @@ export function getAntdKit(): Kit { checkboxGroup: AntdCheckbox.Group, typographyText: Typography.Text, upload: Upload, - datePickerRangePicker: DatePicker.RangePicker, + datePickerRangePicker: AntdDatePicker.RangePicker, tableForm: TableForm, token: Token, statusCapsule: StatusCapsule, diff --git a/packages/eagle/src/spec/base.ts b/packages/eagle/src/spec/base.ts index 49420340c..ff0cbb293 100644 --- a/packages/eagle/src/spec/base.ts +++ b/packages/eagle/src/spec/base.ts @@ -329,7 +329,7 @@ export interface Kit { uploadDragger: React.ComponentType; calendar: CalendarComponentType; timePicker: React.FC; - datePicker: React.ComponentType; + datePicker: React.FC; tabs: React.FC; tabsTabPane: React.FC; antdBadge: React.FC; diff --git a/packages/eagle/stories/docs/core/DatePicker.stories.tsx b/packages/eagle/stories/docs/core/DatePicker.stories.tsx new file mode 100644 index 000000000..dc99ae12b --- /dev/null +++ b/packages/eagle/stories/docs/core/DatePicker.stories.tsx @@ -0,0 +1,44 @@ +import DatePicker from "@src/core/DatePicker"; +import { CoreMeta } from "@stories/types"; +import { StoryObj } from "@storybook/react"; +import React from "react"; + +/** + * * antd4 组件 + * * 更多 props 请参考:https://4x.ant.design/components/date-picker-cn/#API + * * 自定义 props 已在表格进行说明 + */ +const meta = { + component: DatePicker, + title: "Core/DatePicker | 表单日期选择", + parameters: { + design: { + type: "figma", + url: "", + }, + }, +} satisfies CoreMeta; + +export default meta; + +type Story = StoryObj; + +/** + * * 基础用法 + */ +export const baseFieldsDateTime: Story = { + name: "基础用法", + render: () => { + return ; + }, +}; + +/** + * * error 状态 + */ +export const errorFieldsDateTime: Story = { + name: "error 状态", + render: () => { + return ; + }, +};