@fiscozen/ 日期选择器
关于使用情况文件,见 故事书文档。 。 。 .
发展
设置
pnpm install
pnpm --filter @fiscozen/datepicker build
运行测试
pnpm --filter @fiscozen/datepicker test:unit
pnpm --filter @fiscozen/datepicker coverage
覆盖率阈值 vitest.config.ts数字 : 80%的语句、75%的分支、80%的功能、80%的行。快照ID通过自定义序列器在 src/__tests__/FzDatepicker.spec.ts 因此,添加/删除测试不会漂移无关的快照.
当对内人说: <VueDatePicker> 首选项 (wrapper.vm as any).$.setupState.mappedProps 结束 dp.props(...): VueDatePicker 用户 defineModel + 键 v-bind 扩散使得Vue Test Utils的道具反射不可靠.
运行故事本
pnpm --filter @fiscozen/storybook dev
建筑
FzDatepicker是一个浅薄的包装器周围 @vuepic/vue-datepicker 五进制12。包装器补充:
- 费斯克森品牌造型 通过全局(无范围) CSS 覆盖
.dp__*类 - FzInput 整合 将默认输入槽替换为
FzInput - 分槽转发 (单位:千美元)
errorMessage, (中文(简体) ),helpText从FzDatepicker到内FzInput - 遗产 v8 道具映射 所以消费者不需要更新他们的代码 在v8 – v12迁移之后
- 远程传送正常化 确保日历菜单在模式/对话框内正确制作
取时器 UI 使用 VueDatePicker 的默认渲染,所以道具喜欢 hoursIncrement, (中文(简体) ), minutesIncrement, (中文(简体) ), minTime, (中文(简体) ), maxTime, (中文(简体) ), disabledTimes, (中文(简体) ), startTime,以及 is24: false (AM/PM) 上游工作记录.
为什么全球CSS
这个 <style> 块是故意的 非范围VueDatePicker 将日历菜单传送到 <body> 默认情况下,范围化的样式不会到达传送到的DOM。 全体 .dp__* 覆盖必须是全球性的.
代码组织
src/
├── FzDatepicker.vue # Main component (script → template → style)
├── types.ts # FzDatepickerProps interface extending VueDatePicker's RootProps
├── index.ts # Public exports
└── __tests__/
├── FzDatepicker.spec.ts # Unit tests
└── __snapshots__/ # Vitest snapshots
关键概念
稳定次级目标(参考稳定性)
VueDatePicker v12 内部监视某些子对象道具(例如. floating, (中文(简体) ), formats, (中文(简体) ), timeConfig) (中文(简体) ). 如果在每个渲染物上传递出一款新的对象参考物——即使内容相同,它也触发了不必要的再计算,可以表现为相克或布局相克.
为了防止这种情况,该组件使用单个纪念 computed 属性( e)stableFormats, (中文(简体) ), stableLocale, (中文(简体) ), stableFloating, (中文(简体) ), stableTextInput, (中文(简体) ), stableInputAttrs, (中文(简体) ), stableTimeConfig, (中文(简体) ), stableFlow返回该 同样的参考文献 当只有无关道具时(例如. modelValue) 变化。 然后把这些组装成 mappedProps。 。 。 .
遗产道具绘图(v8-v12)
这个 mappedProps 以透明方式计算地产, 将 v8 等式的 scalar 道具降为 v12 等式 :
| v8 推进 | v12 等价键 |
|---|---|
format | formats.input |
formatLocale | locale |
autoPosition | floating |
placement | floating.placement |
state | inputAttrs.state |
name | inputAttrs.name |
enableTimePicker, (中文(简体) ), enableMinutes, (中文(简体) ), is24等 (中文(简体) ). | timeConfig.* |
flow (阵列) | flow.steps |
所有遗留道具都标记了 @deprecated 内 types.ts 并将在未来的版本中删除.
远程传送规范化
Vue 3的布尔铸造规则会导致 <FzDatepicker teleport /> 以通过空字符串 "" 到 VueDatePicker 当道具类型包含两者时 String 财务报告和审定财务报表 Boolean。该组件在 mappedProps数字 :
true或者说""→"body"false或者说null• 完全去除道具(没有传送口)- 明确字符串(例如:.
"#container"——通过现在
默认是 "body",确保日历总是使外溢的容器隐藏.
传送槽( 错误和帮助文本)
FzDate 有条件地向前 errorMessage 财务报告和审定财务报表 helpText fzInput内部的插槽。 转发使用 v-if="$slots.slotName" 守卫,使FzInput只看到FzDatepicker的消费者实际提供时的插槽. 没有这些警卫 FzInput的 $slots.helpText 检查总是真实的( 因为模板已经存在) , 导致每个实例都出现空帮助文本跨度 .
这一模式采用的方法与 FzCurrencyInput。 。 。 .
浮动键( 强制重载)
VueDatePicker 读取 floating.placement 设置期间一次并传递纯值(不是参考值)到 useFloating。为了使位置变化具有反应性,组件通过 :key="floatingKey" 当浮动配置改变时.
添加特性
步骤1:更新类型
添加新道具到 FzDatepickerProps 内 src/types.ts 与联合来文文件.
第2步:在绘图中处理
如果新道具在通过 VueDatePicker 之前需要重印或排除,请更新 mappedProps 计算 FzDatepicker.vue。 。 。 .
步骤 3: 更新模板
如果新道具直接影响到UI,则添加模板绑定.
第4步:添加测试
写入单位测试 src/__tests__/FzDatepicker.spec.ts. 由 vitest.config.ts数字 : 80%的语句、75%的分支、80%的功能、80%的行. 目标更高的新代码,特别是围绕事件排放和道具映射.
当对里面的VueDatePicker主张时,偏好 setupState.mappedProps 结束 dp.props(...): VueDatePicker 软件 defineModel + 键 v-bind 传播使得"Vue Test Utils"的道具反射不可靠. 这个 mappedProps 计算就是我们真正经过的 v-bind="mappedProps",所以测试是等同的.
步骤5:更新故事
添加或更新故事书故事 apps/storybook/src/stories/form/Datepicker.stories.ts 具有游戏功能.
步骤6:更新文档
更新 MDX 文件 apps/storybook/src/FzDatepicker.mdx 包括用法实例.
设计决定
为什么要用"分叉"代替"分叉"
Wrapping VueDatePicker保留了对其丰富的特性集(120+道具)的访问,同时允许我们控制了造型,输入集成,以及API表面. 伪造需要保持取出日期的核心逻辑.
为什么遗产主张
VueDatePicker的v8 → v12迁移引入了显著的API变化. 为了避免所有消费者的移民中断,包装器透明地绘制出旧道具. 留下的道具有标记 @deprecated 并将在未来的主要版本中删除.
为什么没有范围CSS
日历菜单被传送到 <body>。扩展样式将产生 [data-v-xxx] 属性选择器不匹配传送到的 DOM 元素。 全球支助服务是唯一可行的办法.
解决问题
日历显示“ 关闭 ” 在 Modal 内
保证 teleport 设置为 "body" (默认). 如果你通过了 teleport 作为布尔属性( r)<FzDatepicker teleport />),自动正常化为 "body"。 。 。 .
程序更改上的日历闪烁器
检查您是否没有在像道具这样的每次渲染上创建新的对象引用 floating, (中文(简体) ), formats,或 timeConfig。组件通过稳定的计算属性进行内部处理,但如果覆盖 mappedProps 或直接绑定子对象道具,确保参考稳定性.
位置不更新
VueDatePicker 读取 floating.placement 一次在设置期间。 该组件绕着它工作,通过 :key如果放置仍未更新,请检查 placement 道具是反应性的(一个回放或计算,而不是一个不会改变的平板字符串).
依赖关系
同伴依赖关系 :
vue: ^3.4.13 (中文(简体) )@fiscozen/icons: 工作空间:^tailwindcss页:1
运行时间依赖 :
@vuepic/vue-datepicker: ^12.1.0 — 基本的取日期引擎date-fns: ^4.1.0 - (中文(简体) )Locale对象+format()用于valueFormat@fiscozen/button:工作空间 -FzButton(动作按钮"Cancella" /"Seleziona",继承inputProps.environment(中文(简体) )@fiscozen/icons:工作空间 -FzIcon(日历/覆盖导航箭头,内置取时器chevrons,时钟/日历图标)@fiscozen/input:工作空间 -FzInput由VueDatePicker公司制造#dp-input插槽@fiscozen/composables:工作空间 -useBreakpoints(移动探测)@fiscozen/style: 工作空间——断点符和CSS变量
全体 @fiscozen/* 软件包被声明为 external 内 vite.config.ts,因此它们不会被捆绑,消费者在安装时会收到一份副本.
已知的限制
- 语言字符串强制: 通过
locale: 'en'(或任何其他地盘) 被无声地胁迫给意大利人date-fns语言对象 。 VueDatePicker v12 期望一个Locale对象;遗留的字符串形式只保留后向相容性. 对于非意大利人的案件,通过真实的date-fns地语( 如.import { enGB } from 'date-fns/locale') (中文(简体) ). name原则优先是逆向的对JSDoc意图: 遗产顶层name道具获胜inputAttrs.name(V12型API). 记录在types.tsJSDoc;优先级会翻到v4.0.0.- 自定义仅通过掉入发送: 宣布的若干事件
defineEmits(单位:千美元)internal-model-change, (中文(简体) ),am-pm-change, (中文(简体) ),range-start/end, (中文(简体) ),tooltip-*FzDatepicker没有直接排放——它们从<VueDatePicker>通过Vue的属性下降。 它们为消费者服务,但不能孤立地检验wrapper.emitted()。 。 。 . - 只有意大利语的动作按钮: 默认
#action-buttons槽使"Cancella" /"Seleziona"硬编码. 需要其他语言的消费者必须超过该槽. - 默认的意大利方位标签:FzDatepicker通过一个完整的意大利语
ariaLabels映射到 VueDatePicker 。 消费者可通过下列方式推翻单个键(或本地化为另一种语言)ariaLabelsprop – 价值被合并为一键,消费者获胜. - 快照测试不覆盖传送到的菜单: VueDatePicker 将其日历传送到
<body>· ;wrapper.html()只抓取输入包。 日历内部通过故事本游戏功能行使端到端.